├── .editorconfig ├── .gitignore ├── .gitmodules ├── .tm_properties ├── .travis.yml ├── BUGS ├── CHANGELOG-pandoc ├── CHANGELOG.md ├── CONTRIBUTING.md ├── COPYING ├── COPYRIGHT ├── INSTALL.md ├── Interact.hs ├── Makefile ├── README-pandoc ├── README.md ├── Setup.hs ├── benchmark └── benchmark-scholdoc.hs ├── data ├── LaTeXMathML.js ├── MathMLinHTML.js ├── dzslides │ └── template.html ├── reference.docx └── sample.lua ├── deb └── control.in ├── github-upload.sh ├── make_deb.sh ├── make_osx_package.sh ├── osx ├── distribution.xml └── uninstall-pandoc.pl ├── scholdoc.cabal ├── scholdoc.hs ├── src └── Text │ ├── Pandoc.hs │ └── Pandoc │ ├── Asciify.hs │ ├── Compat │ ├── Directory.hs │ ├── Except.hs │ ├── Locale.hs │ ├── Monoid.hs │ └── TagSoupEntity.hs │ ├── Data.hsb │ ├── Highlighting.hs │ ├── ImageSize.hs │ ├── MIME.hs │ ├── MediaBag.hs │ ├── Options.hs │ ├── PDF.hs │ ├── Parsing.hs │ ├── Pretty.hs │ ├── Process.hs │ ├── Readers │ ├── HTML.hs │ ├── LaTeX.hs │ ├── Markdown.hs │ ├── Native.hs │ └── TeXMath.hs │ ├── Scholarly.hs │ ├── SelfContained.hs │ ├── Shared.hs │ ├── Slides.hs │ ├── Templates.hs │ ├── UTF8.hs │ ├── UUID.hs │ ├── Writers │ ├── Custom.hs │ ├── Docx.hs │ ├── HTML.hs │ ├── Haddock.hs │ ├── LaTeX.hs │ ├── Man.hs │ ├── Markdown.hs │ ├── Native.hs │ └── Shared.hs │ └── XML.hs ├── tests ├── Tests │ ├── Arbitrary.hs │ ├── Helpers.hs │ ├── Old.hs │ ├── Readers │ │ ├── LaTeX.hs │ │ └── Markdown.hs │ ├── Shared.hs │ ├── Walk.hs │ └── Writers │ │ ├── HTML.hs │ │ ├── LaTeX.hs │ │ ├── Markdown.hs │ │ ├── Native.hs │ │ └── Plain.hs ├── bodybg.gif ├── docx │ ├── image_vml.docx │ └── image_vml.native ├── dokuwiki_external_images.dokuwiki ├── dokuwiki_external_images.native ├── insert ├── lalune.jpg ├── lhs-test-markdown.native ├── lhs-test.html ├── lhs-test.html+lhs ├── lhs-test.latex ├── lhs-test.latex+lhs ├── lhs-test.markdown ├── lhs-test.markdown+lhs ├── lhs-test.native ├── markdown-citations.native ├── markdown-citations.txt ├── markdown-reader-more.native ├── markdown-reader-more.txt ├── movie.jpg ├── pipe-tables.native ├── pipe-tables.txt ├── s5-basic.html ├── s5-fancy.html ├── s5-fragment.html ├── s5-inserts.html ├── s5.native ├── scholdoc.html ├── scholdoc.latex ├── scholdoc.native ├── scholdoc.txt ├── tables-rstsubset.native ├── tables.haddock ├── tables.html ├── tables.latex ├── tables.man ├── tables.markdown ├── tables.native ├── tables.plain ├── tables.txt ├── test-scholdoc.hs ├── testsuite.native ├── testsuite.txt ├── writer.haddock ├── writer.html ├── writer.latex ├── writer.man ├── writer.markdown ├── writer.native └── writer.plain ├── tryscholdoc ├── index.html └── tryscholdoc.hs └── windows ├── COPYING.rtf ├── make-windows-installer.bat └── scholdoc.wxs /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.{markdown,md}] 12 | trim_trailing_whitespace = false 13 | 14 | [tests/*] 15 | insert_final_newline = false 16 | trim_trailing_whitespace = false 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | dist/* 3 | README.* 4 | !README.Debian 5 | INSTALL.* 6 | .configure-stamp 7 | .cabal-sandbox 8 | cabal.sandbox.config 9 | pandoc.cabal.orig 10 | man/man?/*.1 11 | man/man?/*.5 12 | man/man?/*.html 13 | *.diff 14 | *.o 15 | *.hi 16 | *.pyc 17 | /COPYING.rtf 18 | /COPYRIGHT.txt 19 | /cabal-dev/ 20 | /windows/*.msi 21 | /windows/*.wixpdb 22 | windows/*.wixobj 23 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "templates"] 2 | path = data/templates 3 | url = https://github.com/timtylin/scholdoc-templates.git 4 | branch = master 5 | -------------------------------------------------------------------------------- /.tm_properties: -------------------------------------------------------------------------------- 1 | tabSize = 2 2 | excludeInFolderSearch = "{$excludeInFolderSearch,$extraExcludes,dist}" 3 | 4 | [ source.haskell ] 5 | softWrap = false 6 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # NB: don't set `language: haskell` here 2 | 3 | # The following enables several GHC versions to be tested; often it's enough to test only against the last release in a major GHC version. Feel free to omit lines listings versions you don't need/want testing for. 4 | env: 5 | # - GHCVER=6.12.3 6 | - GHCVER=7.4.2 7 | - GHCVER=7.6.3 8 | - GHCVER=7.8.2 # see note about Alex/Happy 9 | # - GHCVER=head # see section about GHC HEAD snapshots 10 | 11 | # Note: the distinction between `before_install` and `install` is not important. 12 | before_install: 13 | - travis_retry sudo add-apt-repository -y ppa:hvr/ghc 14 | - travis_retry sudo apt-get update 15 | - travis_retry sudo apt-get install cabal-install-1.18 ghc-$GHCVER 16 | - export PATH=/opt/ghc/$GHCVER/bin:$PATH 17 | 18 | install: 19 | - cabal-1.18 update 20 | # - git clone https://github.com/jgm/pandoc-types && cd pandoc-types && cabal-1.18 install && cd .. 21 | - cabal-1.18 install --only-dependencies --enable-tests 22 | 23 | # Here starts the actual work to be performed for the package under test; any command which exits with a non-zero exit code causes the build to fail. 24 | script: 25 | - cabal-1.18 configure --enable-tests -v2 # -v2 provides useful information for debugging 26 | - cabal-1.18 build --ghc-options=-Werror # this builds all libraries and executables (including tests/benchmarks) 27 | - cabal-1.18 test 28 | - cabal-1.18 check 29 | -------------------------------------------------------------------------------- /BUGS: -------------------------------------------------------------------------------- 1 | Scholdoc is fork of Pandoc. While additional capabilities have been added to recognize and output ScholarlyMarkdown-specific features, Scholdoc strives to use most of Pandoc's original code. If you encounter a bug that is not related to features specific to ScholarlyMarkdown, please first check to see if it is already reported in Pandoc's issue tracker , or on the official Pandoc discussion group . 2 | 3 | If you feel confident that a bug is directly related to ScholarlyMarkdown features, you can file a report in the Scholdoc issue tracker: . 4 | 5 | Any bugs that are also deemed to impact Pandoc itself will be referred to Pandoc's issue tracker. The official policy is to merge in the fixes only after it has been made in Pandoc. 6 | 7 | See also CONTRIBUTING.md. 8 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | Scholdoc changelog 2 | ================== 3 | 4 | All notable changes to Scholdoc will be documented in this file. 5 | 6 | This log pertains to Scholdoc development **only**. Pandoc's changelog can be found in the `changelog-pandoc` file. 7 | 8 | Scholdoc's version numbers reflect Scholdoc changes only, and does not necessarily correspond to Pandoc's version number. Scholdoc strives to track the latest official Pandoc release. Whenever new Pandoc commits are merged into Scholdoc, it will be noted in the changelog below. 9 | 10 | Scholdoc follows semantic versioning with regards to its output schema. 11 | 12 | ## 0.1.3-alpha - 2014-10-15 13 | 14 | **Note:** *This version largely consists of major cleanups under the hood. It bring the development of Scholdoc up-to-date with the latest Pandoc development version, and removed many unnecessary source files related to unused reader/writers.* 15 | 16 | ### Added 17 | - The Pandoc-derived portion of Scholdoc is now up to date with Pandoc 1.13.1 (commit 8b60d430) 18 | - The build-chain of Scholdoc have been cleaned-up and is now ready for production. Running `make deps && make install` under the source directory now fully builds using its own `scholdoc-types` and `scholdoc-texmath` packages. 19 | - Updated documentation to reflect the Scholdoc project: README.md, CONTRIBUTING.md, BUGS, COPYRIGHT 20 | 21 | ### Changed 22 | - Scholdoc now looks for custom template files under the `~/.scholdoc/` directory, instead of `~/.pandoc` 23 | - The "--no-standalone" option no longer imply "_bodyOnly" writers. Instead "--no-standalone" now strictly stops all template usage. 24 | 25 | ## 0.1.2-alpha - 2014-09-09 26 | 27 | ### Added 28 | - Allow rudimentary Docx output, although most Scholmd elements map to empty 29 | 30 | ### Changed 31 | - The program name is changed from `scholpandoc` to `scholdoc` to more accurately reflect the limited input/output options compared to Pandoc. 32 | 33 | #### HTML output 34 | - Uses HTTPS instead of protocol-relative URLs for default polyfills in the template from CDNJS. This will make previewing local HTML files much easier. 35 | - Default MathJax CDN URL is also changed to the HTTPS protocol 36 | - Added an additional variable `html-header-includes` for inclusion of HTML-specific header tags. This can be specified in YAML metadata blocks, and will be treated as an unformatted string. 37 | 38 | #### LaTeX output 39 | - Added `indentparagraphs` variable to template, so you can change between "no indent/line-height paragraph margins" and "indent/no paragraph margins" 40 | - Added variables `natbib-options` and `biblatex-options` to specify loading options for these citation packages 41 | - Added additional variables to the template for more flexibility in "injection" of custom LaTeX code without resorting to a separate template: 42 | - `latex-before-documentclass-includes` 43 | - `latex-before-packages-includes` 44 | - `latex-after-packages-includes` 45 | - `latex-header-includes` 46 | - `latex-after-body-includes` 47 | - `latex-after-document-includes` 48 | - *All the above variable can be specified in YAML metadata blocks, and will be treated as unformatted strings (along with `geometry`)* 49 | 50 | ## 0.1.1-alpha - 2014-05-30 51 | 52 | ### Added 53 | - Allow output of JSON-style native format 54 | 55 | ### Changed 56 | 57 | #### LaTeX output 58 | - No longer hard-codes the `htbp` placement of floats. This is now controlled in the template using the `Float` package. 59 | 60 | ### Fixed 61 | - Fixed a bug where figures/floats display captions prefixes when it is not needed 62 | 63 | ## 0.1.0-alpha - 2014-04-22 64 | 65 | ### Changed 66 | 67 | #### HTML output 68 | - Conforms to ScholarlyMarkdown HTML5 Schema 0.1 69 | 70 | ### Fixed 71 | - The `bibliography` metadata is now treated like a pure string and will not be formatted 72 | - Display math and figure/floats now properly parses if delimiters have multiple trailing whitespaces 73 | - Disabling standalone mode using `_bodyonly` suffix now works again 74 | - Minor code cleanup using `hlint`, refactored various writer monads for floats 75 | 76 | ## 0.0.1-alpha - 2014-03-16 77 | 78 | ### Added 79 | - Display math equations that uses the class `math_def` instead of `math` are now appended to a global variable called `$math-macros$`. In the updated templates this is placed in the header, and enables LaTeX declarations that only work in the header 80 | 81 | ### Changed 82 | - ScholarlyPandoc now has the following arguments enabled by default: `-f markdown_scholarly --smart --parse-raw --standalone`. Renaming the executable to anything other than `scholpandoc` reverts this behavior 83 | 84 | ### Fixes 85 | - Fixed a bug where templates files are not compiled into the binary, resulting in complaints about "can't find file ..." 86 | 87 | ## 0.0.0-alpha - 2014-03-14 88 | 89 | Initial Release 90 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Contributing to Scholdoc 2 | ======================== 3 | 4 | Official Scholdoc repository address on GitHub: 5 | 6 | https://github.com/timtylin/scholdoc 7 | 8 | Had a sudden inspiration? 9 | ------------------------- 10 | 11 | If you have an awesome idea for Scholdoc, great! You should probably discuss it on the ScholarlyMarkdown discussion forum, so others will have a chance to weigh in. 12 | 13 | If your idea is related to the syntax, design, or convention prescribed by ScholarlyMarkdown itself, and concerns changes that would affect all implementations, please talk about it in the Syntax category: 14 | 15 | http://forum.scholarlymarkdown.com/category/syntax 16 | 17 | If you have suggestions concerning the *behavior* of Scholdoc itself, such as default settings or command-line options, use the Scholdoc category instead: 18 | 19 | http://forum.scholarlymarkdown.com/category/implementations/scholdoc 20 | 21 | 22 | Have you found a bug? 23 | --------------------- 24 | 25 | If you feel confident that a bug is directly related to ScholarlyMarkdown features, you can file a report in the Scholdoc issue tracker: 26 | 27 | https://github.com/timtylin/scholdoc/issues 28 | 29 | Before submitting a bug report, please search all issued (both open *and* closed) to make sure it is not a duplicate issue. 30 | 31 | Your report should give detailed instructions for how to reproduce the problem, 32 | including 33 | 34 | * the exact command line used 35 | * the exact input used 36 | * the output received 37 | * the output you expected instead 38 | 39 | A small test case (just a few lines) is ideal. If your input is large, 40 | try to whittle it down to the minimum necessary to illustrate the problem. 41 | 42 | If the issue does not reflect an obvious programming bug, but instead an 43 | undesired behavior, the policy is to aggressively close the issue and move the 44 | discussion to the forum instead (see above). The goal is to ensure that 45 | important discussion concerning potential improvements do not get lost in the 46 | bug tracker. 47 | 48 | Any bugs that are also deemed to impact Pandoc itself will be referred to 49 | Pandoc's issue tracker. The official policy is to merge in the fixes only after 50 | it has been made in Pandoc. 51 | 52 | The README file will always describe the latest version of improvement to Pandoc 53 | that have been merged into Scholdoc. This information will also be reflected in the changelog. 54 | 55 | Pull requests 56 | ------------- 57 | 58 | Pull requests without an associated issue ticket or discussion on the forum are welcome for bugs and trivial fixes (such as documentation). 59 | 60 | All other pull request will be considered, but not necessarily followed-up on. It is very possible that you will be asked to discuss the pull request first on the forum. 61 | 62 | All pull requests are expected to meet the [guidelines laid out for Pandoc][pandoc-pr-guidelines]. 63 | 64 | Technical details 65 | ----------------- 66 | 67 | All bug fixes and pull requests are requested to provide appropriate addition to the test cases. For information on running tests, as well as the general library structure of Scholdoc, please refer to the [contribution guide for Pandoc][pandoc-contrib-tech]. 68 | 69 | 70 | [pandoc-pr-guidelines]: http://johnmacfarlane.net/pandoc/CONTRIBUTING.html#patches-and-pull-requests 71 | [pandoc-contrib-tech]: http://johnmacfarlane.net/pandoc/CONTRIBUTING.html#tests 72 | -------------------------------------------------------------------------------- /COPYRIGHT: -------------------------------------------------------------------------------- 1 | Scholdoc 2 | Copyright (C) 2014 Tim T.Y. Lin 3 | 4 | This code is released under the [GPL], version 2 or later: 5 | 6 | This program is free software; you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | 20 | The GNU General Public License is available in the file COPYING in 21 | the source distribution. On Debian systems, the complete text of the 22 | GPL can be found in `/usr/share/common-licenses/GPL`. 23 | 24 | Scholdoc's complete source code is available on [Github][scholdoc repo]. 25 | 26 | [GPL]: http://www.gnu.org/copyleft/gpl.html 27 | [scholdoc repo]: https://github.com/timtylin/scholdoc 28 | 29 | ---------------------------------------------------------------------- 30 | Scholdoc is a fork of: 31 | 32 | Pandoc 33 | Copyright (C) 2006-2014 John MacFarlane 34 | 35 | Released under the GNU General Public License version 2 or later. 36 | 37 | Pandoc's complete source code is available from the [Pandoc home page]. 38 | 39 | [Pandoc home page]: http://johnmacfarlane.net/pandoc/ 40 | 41 | Pandoc includes some code from other authors. The copyright and license 42 | statements for these sources are included below. All are GPL-compatible 43 | licenses. 44 | 45 | ---------------------------------------------------------------------- 46 | src/Text/Pandoc/Writers/Texinfo.hs 47 | Copyright (C) 2008-2014 John MacFarlane and Peter Wang 48 | 49 | Released under the GNU General Public License version 2 or later. 50 | 51 | ---------------------------------------------------------------------- 52 | src/Text/Pandoc/Writers/OpenDocument.hs 53 | Copyright (C) 2008-2014 Andrea Rossato and John MacFarlane 54 | 55 | Released under the GNU General Public License version 2 or later. 56 | 57 | ---------------------------------------------------------------------- 58 | src/Text/Pandoc/Writers/Org.hs 59 | Copyright (C) 2010-2014 Puneeth Chaganti and JohnMacFarlane 60 | 61 | Released under the GNU General Public License version 2 or later. 62 | 63 | ---------------------------------------------------------------------- 64 | src/Text/Pandoc/Readers/Textile.hs 65 | Copyright (C) 2010-2014 Paul Rivier and John MacFarlane 66 | 67 | Released under the GNU General Public License version 2 or later. 68 | 69 | ---------------------------------------------------------------------- 70 | src/Text/Pandoc/Readers/Org.hs 71 | tests/Tests/Readers/Org.hs 72 | Copyright (C) 2014 Albert Krewinkel 73 | 74 | Released under the GNU General Public License version 2 or later. 75 | 76 | ---------------------------------------------------------------------- 77 | data/LaTeXMathML.js 78 | Adapted by Jeff Knisely and Douglas Woodall from 79 | ASCIIMathML.js v. 1.4.7 80 | Copyright (C) 2005 Peter Jipsen 81 | 82 | Released under the GNU General Public License version 2 or later. 83 | 84 | ---------------------------------------------------------------------- 85 | data/MathMLinHTML.js 86 | Copyright (C) 2004 Peter Jipsen http://www.chapman.edu/~jipsen 87 | 88 | Released under the GNU General Public License version 2 or later. 89 | 90 | ------------------------------------------------------------------------ 91 | The dzslides template contains javascript and CSS from Paul Rouget's 92 | dzslides template. 93 | http://github.com/apulrouget/dzslides 94 | 95 | Released under the Do What the Fuck You Want To Public License. 96 | -------------------------------------------------------------------------------- /Interact.hs: -------------------------------------------------------------------------------- 1 | -- Get an interactive shell with the right packages to load 2 | -- pandoc modules. 3 | 4 | -- To use: 5 | -- runghc Interact.hs 6 | -- then, 7 | -- :l Text/Pandoc.hs 8 | -- (or whichever package you like) 9 | 10 | -- You must have first done a 'cabal configure' or 'cabal install' 11 | 12 | -- Note: Interact.hs doesn't work with Cabal >= 1.18. I recommend 13 | -- using cabal sandboxes and the new 'cabal repl' command if you are 14 | -- using a recent version. 15 | 16 | import System.Process 17 | import Distribution.Simple.LocalBuildInfo 18 | import Distribution.Package 19 | import Distribution.Version 20 | import Data.List (intercalate) 21 | 22 | main = do 23 | setupConfig' <- readFile "dist/setup-config" 24 | let setupConfig = read $ unlines $ drop 1 $ lines setupConfig' 25 | let (Just (ComponentLocalBuildInfo { componentPackageDeps = deps })) = libraryConfig setupConfig 26 | let packageSpecs = map (toPackageSpec . snd) deps 27 | let args = ["-optP-include", "-optP../dist/build/autogen/cabal_macros.h","-cpp","-I../dist/build/autogen","-i../dist/build/autogen"] ++ concatMap (\p -> ["-package",p]) packageSpecs 28 | print args 29 | ph <- runProcess "ghci" args (Just "src") Nothing Nothing Nothing Nothing 30 | waitForProcess ph 31 | 32 | toPackageSpec pkg = pkgN ++ "-" ++ pkgV 33 | where (PackageName pkgN) = pkgName pkg 34 | pkgV = intercalate "." $ map show $ versionBranch $ pkgVersion pkg 35 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | version=$(shell grep '^Version:' scholdoc.cabal | awk '{print $$2;}') 2 | CABALARGS=--enable-tests --disable-optimization -ftryscholdoc -fembed_data_files --enable-benchmarks 3 | 4 | quick: 5 | cabal configure --enable-tests --disable-optimization 6 | cabal build 7 | 8 | full: 9 | cabal configure --enable-tests --enable-optimization -ftryscholdoc -fembed_data_files --enable-benchmarks 10 | cabal build 11 | cabal haddock 12 | 13 | deps: 14 | cabal install --only-dependencies --enable-tests -ftryscholdoc -fembed_data_files --enable-benchmarks 15 | 16 | prof: 17 | cabal configure --enable-library-profiling --enable-executable-profiling --enable-optimization --enable-tests 18 | cabal build 19 | 20 | test: 21 | cabal test 22 | 23 | bench: 24 | cabal bench 25 | 26 | install: full 27 | cabal copy 28 | cabal register 29 | 30 | dist: 31 | cabal sdist 32 | rm -rf "scholdoc-${version}" 33 | tar xvzf dist/scholdoc-${version}.tar.gz 34 | cd scholdoc-${version} 35 | cabal configure ${CABALARGS} && cabal build && cabal test && cd .. && rm -rf "scholdoc-${version}" 36 | 37 | debpkg: 38 | ./make_deb.sh 39 | 40 | osxpkg: 41 | ./make_osx_package.sh 42 | 43 | unuseddeps: # finds redundant Cabal package dependencies, requires `packunused` 44 | cabal configure --enable-tests --enable-benchmarks -ftryscholdoc -fembed_data_files --disable-optimization 45 | cabal build --ghc-option="-ddump-minimal-imports" 46 | packunused 47 | 48 | clean: 49 | cabal clean 50 | 51 | .PHONY: deps quick full install clean test bench haddock osxpkg debpkg dist prof unuseddeps 52 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Scholdoc 2 | ======== 3 | 4 | ### Converts [ScholarlyMarkdown][scholmd] documents into HTML5, LaTeX, or Docx 5 | 6 | **Current stable version:** 0.1.4 7 | 8 | **Development build status** [![build status][scholarly-devel-travisimage]][travis_stat] 9 | **Stable build status** [![build status][scholarly-travisimage]][travis_stat] 10 | 11 | **Scholdoc** is a command-line utility that converts 12 | [ScholarlyMarkdown][scholmd] documents into the HTML5, LaTeX, and Docx (OOML) 13 | formats. It is intended to facilitate academic writing in a cross-platform, 14 | semantic-aware, plaintext format that can be quickly used in modern publishing 15 | pipelines. 16 | 17 | You can test the HTML and LaTeX output of Scholdoc on small (limited to 10,000 18 | characters) [ScholarlyMarkdown][scholmd] snippets using the online 19 | [Dingus][dingus]. 20 | 21 | Scholdoc is implemented as fork of [Pandoc][pandoc], and mostly retains the 22 | same user interface (including the custom [template][pandocTemplate] and 23 | [filter][pandocFilters] system). It essentially understands a new input format 24 | `markdown_scholarly` (implemented in the markdown reader a superset of 25 | `markdown_pandoc` features), and limits itself to HTML5/LaTeX/Docx output. 26 | Scholdoc defaults to `standalone` output and has its own [custom 27 | templates][scholdoc-templates] to ensure output compatibility with 28 | [ScholarlyMarkdown][scholmd]. 29 | 30 | See the [Pandoc Guide][pandocReadme] for more about Pandoc, its usage, and the 31 | Markdown dialect that Pandoc (and hence Scholdoc) [understands][pandocMarkdown]. 32 | 33 | Scholdoc is currently up to date with [Pandoc][pandoc] version 1.13.2 (up to commit fb7a03dcda) 34 | 35 | ### Installing Scholdoc 36 | 37 | #### Via Homebrew (OS X only) 38 | 39 | On OS X, the easiest way to obtain Scholdoc is from the official 40 | [Homebrew][Homebrew] [tap][homebrew-scholdoc]. First make sure you have 41 | [Homebrew][Homebrew] set-up correctly on your system, and that running `brew 42 | doctor` gives you no serious warnings. After that, run the following: 43 | 44 | brew tap timtylin/scholdoc 45 | brew update 46 | brew install scholdoc scholdoc-citeproc 47 | 48 | To upgrade to the latest release, just run 49 | 50 | brew update 51 | brew upgrade scholdoc scholdoc-citeproc 52 | 53 | #### Via pre-built binary distribution 54 | 55 | Pre-built binary distributions exist for some platforms. Check the [download][scholdoc-download] page to see the list of available builds. 56 | 57 | #### Compile via Hackage (all operating systems) 58 | 59 | Scholdoc is written in pure Haskell. It requires the [GHC] compiler and the 60 | [cabal-install] build system. The easiest way to get it on all platforms is by 61 | installing the [Haskell platform] for your operating system. Please make sure 62 | you are using GHC version 7.4 or above. 63 | 64 | If you are using Ubuntu, Herbert V. Riedel have conveniently provided a [PPA of 65 | pre-compiled GHC and cabal-install][hvr-PPA] for recent Ubuntu systems. Here's 66 | an example of how to get recommended versions of [GHC] and [cabal-install] 67 | using `apt-get` 68 | 69 | sudo add-apt-repository ppa:hvr/ghc 70 | sudo apt-get update && sudo apt-get install ghc-7.8.3 cabal-install-1.20 71 | 72 | Once you have GHC and `cabal-install` on your system, run the following 73 | 74 | cabal update 75 | cabal install scholdoc 76 | cabal install scholdoc-citeproc 77 | 78 | To upgrade to the latest release of Scholdoc, just run the above three commands 79 | again. 80 | 81 | ### HTML output 82 | 83 | ***Important:*** *A ScholarlyMarkdown [core CSS][corecss] is required for proper 84 | formatting of most HTML files output by Scholdoc.* 85 | 86 | Scholdoc's HTML output is strictly limited to HTML5 due to its enhanced 87 | semantic capabilities (such as the `figure` and `figcaption` element), and 88 | relies on some CSS3 features for layout (mostly for multi-image figures with 89 | subcaptions). It adheres to a fairly straightforward [schema][html-schema]. No 90 | formatting information is written to the HTML by Scholdoc, so a 91 | ScholarlyMarkdown [core CSS][corecss] is required for bare minimum proper 92 | formatting. You can also write your own CSS that target the schema. 93 | 94 | By default, the `html` output format generates a complete (but bare-bones) 95 | HTML5 document that can be used immediately. To have Scholdoc generate just the 96 | bare content (everything inside [`scholmd-content`][html-schema-content]), use 97 | the `html_bodyonly` output format. By default, Scholdoc will always include 98 | proper [MathJax] settings for the way [ScholarlyMarkdown][scholmd] prescribes 99 | math content in HTML. 100 | 101 | ### Docx output 102 | 103 | The Docx writer currently isn't fully functional yet. It does not yet output structures specific to ScholarlyMarkdown (such as figures). 104 | 105 | [scholmd]: http://scholarlymarkdown.com 106 | [scholdoc]: https://github.com/timtylin/scholdoc 107 | [scholdoc-types]: https://github.com/timtylin/scholdoc-types 108 | [texmath]: https://github.com/jgm/texmath 109 | [pandoc]: http://johnmacfarlane.net/pandoc/ 110 | [pandocReadme]: http://johnmacfarlane.net/pandoc/README.html 111 | [pandocMarkdown]: http://johnmacfarlane.net/pandoc/README.html#pandocs-markdown 112 | [pandocTemplate]: http://johnmacfarlane.net/pandoc/README.html#templates 113 | [pandocFilters]: https://github.com/jgm/pandocfilters 114 | [pandocWriters]: http://johnmacfarlane.net/pandoc/README.html#custom-writers 115 | [pandoc-types]: https://github.com/jgm/pandoc-types 116 | [travis_stat]: https://travis-ci.org/timtylin/scholdoc 117 | [scholarly-devel-travisimage]: https://travis-ci.org/timtylin/scholdoc.svg?branch=master 118 | [scholarly-travisimage]: https://travis-ci.org/timtylin/scholdoc.svg?branch=stable 119 | [scholdoc-templates]: https://github.com/timtylin/scholdoc-templates 120 | [html-schema]: http://scholarlymarkdown.com/Scholarly-Markdown-HTML-Schema.html 121 | [html-schema-content]: http://scholarlymarkdown.com/Scholarly-Markdown-HTML-Schema.html#content 122 | [corecss]: http://scholarlymarkdown.com/scholdoc-distribution/css/core/scholmd-core-latest.css 123 | [mathjax]: http://www.mathjax.org 124 | [GHC]: http://www.haskell.org/ghc/ 125 | [Haskell platform]: http://hackage.haskell.org/platform/ 126 | [cabal-install]: http://hackage.haskell.org/trac/hackage/wiki/CabalInstall 127 | [zip-archive]: http://hackage.haskell.org/package/zip-archive 128 | [highlighting-kate]: http://hackage.haskell.org/package/highlighting-kate 129 | [blaze-html]: http://hackage.haskell.org/package/blaze-html 130 | [Cabal User's Guide]: http://www.haskell.org/cabal/release/latest/doc/users-guide/builders.html#setup-configure-paths 131 | [Homebrew]: http://brew.sh 132 | [hvr-PPA]: https://launchpad.net/~hvr/+archive/ubuntu/ghc 133 | [homebrew-scholdoc]: https://github.com/timtylin/homebrew-scholdoc/ 134 | [dingus]: http://scholarlymarkdown.com/dingus/ 135 | [scholdoc-download]: http://scholdoc.scholarlymarkdown.com/download/ 136 | -------------------------------------------------------------------------------- /Setup.hs: -------------------------------------------------------------------------------- 1 | {- 2 | Copyright (C) 2006-2014 John MacFarlane 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program; if not, write to the Free Software 16 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | -} 18 | 19 | import Distribution.Simple 20 | import Distribution.Simple.PreProcess 21 | import Distribution.PackageDescription (PackageDescription(..), Executable(..)) 22 | import System.Process ( rawSystem ) 23 | import System.FilePath ( () ) 24 | import System.Directory ( findExecutable ) 25 | import Distribution.Simple.Utils (info) 26 | 27 | main :: IO () 28 | main = defaultMainWithHooks $ simpleUserHooks { 29 | -- enable hsb2hs preprocessor for .hsb files 30 | hookedPreProcessors = [ppBlobSuffixHandler] 31 | -- ensure that make-pandoc-man-pages doesn't get installed to bindir 32 | , copyHook = \pkgdescr -> 33 | (copyHook simpleUserHooks) pkgdescr{ executables = 34 | [x | x <- executables pkgdescr, exeName x /= "make-pandoc-man-pages"] } 35 | , instHook = \pkgdescr -> 36 | (instHook simpleUserHooks) pkgdescr{ executables = 37 | [x | x <- executables pkgdescr, exeName x /= "make-pandoc-man-pages"] } 38 | } 39 | 40 | ppBlobSuffixHandler :: PPSuffixHandler 41 | ppBlobSuffixHandler = ("hsb", \_ _ -> 42 | PreProcessor { 43 | platformIndependent = True, 44 | runPreProcessor = mkSimplePreProcessor $ \infile outfile verbosity -> 45 | do info verbosity $ "Preprocessing " ++ infile ++ " to " ++ outfile 46 | hsb2hsPath <- findExecutable "hsb2hs" 47 | case hsb2hsPath of 48 | Just p -> rawSystem p [infile, infile, outfile] 49 | Nothing -> error "hsb2hs is needed to build this program: cabal install hsb2hs" 50 | return () 51 | }) 52 | -------------------------------------------------------------------------------- /benchmark/benchmark-scholdoc.hs: -------------------------------------------------------------------------------- 1 | {- 2 | Copyright (C) 2012-2014 John MacFarlane 3 | Copyright (C) 2015 Tim T.Y. Lin 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | -} 19 | import Text.Pandoc 20 | import Criterion.Main 21 | import Criterion.Types 22 | import Data.Maybe (mapMaybe) 23 | import Debug.Trace (trace) 24 | 25 | readerBench :: Pandoc 26 | -> (String, ReaderOptions -> String -> IO Pandoc) 27 | -> Maybe Benchmark 28 | readerBench doc (name, reader) = case lookup name writers of 29 | Just (PureStringWriter writer) -> 30 | let inp = writer def{ writerWrapText = True} doc 31 | in return $ bench (name ++ " reader") $ nfIO $ 32 | (reader def{ readerSmart = True }) inp 33 | _ -> trace ("\nCould not find writer for " ++ name ++ "\n") Nothing 34 | 35 | writerBench :: Pandoc 36 | -> (String, WriterOptions -> Pandoc -> String) 37 | -> Benchmark 38 | writerBench doc (name, writer) = bench (name ++ " writer") $ nf 39 | (writer def{ writerWrapText = True }) doc 40 | 41 | main :: IO () 42 | main = do 43 | inp <- readFile "tests/testsuite.txt" 44 | let opts = def{ readerSmart = True } 45 | let doc = readMarkdown opts inp 46 | let readers' = [(n,r) | (n, StringReader r) <- readers] 47 | let readerBs = mapMaybe (readerBench doc) 48 | $ filter (\(n,_) -> n /="haddock") readers' 49 | let writers' = [(n,w) | (n, PureStringWriter w) <- writers] 50 | let writerBs = map (writerBench doc) 51 | $ writers' 52 | let conf = defaultConfig { timeLimit = 2.0 } 53 | defaultMainWith conf $ writerBs ++ readerBs 54 | -------------------------------------------------------------------------------- /data/MathMLinHTML.js: -------------------------------------------------------------------------------- 1 | /* 2 | March 19, 2004 MathHTML (c) Peter Jipsen http://www.chapman.edu/~jipsen 3 | Released under the GNU General Public License version 2 or later. 4 | See the GNU General Public License (at http://www.gnu.org/copyleft/gpl.html) 5 | for more details. 6 | */ 7 | 8 | function convertMath(node) {// for Gecko 9 | if (node.nodeType==1) { 10 | var newnode = 11 | document.createElementNS("http://www.w3.org/1998/Math/MathML", 12 | node.nodeName.toLowerCase()); 13 | for(var i=0; i < node.attributes.length; i++) 14 | newnode.setAttribute(node.attributes[i].nodeName, 15 | node.attributes[i].value); 16 | for (var i=0; i"); 63 | document.write(""); 64 | } 65 | if(typeof window.addEventListener != 'undefined'){ 66 | window.addEventListener('load', convert, false); 67 | } 68 | if(typeof window.attachEvent != 'undefined') { 69 | window.attachEvent('onload', convert); 70 | } 71 | -------------------------------------------------------------------------------- /data/reference.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/timtylin/scholdoc/2620c8abccd544795d0b9f6687811102c21f21a6/data/reference.docx -------------------------------------------------------------------------------- /deb/control.in: -------------------------------------------------------------------------------- 1 | Package: pandoc 2 | Version: VERSION 3 | Section: text 4 | Priority: optional 5 | Architecture: ARCHITECTURE 6 | Installed-Size: INSTALLED_SIZE 7 | Depends: libc6 (>= 2.11), libgmp10, zlib1g (>= 1:1.1.4) 8 | Maintainer: John MacFarlane 9 | Description: general markup converter 10 | Pandoc is a Haskell library for converting from one markup 11 | format to another, and a command-line tool that uses 12 | this library. It can read markdown and (subsets of) HTML, 13 | reStructuredText, LaTeX, DocBook, MediaWiki markup, Twiki markup, 14 | Haddock markup, OPML, Emacs Org-Mode, txt2tags and Textile, and 15 | it can write markdown, reStructuredText, HTML, LaTeX, ConTeXt, 16 | Docbook, OPML, OpenDocument, ODT, Word docx, RTF, MediaWiki, 17 | DokuWiki, Textile, groff man pages, plain text, Emacs Org-Mode, 18 | AsciiDoc, Haddock markup, EPUB (v2 and v3), FictionBook2, 19 | InDesign ICML, and several kinds of HTML/javascript 20 | slide shows (S5, Slidy, Slideous, DZSlides, reveal.js). 21 | -------------------------------------------------------------------------------- /github-upload.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | VERSION=$1 4 | FULLNAME=pandoc-$VERSION 5 | read -s -p "Token (https://github.com/settings/applications): " TOKEN 6 | 7 | curl -H "Authorization: token $TOKEN" \ 8 | -H "Accept: application/vnd.github.manifold-preview" \ 9 | -H "Content-Type: application/x-apple-diskimage" \ 10 | --data-binary @$FULLNAME.pkg.zip \ 11 | "https://uploads.github.com/repos/jgm/pandoc/releases/$VERSION/assets?name=$FULLNAME.pkg.zip" 12 | 13 | curl -H "Authorization: token $TOKEN" \ 14 | -H "Accept: application/vnd.github.manifold-preview" \ 15 | -H "Content-Type: application/x-msi" \ 16 | --data-binary @$FULLNAME.msi \ 17 | "https://uploads.github.com/repos/jgm/pandoc/releases/$VERSION/assets?name=$FULLNAME.msi" 18 | 19 | -------------------------------------------------------------------------------- /make_deb.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | MACHINE=$(uname -m) 4 | case "$MACHINE" in 5 | x86_64) ARCHITECTURE=amd64;; 6 | i686) ARCHITECTURE=i386;; 7 | i386) ARCHITECTURE=i386;; 8 | esac 9 | 10 | SANDBOX=`pwd`/.cabal-sandbox 11 | VERSION=$(grep -e '^Version' pandoc.cabal | awk '{print $2}') 12 | DEBPKGVER=1 13 | DEBVER=$VERSION-$DEBPKGVER 14 | BASE=pandoc-$DEBVER-$ARCHITECTURE 15 | DIST=`pwd`/$BASE 16 | MANDIR=`pwd`/man 17 | DEST=$DIST/usr 18 | ME=$(whoami) 19 | COPYRIGHT=$DEST/share/doc/pandoc/copyright 20 | 21 | # echo Removing old files... 22 | rm -rf $DIST 23 | 24 | cabal sandbox init 25 | echo Updating database 26 | cabal update 27 | 28 | export PATH=`pwd`/.cabal-sandbox/bin:$PATH 29 | which hsb2hs || cabal install hsb2hs 30 | echo Building pandoc... 31 | cabal clean 32 | cabal install --force --reinstall --flags="embed_data_files make-pandoc-man-pages" . pandoc-citeproc 33 | 34 | make man 35 | # get pandoc-citeproc man page: 36 | PANDOC_CITEPROC_PATH=`cabal unpack -d make_binary_package.tmp.$$ pandoc-citeproc | awk '{print $3;}'` 37 | strip $SANDBOX/bin/pandoc 38 | strip $SANDBOX/bin/pandoc-citeproc 39 | mkdir -p $DEST/bin 40 | mkdir -p $DEST/share/man/man1 41 | mkdir -p $DEST/share/man/man5 42 | mkdir -p $DEST/share/doc/pandoc 43 | mkdir -p $DEST/share/doc/pandoc-citeproc 44 | find $DIST -type d | xargs chmod 755 45 | cp $SANDBOX/bin/pandoc $DEST/bin/ 46 | cp $SANDBOX/bin/pandoc-citeproc $DEST/bin/ 47 | cp $MANDIR/man1/pandoc.1 $DEST/share/man/man1/ 48 | gzip -9 $DEST/share/man/man1/pandoc.1 49 | cp $MANDIR/man5/pandoc_markdown.5 $DEST/share/man/man5/ 50 | gzip -9 $DEST/share/man/man5/pandoc_markdown.5 51 | cp $PANDOC_CITEPROC_PATH/man/man1/pandoc-citeproc.1 $DEST/share/man/man1/ 52 | gzip -9 $DEST/share/man/man1/pandoc-citeproc.1 53 | cp COPYRIGHT $COPYRIGHT 54 | echo "" >> $COPYRIGHT 55 | echo "pandoc-citeproc" >> $COPYRIGHT 56 | cat $PANDOC_CITEPROC_PATH/LICENSE >> $COPYRIGHT 57 | rm -rf make_binary_package.tmp.$$ 58 | 59 | INSTALLED_SIZE=$(du -B 1024 -s $DEST | awk '{print $1}') 60 | mkdir $DIST/DEBIAN 61 | perl -pe "s/VERSION/$DEBVER/" deb/control.in | \ 62 | perl -pe "s/ARCHITECTURE/$ARCHITECTURE/" | \ 63 | perl -pe "s/INSTALLED_SIZE/$INSTALLED_SIZE/" \ 64 | > $DIST/DEBIAN/control 65 | 66 | fakeroot dpkg-deb --build $DIST 67 | rm -rf $DIST 68 | -------------------------------------------------------------------------------- /make_osx_package.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | DIST=`pwd`/osx_package 4 | SANDBOX=`pwd`/.cabal-sandbox 5 | VERSION=$(grep -e '^Version' pandoc.cabal | awk '{print $2}') 6 | RESOURCES=$DIST/Resources 7 | ROOT=$DIST/pandoc 8 | MANDIR=`pwd`/man 9 | DEST=$ROOT/usr/local 10 | OSX=osx 11 | SCRIPTS=$OSX/osx-resources 12 | BASE=pandoc-$VERSION 13 | ME=$(whoami) 14 | PACKAGEMAKER=/Applications/PackageMaker.app/Contents/MacOS/PackageMaker 15 | CPPHS=$SANDBOX/bin/cpphs 16 | 17 | # echo Removing old files... 18 | rm -rf $DIST 19 | mkdir -p $RESOURCES 20 | 21 | cabal sandbox init 22 | echo Updating database 23 | cabal update 24 | 25 | echo Building pandoc... 26 | cabal clean 27 | # Use cpphs to avoid problems with clang cpp on ghc 7.8 osx: 28 | cabal install cpphs hsb2hs 29 | cabal install --ghc-options="-optl-mmacosx-version-min=10.6" --reinstall --flags="embed_data_files make-pandoc-man-pages" --ghc-options "-pgmP$CPPHS -optP--cpp" . pandoc-citeproc 30 | 31 | make man 32 | # get pandoc-citeproc man page: 33 | PANDOC_CITEPROC_PATH=`cabal unpack -d $DIST pandoc-citeproc | awk '{print $3;}'` 34 | cp $PANDOC_CITEPROC_PATH/man/man1/pandoc-citeproc.1 $MANDIR/man1/ 35 | 36 | mkdir -p $DEST/bin 37 | mkdir -p $DEST/share/man/man1 38 | mkdir -p $DEST/share/man/man5 39 | for f in pandoc pandoc-citeproc; do 40 | cp $SANDBOX/bin/$f $DEST/bin/; 41 | cp $MANDIR/man1/$f.1 $DEST/share/man/man1/ 42 | done 43 | cp $MANDIR/man5/pandoc_markdown.5 $DEST/share/man/man5/ 44 | 45 | chown -R $ME:staff $DIST 46 | 47 | echo Copying license... 48 | $SANDBOX/bin/pandoc --data data -t html5 -s COPYING -o $RESOURCES/license.html 49 | 50 | echo Signing pandoc executable... 51 | 52 | codesign --force --sign "Developer ID Application: John Macfarlane" $DEST/bin/pandoc 53 | # make sure it's valid... returns nonzero exit code if it isn't: 54 | spctl --assess --type execute $DEST/bin/pandoc 55 | 56 | echo Creating OSX package... 57 | # remove old package first 58 | rm -rf $BASE.pkg 59 | 60 | pkgbuild --root $DIST/pandoc --identifier net.johnmacfarlane.pandoc --version 1.13 --ownership recommended $DIST/pandoc.pkg 61 | productbuild --distribution osx/distribution.xml --resources $DIST/Resources --package-path $DIST --version 1.13 --sign "Developer ID Installer: John Macfarlane" $BASE-osx.pkg 62 | 63 | # verify signature 64 | spctl --assess --type install $BASE-osx.pkg 65 | 66 | # cleanup 67 | rm -r $DIST 68 | -------------------------------------------------------------------------------- /osx/distribution.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | pandoc 4 | net.johnmacfarlane.pandoc 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | pandoc.pkg 16 | 18 | 19 | 20 | 21 | 22 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /osx/uninstall-pandoc.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # Script to remove all files installed by the OSX pandoc installer 4 | # and unregister the package. Modified from a script contributed 5 | # by Daniel T. Staal. 6 | 7 | use warnings; 8 | use strict; 9 | 10 | use File::Spec; 11 | 12 | # The main info: this is the list of files to remove and the pkg_id. 13 | my $pkg_id = 'net.johnmacfarlane.pandoc'; 14 | 15 | # Find which, if any, volume Pandoc is installed on. 16 | my $volume; 17 | 18 | # First check /, then other volumes on the box. 19 | my $cur_test = `pkgutil --pkgs=$pkg_id`; 20 | if ( $cur_test =~ m/$pkg_id/ ) { 21 | $volume = '/'; 22 | } else { 23 | opendir( my $dh, '/Volumes' ) or die "Can't list Volumes: $!\n"; 24 | foreach my $dir ( readdir($dh) ) { 25 | next if $dir =~ m/^\./; # Skip dotfiles. 26 | 27 | my $path = File::Spec->rel2abs( $dir, '/Volumes' ); 28 | next if !( -d $path ); # Skip anything that isn't a directory. 29 | 30 | my $cur_test = `pkgutil --pkgs=$pkg_id --volume '$path'`; 31 | if ( $cur_test =~ m/$pkg_id/ ) { 32 | $volume = $path; 33 | last; 34 | } 35 | } 36 | } 37 | 38 | die "Pandoc not installed.\n" if !( defined($volume) ); 39 | 40 | # Get the list of files to remove. 41 | my @pkg_files = `pkgutil --volume '$volume' --only-files --files '$pkg_id'`; 42 | @pkg_files = map { chomp; File::Spec->rel2abs($_, $volume) } @pkg_files; 43 | 44 | # Confirm uninistall with the user. 45 | print "The following files will be deleted:\n\n"; 46 | print join("\n", @pkg_files); 47 | print "\n\n"; 48 | print "Do you want to proceed and uninstall pandoc (Y/N)?"; 49 | my $input = ; 50 | 51 | if ($input =~ m/^[Yy]/) { 52 | 53 | # Actually remove the files. 54 | foreach my $file (@pkg_files) { 55 | if ( -e $file ) { 56 | if ( system( 'sudo', 'rm', $file ) == 0 ) { 57 | warn "Deleted $file\n"; 58 | } else { 59 | warn "Unable to delete $file: $?\n"; 60 | die "Aborting Uninstall.\n"; 61 | } 62 | } else { 63 | warn "File $file does not exist. Skipping.\n"; 64 | } 65 | } 66 | 67 | # Clean up the install. 68 | if (system('sudo', 'pkgutil', '--forget', $pkg_id, '--volume', $volume) != 0) { 69 | die "Unable to clean up install: $?\n"; 70 | } 71 | 72 | } else { 73 | 74 | print "OK, aborting uninstall.\n"; 75 | exit; 76 | } 77 | 78 | print "Pandoc has been successfully uninstalled.\n"; 79 | exit; 80 | -------------------------------------------------------------------------------- /src/Text/Pandoc/Compat/Directory.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE CPP #-} 2 | module Text.Pandoc.Compat.Directory ( getModificationTime ) 3 | where 4 | 5 | #if MIN_VERSION_directory(1,2,0) 6 | import System.Directory 7 | 8 | 9 | #else 10 | import qualified System.Directory as S 11 | import Data.Time.Clock (UTCTime) 12 | import Data.Time.Clock.POSIX 13 | import System.Time 14 | 15 | getModificationTime :: FilePath -> IO UTCTime 16 | getModificationTime fp = convert `fmap` S.getModificationTime fp 17 | where 18 | convert (TOD x _) = posixSecondsToUTCTime (realToFrac x) 19 | 20 | #endif 21 | 22 | -------------------------------------------------------------------------------- /src/Text/Pandoc/Compat/Except.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE CPP #-} 2 | module Text.Pandoc.Compat.Except ( ExceptT 3 | , Except 4 | , Error(..) 5 | , runExceptT 6 | , runExcept 7 | , MonadError 8 | , throwError 9 | , catchError ) 10 | where 11 | 12 | #if MIN_VERSION_mtl(2,2,1) 13 | import Control.Monad.Except 14 | 15 | class Error a where 16 | noMsg :: a 17 | strMsg :: String -> a 18 | 19 | noMsg = strMsg "" 20 | strMsg _ = noMsg 21 | 22 | #else 23 | import Control.Monad.Error 24 | import Control.Monad.Identity (Identity, runIdentity) 25 | 26 | type ExceptT = ErrorT 27 | 28 | type Except s a = ErrorT s Identity a 29 | 30 | runExceptT :: ExceptT e m a -> m (Either e a) 31 | runExceptT = runErrorT 32 | 33 | runExcept :: ExceptT e Identity a -> Either e a 34 | runExcept = runIdentity . runExceptT 35 | #endif 36 | 37 | 38 | -------------------------------------------------------------------------------- /src/Text/Pandoc/Compat/Locale.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE CPP #-} 2 | module Text.Pandoc.Compat.Locale ( defaultTimeLocale ) 3 | where 4 | 5 | #if MIN_VERSION_time(1,5,0) 6 | import Data.Time.Format ( defaultTimeLocale ) 7 | #else 8 | import System.Locale ( defaultTimeLocale ) 9 | #endif 10 | -------------------------------------------------------------------------------- /src/Text/Pandoc/Compat/Monoid.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE CPP #-} 2 | module Text.Pandoc.Compat.Monoid ( Monoid(..) 3 | , (<>) 4 | ) where 5 | 6 | #if MIN_VERSION_base(4,5,0) 7 | import Data.Monoid ((<>), Monoid(..)) 8 | #else 9 | import Data.Monoid (mappend, Monoid(..)) 10 | #endif 11 | 12 | #if MIN_VERSION_base(4,5,0) 13 | #else 14 | infixr 6 <> 15 | 16 | -- | An infix synonym for 'mappend'. 17 | (<>) :: Monoid m => m -> m -> m 18 | (<>) = mappend 19 | {-# INLINE (<>) #-} 20 | #endif 21 | -------------------------------------------------------------------------------- /src/Text/Pandoc/Compat/TagSoupEntity.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE CPP #-} 2 | module Text.Pandoc.Compat.TagSoupEntity (lookupEntity 3 | ) where 4 | 5 | import qualified Text.HTML.TagSoup.Entity as TE 6 | 7 | lookupEntity :: String -> Maybe Char 8 | #if MIN_VERSION_tagsoup(0,13,0) 9 | lookupEntity = str2chr . TE.lookupEntity 10 | where str2chr :: Maybe String -> Maybe Char 11 | str2chr (Just [c]) = Just c 12 | str2chr _ = Nothing 13 | #else 14 | lookupEntity = TE.lookupEntity 15 | #endif 16 | -------------------------------------------------------------------------------- /src/Text/Pandoc/Data.hsb: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE OverloadedStrings #-} 2 | -- to be processed using hsb2hs 3 | module Text.Pandoc.Data (dataFiles) where 4 | import qualified Data.ByteString as B 5 | 6 | dataFiles :: [(FilePath, B.ByteString)] 7 | dataFiles = %blobs "data" 8 | -------------------------------------------------------------------------------- /src/Text/Pandoc/Highlighting.hs: -------------------------------------------------------------------------------- 1 | {- 2 | Copyright (C) 2008-2014 John MacFarlane 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program; if not, write to the Free Software 16 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | -} 18 | 19 | {- | 20 | Module : Text.Pandoc.Highlighting 21 | Copyright : Copyright (C) 2008-2014 John MacFarlane 22 | License : GNU GPL, version 2 or above 23 | 24 | Maintainer : John MacFarlane 25 | Stability : alpha 26 | Portability : portable 27 | 28 | Exports functions for syntax highlighting. 29 | -} 30 | 31 | module Text.Pandoc.Highlighting ( languages 32 | , languagesByExtension 33 | , highlight 34 | , formatLaTeXInline 35 | , formatLaTeXBlock 36 | , styleToLaTeX 37 | , formatHtmlInline 38 | , formatHtmlBlock 39 | , styleToCss 40 | , pygments 41 | , espresso 42 | , zenburn 43 | , tango 44 | , kate 45 | , monochrome 46 | , haddock 47 | , Style 48 | , fromListingsLanguage 49 | , toListingsLanguage 50 | ) where 51 | import Text.Pandoc.Definition 52 | import Text.Pandoc.Shared (safeRead) 53 | import Text.Highlighting.Kate 54 | import Data.List (find) 55 | import Data.Maybe (fromMaybe) 56 | import Data.Char (toLower) 57 | import qualified Data.Map as M 58 | import Control.Applicative ((<|>)) 59 | 60 | lcLanguages :: [String] 61 | lcLanguages = map (map toLower) languages 62 | 63 | highlight :: (FormatOptions -> [SourceLine] -> a) -- ^ Formatter 64 | -> Attr -- ^ Attributes of the CodeBlock 65 | -> String -- ^ Raw contents of the CodeBlock 66 | -> Maybe a -- ^ Maybe the formatted result 67 | highlight formatter (_, classes, keyvals) rawCode = 68 | let firstNum = case safeRead (fromMaybe "1" $ lookup "startFrom" keyvals) of 69 | Just n -> n 70 | Nothing -> 1 71 | fmtOpts = defaultFormatOpts{ 72 | startNumber = firstNum, 73 | numberLines = any (`elem` 74 | ["number","numberLines", "number-lines"]) classes } 75 | lcclasses = map (map toLower) classes 76 | in case find (`elem` lcLanguages) lcclasses of 77 | Nothing 78 | | numberLines fmtOpts -> Just 79 | $ formatter fmtOpts{ codeClasses = [], 80 | containerClasses = classes } 81 | $ map (\ln -> [(NormalTok, ln)]) $ lines rawCode 82 | | otherwise -> Nothing 83 | Just language -> Just 84 | $ formatter fmtOpts{ codeClasses = [language], 85 | containerClasses = classes } 86 | $ highlightAs language rawCode 87 | 88 | -- Functions for correlating latex listings package's language names 89 | -- with highlighting-kate language names: 90 | 91 | langToListingsMap :: M.Map String String 92 | langToListingsMap = M.fromList langsList 93 | 94 | listingsToLangMap :: M.Map String String 95 | listingsToLangMap = M.fromList $ map switch langsList 96 | where switch (a,b) = (b,a) 97 | 98 | langsList :: [(String, String)] 99 | langsList = [("ada","Ada") 100 | ,("java","Java") 101 | ,("prolog","Prolog") 102 | ,("python","Python") 103 | ,("gnuassembler","Assembler") 104 | ,("commonlisp","Lisp") 105 | ,("r","R") 106 | ,("awk","Awk") 107 | ,("bash","bash") 108 | ,("makefile","make") 109 | ,("c","C") 110 | ,("matlab","Matlab") 111 | ,("ruby","Ruby") 112 | ,("cpp","C++") 113 | ,("ocaml","Caml") 114 | ,("modula2","Modula-2") 115 | ,("sql","SQL") 116 | ,("eiffel","Eiffel") 117 | ,("tcl","tcl") 118 | ,("erlang","erlang") 119 | ,("verilog","Verilog") 120 | ,("fortran","Fortran") 121 | ,("vhdl","VHDL") 122 | ,("pascal","Pascal") 123 | ,("perl","Perl") 124 | ,("xml","XML") 125 | ,("haskell","Haskell") 126 | ,("php","PHP") 127 | ,("xslt","XSLT") 128 | ,("html","HTML") 129 | ] 130 | 131 | listingsLangs :: [String] 132 | listingsLangs = ["Ada","Java","Prolog","Algol","JVMIS","Promela", 133 | "Ant","ksh","Python","Assembler","Lisp","R","Awk", 134 | "Logo","Reduce","bash","make","Rexx","Basic", 135 | "Mathematica","RSL","C","Matlab","Ruby","C++", 136 | "Mercury","S","Caml","MetaPost","SAS","Clean", 137 | "Miranda","Scilab","Cobol","Mizar","sh","Comal", 138 | "ML","SHELXL","csh","Modula-2","Simula","Delphi", 139 | "MuPAD","SQL","Eiffel","NASTRAN","tcl","Elan", 140 | "Oberon-2","TeX","erlang","OCL","VBScript","Euphoria", 141 | "Octave","Verilog","Fortran","Oz","VHDL","GCL", 142 | "Pascal","VRML","Gnuplot","Perl","XML","Haskell", 143 | "PHP","XSLT","HTML","PL/I"] 144 | 145 | -- Determine listings language name from highlighting-kate language name. 146 | toListingsLanguage :: String -> Maybe String 147 | toListingsLanguage lang = (if lang `elem` listingsLangs 148 | then Just lang 149 | else Nothing) <|> 150 | M.lookup (map toLower lang) langToListingsMap 151 | 152 | -- Determine highlighting-kate language name from listings language name. 153 | fromListingsLanguage :: String -> Maybe String 154 | fromListingsLanguage lang = M.lookup lang listingsToLangMap 155 | -------------------------------------------------------------------------------- /src/Text/Pandoc/MediaBag.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE GeneralizedNewtypeDeriving #-} 2 | {- 3 | Copyright (C) 2014 John MacFarlane 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | -} 19 | 20 | {- | 21 | Module : Text.Pandoc.MediaBag 22 | Copyright : Copyright (C) 2014 John MacFarlane 23 | License : GNU GPL, version 2 or above 24 | 25 | Maintainer : John MacFarlane 26 | Stability : alpha 27 | Portability : portable 28 | 29 | Definition of a MediaBag object to hold binary resources, and an 30 | interface for interacting with it. 31 | -} 32 | module Text.Pandoc.MediaBag ( 33 | MediaBag, 34 | lookupMedia, 35 | insertMedia, 36 | mediaDirectory, 37 | extractMediaBag 38 | ) where 39 | import System.FilePath 40 | import System.Directory (createDirectoryIfMissing) 41 | import qualified Data.Map as M 42 | import qualified Data.ByteString.Lazy as BL 43 | import Data.Monoid (Monoid) 44 | import Control.Monad (when) 45 | import Text.Pandoc.MIME (MimeType, getMimeTypeDef) 46 | import qualified Text.Pandoc.UTF8 as UTF8 47 | import Data.Maybe (fromMaybe) 48 | import System.IO (stderr) 49 | 50 | -- | A container for a collection of binary resources, with names and 51 | -- mime types. Note that a 'MediaBag' is a Monoid, so 'mempty' 52 | -- can be used for an empty 'MediaBag', and '<>' can be used to append 53 | -- two 'MediaBag's. 54 | newtype MediaBag = MediaBag (M.Map [String] (MimeType, BL.ByteString)) 55 | deriving (Monoid) 56 | 57 | instance Show MediaBag where 58 | show bag = "MediaBag " ++ show (mediaDirectory bag) 59 | 60 | -- | Insert a media item into a 'MediaBag', replacing any existing 61 | -- value with the same name. 62 | insertMedia :: FilePath -- ^ relative path and canonical name of resource 63 | -> Maybe MimeType -- ^ mime type (Nothing = determine from extension) 64 | -> BL.ByteString -- ^ contents of resource 65 | -> MediaBag 66 | -> MediaBag 67 | insertMedia fp mbMime contents (MediaBag mediamap) = 68 | MediaBag (M.insert (splitPath fp) (mime, contents) mediamap) 69 | where mime = fromMaybe fallback mbMime 70 | fallback = case takeExtension fp of 71 | ".gz" -> getMimeTypeDef $ dropExtension fp 72 | _ -> getMimeTypeDef fp 73 | 74 | -- | Lookup a media item in a 'MediaBag', returning mime type and contents. 75 | lookupMedia :: FilePath 76 | -> MediaBag 77 | -> Maybe (MimeType, BL.ByteString) 78 | lookupMedia fp (MediaBag mediamap) = M.lookup (splitPath fp) mediamap 79 | 80 | -- | Get a list of the file paths stored in a 'MediaBag', with 81 | -- their corresponding mime types and the lengths in bytes of the contents. 82 | mediaDirectory :: MediaBag -> [(String, MimeType, Int)] 83 | mediaDirectory (MediaBag mediamap) = 84 | M.foldWithKey (\fp (mime,contents) -> 85 | (((joinPath fp), mime, fromIntegral $ BL.length contents):)) [] mediamap 86 | 87 | -- | Extract contents of MediaBag to a given directory. Print informational 88 | -- messages if 'verbose' is true. 89 | extractMediaBag :: Bool 90 | -> FilePath 91 | -> MediaBag 92 | -> IO () 93 | extractMediaBag verbose dir (MediaBag mediamap) = do 94 | sequence_ $ M.foldWithKey 95 | (\fp (_ ,contents) -> 96 | ((writeMedia verbose dir (joinPath fp, contents)):)) [] mediamap 97 | 98 | writeMedia :: Bool -> FilePath -> (FilePath, BL.ByteString) -> IO () 99 | writeMedia verbose dir (subpath, bs) = do 100 | -- we join and split to convert a/b/c to a\b\c on Windows; 101 | -- in zip containers all paths use / 102 | let fullpath = dir normalise subpath 103 | createDirectoryIfMissing True $ takeDirectory fullpath 104 | when verbose $ UTF8.hPutStrLn stderr $ "pandoc: extracting " ++ fullpath 105 | BL.writeFile fullpath bs 106 | 107 | 108 | -------------------------------------------------------------------------------- /src/Text/Pandoc/Process.hs: -------------------------------------------------------------------------------- 1 | {- 2 | Copyright (C) 2013-2014 John MacFarlane 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program; if not, write to the Free Software 16 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | -} 18 | 19 | {- | 20 | Module : Text.Pandoc.Process 21 | Copyright : Copyright (C) 2013-2014 John MacFarlane 22 | License : GNU GPL, version 2 or above 23 | 24 | Maintainer : John MacFarlane 25 | Stability : alpha 26 | Portability : portable 27 | 28 | ByteString variant of 'readProcessWithExitCode'. 29 | -} 30 | module Text.Pandoc.Process (pipeProcess) 31 | where 32 | import System.Process 33 | import System.Exit (ExitCode (..)) 34 | import Control.Exception 35 | import System.IO (hClose, hFlush) 36 | import Control.Concurrent (putMVar, takeMVar, newEmptyMVar, forkIO) 37 | import Control.Monad (unless) 38 | import qualified Data.ByteString.Lazy as BL 39 | 40 | {- | 41 | Version of 'System.Process.readProcessWithExitCode' that uses lazy bytestrings 42 | instead of strings and allows setting environment variables. 43 | 44 | @readProcessWithExitCode@ creates an external process, reads its 45 | standard output and standard error strictly, waits until the process 46 | terminates, and then returns the 'ExitCode' of the process, 47 | the standard output, and the standard error. 48 | 49 | If an asynchronous exception is thrown to the thread executing 50 | @readProcessWithExitCode@, the forked process will be terminated and 51 | @readProcessWithExitCode@ will wait (block) until the process has been 52 | terminated. 53 | -} 54 | 55 | pipeProcess 56 | :: Maybe [(String, String)] -- ^ environment variables 57 | -> FilePath -- ^ Filename of the executable (see 'proc' for details) 58 | -> [String] -- ^ any arguments 59 | -> BL.ByteString -- ^ standard input 60 | -> IO (ExitCode,BL.ByteString,BL.ByteString) -- ^ exitcode, stdout, stderr 61 | pipeProcess mbenv cmd args input = 62 | mask $ \restore -> do 63 | (Just inh, Just outh, Just errh, pid) <- createProcess (proc cmd args) 64 | { env = mbenv, 65 | std_in = CreatePipe, 66 | std_out = CreatePipe, 67 | std_err = CreatePipe } 68 | flip onException 69 | (do hClose inh; hClose outh; hClose errh; 70 | terminateProcess pid; waitForProcess pid) $ restore $ do 71 | -- fork off a thread to start consuming stdout 72 | out <- BL.hGetContents outh 73 | waitOut <- forkWait $ evaluate $ BL.length out 74 | 75 | -- fork off a thread to start consuming stderr 76 | err <- BL.hGetContents errh 77 | waitErr <- forkWait $ evaluate $ BL.length err 78 | 79 | -- now write and flush any input 80 | let writeInput = do 81 | unless (BL.null input) $ do 82 | BL.hPutStr inh input 83 | hFlush inh 84 | hClose inh 85 | 86 | writeInput 87 | 88 | -- wait on the output 89 | waitOut 90 | waitErr 91 | 92 | hClose outh 93 | hClose errh 94 | 95 | -- wait on the process 96 | ex <- waitForProcess pid 97 | 98 | return (ex, out, err) 99 | 100 | forkWait :: IO a -> IO (IO a) 101 | forkWait a = do 102 | res <- newEmptyMVar 103 | _ <- mask $ \restore -> forkIO $ try (restore a) >>= putMVar res 104 | return (takeMVar res >>= either (\ex -> throwIO (ex :: SomeException)) return) 105 | -------------------------------------------------------------------------------- /src/Text/Pandoc/Readers/Native.hs: -------------------------------------------------------------------------------- 1 | {- 2 | Copyright (C) 2011-2014 John MacFarlane 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program; if not, write to the Free Software 16 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | -} 18 | 19 | {- | 20 | Module : Text.Pandoc.Readers.Native 21 | Copyright : Copyright (C) 2011-2014 John MacFarlane 22 | License : GNU GPL, version 2 or above 23 | 24 | Maintainer : John MacFarlane 25 | Stability : alpha 26 | Portability : portable 27 | 28 | Conversion of a string representation of a pandoc type (@Pandoc@, 29 | @[Block]@, @Block@, @[Inline]@, or @Inline@) to a @Pandoc@ document. 30 | -} 31 | module Text.Pandoc.Readers.Native ( readNative ) where 32 | 33 | import Text.Pandoc.Definition 34 | import Text.Pandoc.Shared (safeRead) 35 | 36 | -- | Read native formatted text and return a Pandoc document. 37 | -- The input may be a full pandoc document, a block list, a block, 38 | -- an inline list, or an inline. Thus, for example, 39 | -- 40 | -- > Str "hi" 41 | -- 42 | -- will be treated as if it were 43 | -- 44 | -- > Pandoc nullMeta [Plain [Str "hi"]] 45 | -- 46 | readNative :: String -- ^ String to parse (assuming @'\n'@ line endings) 47 | -> Pandoc 48 | readNative s = 49 | case safeRead s of 50 | Just d -> d 51 | Nothing -> Pandoc nullMeta $ readBlocks s 52 | 53 | readBlocks :: String -> [Block] 54 | readBlocks s = 55 | case safeRead s of 56 | Just d -> d 57 | Nothing -> [readBlock s] 58 | 59 | readBlock :: String -> Block 60 | readBlock s = 61 | case safeRead s of 62 | Just d -> d 63 | Nothing -> Plain $ readInlines s 64 | 65 | readInlines :: String -> [Inline] 66 | readInlines s = 67 | case safeRead s of 68 | Just d -> d 69 | Nothing -> [readInline s] 70 | 71 | readInline :: String -> Inline 72 | readInline s = 73 | case safeRead s of 74 | Just d -> d 75 | Nothing -> error "Cannot parse document" 76 | 77 | -------------------------------------------------------------------------------- /src/Text/Pandoc/Readers/TeXMath.hs: -------------------------------------------------------------------------------- 1 | {- 2 | Copyright (C) 2007-2014 John MacFarlane 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program; if not, write to the Free Software 16 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | -} 18 | 19 | {- | 20 | Module : Text.Pandoc.Readers.TeXMath 21 | Copyright : Copyright (C) 2007-2014 John MacFarlane 22 | License : GNU GPL, version 2 or above 23 | 24 | Maintainer : John MacFarlane 25 | Stability : alpha 26 | Portability : portable 27 | 28 | Conversion of TeX math to a list of 'Pandoc' inline elements. 29 | -} 30 | module Text.Pandoc.Readers.TeXMath ( texMathToInlines ) where 31 | 32 | import Text.Pandoc.Definition 33 | import Text.TeXMath 34 | 35 | -- | Converts a raw TeX math formula to a list of 'Pandoc' inlines. 36 | -- Defaults to raw formula between @$@ or @$$@ characters if entire formula 37 | -- can't be converted. 38 | texMathToInlines :: MathType 39 | -> String -- ^ String to parse (assumes @'\n'@ line endings) 40 | -> [Inline] 41 | texMathToInlines mt inp = 42 | case writePandoc dt `fmap` readTeX inp of 43 | Right (Just ils) -> ils 44 | _ -> [Str (delim ++ inp ++ delim)] 45 | where (dt, delim) = case mt of 46 | (DisplayMath _) -> (DisplayBlock, "$$") 47 | InlineMath -> (DisplayInline, "$") 48 | 49 | -------------------------------------------------------------------------------- /src/Text/Pandoc/SelfContained.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE OverloadedStrings #-} 2 | {- 3 | Copyright (C) 2011-2014 John MacFarlane 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | -} 19 | 20 | {- | 21 | Module : Text.Pandoc.SelfContained 22 | Copyright : Copyright (C) 2011-2014 John MacFarlane 23 | License : GNU GPL, version 2 or above 24 | 25 | Maintainer : John MacFarlane 26 | Stability : alpha 27 | Portability : portable 28 | 29 | Functions for converting an HTML file into one that can be viewed 30 | offline, by incorporating linked images, CSS, and scripts into 31 | the HTML using data URIs. 32 | -} 33 | module Text.Pandoc.SelfContained ( makeSelfContained ) where 34 | import Text.HTML.TagSoup 35 | import Network.URI (isURI, escapeURIString, URI(..), parseURI) 36 | import Data.ByteString.Base64 37 | import qualified Data.ByteString.Char8 as B 38 | import Data.ByteString (ByteString) 39 | import System.FilePath (takeExtension, takeDirectory, ()) 40 | import Data.Char (toLower, isAscii, isAlphaNum) 41 | import Codec.Compression.GZip as Gzip 42 | import qualified Data.ByteString.Lazy as L 43 | import Text.Pandoc.Shared (renderTags', err, fetchItem') 44 | import Text.Pandoc.MediaBag (MediaBag) 45 | import Text.Pandoc.MIME (MimeType) 46 | import Text.Pandoc.UTF8 (toString, fromString) 47 | import Text.Pandoc.Options (WriterOptions(..)) 48 | 49 | isOk :: Char -> Bool 50 | isOk c = isAscii c && isAlphaNum c 51 | 52 | convertTag :: MediaBag -> Maybe String -> Tag String -> IO (Tag String) 53 | convertTag media sourceURL t@(TagOpen tagname as) 54 | | tagname `elem` 55 | ["img", "embed", "video", "input", "audio", "source", "track"] = do 56 | as' <- mapM processAttribute as 57 | return $ TagOpen tagname as' 58 | where processAttribute (x,y) = 59 | if x == "src" || x == "href" || x == "poster" 60 | then do 61 | (raw, mime) <- getRaw media sourceURL (fromAttrib "type" t) y 62 | let enc = "data:" ++ mime ++ ";base64," ++ toString (encode raw) 63 | return (x, enc) 64 | else return (x,y) 65 | convertTag media sourceURL t@(TagOpen "script" as) = 66 | case fromAttrib "src" t of 67 | [] -> return t 68 | src -> do 69 | (raw, mime) <- getRaw media sourceURL (fromAttrib "type" t) src 70 | let mime' = if ';' `elem` mime 71 | then mime -- mime type already has charset 72 | else mime ++ ";charset=utf-8" 73 | let enc = "data:" ++ mime' ++ "," ++ escapeURIString isOk (toString raw) 74 | return $ TagOpen "script" (("src",enc) : [(x,y) | (x,y) <- as, x /= "src"]) 75 | convertTag media sourceURL t@(TagOpen "link" as) = 76 | case fromAttrib "href" t of 77 | [] -> return t 78 | src -> do 79 | (raw, mime) <- getRaw media sourceURL (fromAttrib "type" t) src 80 | let enc = "data:" ++ mime ++ "," ++ escapeURIString isOk (toString raw) 81 | return $ TagOpen "link" (("href",enc) : [(x,y) | (x,y) <- as, x /= "href"]) 82 | convertTag _ _ t = return t 83 | 84 | -- NOTE: This is really crude, it doesn't respect CSS comments. 85 | cssURLs :: MediaBag -> Maybe String -> FilePath -> ByteString 86 | -> IO ByteString 87 | cssURLs media sourceURL d orig = 88 | case B.breakSubstring "url(" orig of 89 | (x,y) | B.null y -> return orig 90 | | otherwise -> do 91 | let (u,v) = B.breakSubstring ")" $ B.drop 4 y 92 | let url = toString 93 | $ case B.take 1 u of 94 | "\"" -> B.takeWhile (/='"') $ B.drop 1 u 95 | "'" -> B.takeWhile (/='\'') $ B.drop 1 u 96 | _ -> u 97 | let url' = if isURI url 98 | then url 99 | else d url 100 | (raw, mime) <- getRaw media sourceURL "" url' 101 | rest <- cssURLs media sourceURL d v 102 | let enc = "data:" `B.append` fromString mime `B.append` 103 | ";base64," `B.append` (encode raw) 104 | return $ x `B.append` "url(" `B.append` enc `B.append` rest 105 | 106 | getRaw :: MediaBag -> Maybe String -> MimeType -> String 107 | -> IO (ByteString, MimeType) 108 | getRaw media sourceURL mimetype src = do 109 | let ext = map toLower $ takeExtension src 110 | fetchResult <- fetchItem' media sourceURL src 111 | (raw, respMime) <- case fetchResult of 112 | Left msg -> err 67 $ "Could not fetch " ++ src ++ 113 | "\n" ++ show msg 114 | Right x -> return x 115 | let raw' = if ext == ".gz" 116 | then B.concat $ L.toChunks $ Gzip.decompress $ L.fromChunks 117 | $ [raw] 118 | else raw 119 | let mime = case (mimetype, respMime) of 120 | ("",Nothing) -> error 121 | $ "Could not determine mime type for `" ++ src ++ "'" 122 | (x, Nothing) -> x 123 | (_, Just x ) -> x 124 | let cssSourceURL = case parseURI src of 125 | Just u 126 | | uriScheme u `elem` ["http:","https:"] -> 127 | Just $ show u{ uriPath = "", 128 | uriQuery = "", 129 | uriFragment = "" } 130 | _ -> Nothing 131 | result <- if mime == "text/css" 132 | then cssURLs media cssSourceURL (takeDirectory src) raw' 133 | else return raw' 134 | return (result, mime) 135 | 136 | -- | Convert HTML into self-contained HTML, incorporating images, 137 | -- scripts, and CSS using data: URIs. 138 | makeSelfContained :: WriterOptions -> String -> IO String 139 | makeSelfContained opts inp = do 140 | let tags = parseTags inp 141 | out' <- mapM (convertTag (writerMediaBag opts) (writerSourceURL opts)) tags 142 | return $ renderTags' out' 143 | -------------------------------------------------------------------------------- /src/Text/Pandoc/Slides.hs: -------------------------------------------------------------------------------- 1 | {- 2 | Copyright (C) 2012-2014 John MacFarlane 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program; if not, write to the Free Software 16 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | -} 18 | 19 | {- | 20 | Module : Text.Pandoc.Slides 21 | Copyright : Copyright (C) 2012-2014 John MacFarlane 22 | License : GNU GPL, version 2 or above 23 | 24 | Maintainer : John MacFarlane 25 | Stability : alpha 26 | Portability : portable 27 | 28 | Utility functions for splitting documents into slides for slide 29 | show formats (dzslides, revealjs, s5, slidy, slideous, beamer). 30 | -} 31 | module Text.Pandoc.Slides ( getSlideLevel, prepSlides ) where 32 | import Text.Pandoc.Definition 33 | 34 | -- | Find level of header that starts slides (defined as the least header 35 | -- level that occurs before a non-header/non-hrule in the blocks). 36 | getSlideLevel :: [Block] -> Int 37 | getSlideLevel = go 6 38 | where go least (Header n _ _ : x : xs) 39 | | n < least && nonHOrHR x = go n xs 40 | | otherwise = go least (x:xs) 41 | go least (_ : xs) = go least xs 42 | go least [] = least 43 | nonHOrHR (Header _ _ _) = False 44 | nonHOrHR (HorizontalRule) = False 45 | nonHOrHR _ = True 46 | 47 | -- | Prepare a block list to be passed to hierarchicalize. 48 | prepSlides :: Int -> [Block] -> [Block] 49 | prepSlides slideLevel = ensureStartWithH . splitHrule . extractRefsHeader 50 | where splitHrule (HorizontalRule : Header n attr xs : ys) 51 | | n == slideLevel = Header slideLevel attr xs : splitHrule ys 52 | splitHrule (HorizontalRule : xs) = Header slideLevel nullAttr [Str "\0"] : 53 | splitHrule xs 54 | splitHrule (x : xs) = x : splitHrule xs 55 | splitHrule [] = [] 56 | extractRefsHeader bs = 57 | case reverse bs of 58 | (Div ("",["references"],[]) (Header n attrs xs : ys) : zs) 59 | -> reverse zs ++ (Header n attrs xs : [Div ("",["references"],[]) ys]) 60 | _ -> bs 61 | ensureStartWithH bs@(Header n _ _:_) 62 | | n <= slideLevel = bs 63 | ensureStartWithH bs = Header slideLevel nullAttr [Str "\0"] : bs 64 | -------------------------------------------------------------------------------- /src/Text/Pandoc/UTF8.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE CPP #-} 2 | {- 3 | Copyright (C) 2010-2014 John MacFarlane 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | -} 19 | 20 | {- | 21 | Module : Text.Pandoc.UTF8 22 | Copyright : Copyright (C) 2010-2014 John MacFarlane 23 | License : GNU GPL, version 2 or above 24 | 25 | Maintainer : John MacFarlane 26 | Stability : alpha 27 | Portability : portable 28 | 29 | UTF-8 aware string IO functions that will work with GHC 6.10, 6.12, or 7. 30 | -} 31 | module Text.Pandoc.UTF8 ( readFile 32 | , writeFile 33 | , getContents 34 | , putStr 35 | , putStrLn 36 | , hPutStr 37 | , hPutStrLn 38 | , hGetContents 39 | , toString 40 | , fromString 41 | , toStringLazy 42 | , fromStringLazy 43 | , encodePath 44 | , decodeArg 45 | ) 46 | 47 | where 48 | 49 | import System.IO hiding (readFile, writeFile, getContents, 50 | putStr, putStrLn, hPutStr, hPutStrLn, hGetContents) 51 | import Prelude hiding (readFile, writeFile, getContents, putStr, putStrLn) 52 | import qualified System.IO as IO 53 | import qualified Data.ByteString.Char8 as B 54 | import qualified Data.ByteString.Lazy as BL 55 | import qualified Data.Text.Encoding as T 56 | import qualified Data.Text as T 57 | import qualified Data.Text.Lazy as TL 58 | import qualified Data.Text.Lazy.Encoding as TL 59 | 60 | readFile :: FilePath -> IO String 61 | readFile f = do 62 | h <- openFile (encodePath f) ReadMode 63 | hGetContents h 64 | 65 | writeFile :: FilePath -> String -> IO () 66 | writeFile f s = withFile (encodePath f) WriteMode $ \h -> hPutStr h s 67 | 68 | getContents :: IO String 69 | getContents = hGetContents stdin 70 | 71 | putStr :: String -> IO () 72 | putStr s = hPutStr stdout s 73 | 74 | putStrLn :: String -> IO () 75 | putStrLn s = hPutStrLn stdout s 76 | 77 | hPutStr :: Handle -> String -> IO () 78 | hPutStr h s = hSetEncoding h utf8 >> IO.hPutStr h s 79 | 80 | hPutStrLn :: Handle -> String -> IO () 81 | hPutStrLn h s = hSetEncoding h utf8 >> IO.hPutStrLn h s 82 | 83 | hGetContents :: Handle -> IO String 84 | hGetContents = fmap toString . B.hGetContents 85 | -- hGetContents h = hSetEncoding h utf8_bom 86 | -- >> hSetNewlineMode h universalNewlineMode 87 | -- >> IO.hGetContents h 88 | 89 | -- | Drop BOM (byte order marker) if present at beginning of string. 90 | -- Note that Data.Text converts the BOM to code point FEFF, zero-width 91 | -- no-break space, so if the string begins with this we strip it off. 92 | dropBOM :: String -> String 93 | dropBOM ('\xFEFF':xs) = xs 94 | dropBOM xs = xs 95 | 96 | -- | Convert UTF8-encoded ByteString to String, also 97 | -- removing '\r' characters. 98 | toString :: B.ByteString -> String 99 | toString = filter (/='\r') . dropBOM . T.unpack . T.decodeUtf8 100 | 101 | fromString :: String -> B.ByteString 102 | fromString = T.encodeUtf8 . T.pack 103 | 104 | -- | Convert UTF8-encoded ByteString to String, also 105 | -- removing '\r' characters. 106 | toStringLazy :: BL.ByteString -> String 107 | toStringLazy = filter (/='\r') . dropBOM . TL.unpack . TL.decodeUtf8 108 | 109 | fromStringLazy :: String -> BL.ByteString 110 | fromStringLazy = TL.encodeUtf8 . TL.pack 111 | 112 | encodePath :: FilePath -> FilePath 113 | decodeArg :: String -> String 114 | #if MIN_VERSION_base(4,4,0) 115 | encodePath = id 116 | decodeArg = id 117 | #else 118 | encodePath = B.unpack . fromString 119 | decodeArg = toString . B.pack 120 | #endif 121 | -------------------------------------------------------------------------------- /src/Text/Pandoc/UUID.hs: -------------------------------------------------------------------------------- 1 | {- 2 | Copyright (C) 2010-2014 John MacFarlane 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program; if not, write to the Free Software 16 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | -} 18 | 19 | {- | 20 | Module : Text.Pandoc.UUID 21 | Copyright : Copyright (C) 2010-2014 John MacFarlane 22 | License : GNU GPL, version 2 or above 23 | 24 | Maintainer : John MacFarlane 25 | Stability : alpha 26 | Portability : portable 27 | 28 | UUID generation using Version 4 (random method) described 29 | in RFC4122. See http://tools.ietf.org/html/rfc4122 30 | -} 31 | 32 | module Text.Pandoc.UUID ( UUID, getRandomUUID ) where 33 | 34 | import Text.Printf ( printf ) 35 | import System.Random ( randomIO ) 36 | import Data.Word 37 | import Data.Bits ( setBit, clearBit ) 38 | import Control.Monad ( liftM ) 39 | 40 | data UUID = UUID Word8 Word8 Word8 Word8 Word8 Word8 Word8 Word8 41 | Word8 Word8 Word8 Word8 Word8 Word8 Word8 Word8 42 | 43 | instance Show UUID where 44 | show (UUID a b c d e f g h i j k l m n o p) = 45 | "urn:uuid:" ++ 46 | printf "%02x" a ++ 47 | printf "%02x" b ++ 48 | printf "%02x" c ++ 49 | printf "%02x" d ++ 50 | "-" ++ 51 | printf "%02x" e ++ 52 | printf "%02x" f ++ 53 | "-" ++ 54 | printf "%02x" g ++ 55 | printf "%02x" h ++ 56 | "-" ++ 57 | printf "%02x" i ++ 58 | printf "%02x" j ++ 59 | "-" ++ 60 | printf "%02x" k ++ 61 | printf "%02x" l ++ 62 | printf "%02x" m ++ 63 | printf "%02x" n ++ 64 | printf "%02x" o ++ 65 | printf "%02x" p 66 | 67 | getRandomUUID :: IO UUID 68 | getRandomUUID = do 69 | let getRN :: a -> IO Word8 70 | getRN _ = liftM fromIntegral (randomIO :: IO Int) 71 | [a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p] <- mapM getRN ([1..16] :: [Int]) 72 | -- set variant 73 | let i' = i `setBit` 7 `clearBit` 6 74 | -- set version (0100 for random) 75 | let g' = g `clearBit` 7 `setBit` 6 `clearBit` 5 `clearBit` 4 76 | return $ UUID a b c d e f g' h i' j k l m n o p 77 | 78 | -------------------------------------------------------------------------------- /src/Text/Pandoc/Writers/Native.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE OverloadedStrings #-} 2 | {- 3 | Copyright (C) 2006-2014 John MacFarlane 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | -} 19 | 20 | {- | 21 | Module : Text.Pandoc.Writers.Native 22 | Copyright : Copyright (C) 2006-2014 John MacFarlane 23 | License : GNU GPL, version 2 or above 24 | 25 | Maintainer : John MacFarlane 26 | Stability : alpha 27 | Portability : portable 28 | 29 | Conversion of a 'Pandoc' document to a string representation. 30 | 31 | Note: If @writerStandalone@ is @False@, only the document body 32 | is represented; otherwise, the full 'Pandoc' document, including the 33 | metadata. 34 | -} 35 | module Text.Pandoc.Writers.Native ( writeNative ) 36 | where 37 | import Text.Pandoc.Options ( WriterOptions(..) ) 38 | import Data.List ( intersperse ) 39 | import Text.Pandoc.Definition 40 | import Text.Pandoc.Pretty 41 | 42 | prettyList :: [Doc] -> Doc 43 | prettyList ds = 44 | "[" <> (cat $ intersperse (cr <> ",") $ map (nest 1) ds) <> "]" 45 | 46 | -- | Prettyprint Pandoc block element. 47 | prettyBlock :: Block -> Doc 48 | prettyBlock (BlockQuote blocks) = 49 | "BlockQuote" $$ prettyList (map prettyBlock blocks) 50 | prettyBlock (OrderedList attribs blockLists) = 51 | "OrderedList" <> space <> text (show attribs) $$ 52 | (prettyList $ map (prettyList . map prettyBlock) blockLists) 53 | prettyBlock (BulletList blockLists) = 54 | "BulletList" $$ 55 | (prettyList $ map (prettyList . map prettyBlock) blockLists) 56 | prettyBlock (DefinitionList items) = "DefinitionList" $$ 57 | (prettyList $ map deflistitem items) 58 | where deflistitem (term, defs) = "(" <> text (show term) <> "," <> cr <> 59 | nest 1 (prettyList $ map (prettyList . map prettyBlock) defs) <> ")" 60 | prettyBlock (Table caption aligns widths header rows) = 61 | "Table " <> text (show caption) <> " " <> text (show aligns) <> " " <> 62 | text (show widths) $$ 63 | prettyRow header $$ 64 | prettyList (map prettyRow rows) 65 | where prettyRow cols = prettyList (map (prettyList . map prettyBlock) cols) 66 | prettyBlock block = text $ show block 67 | 68 | -- | Prettyprint Pandoc document. 69 | writeNative :: WriterOptions -> Pandoc -> String 70 | writeNative opts (Pandoc meta blocks) = 71 | let colwidth = if writerWrapText opts 72 | then Just $ writerColumns opts 73 | else Nothing 74 | withHead = if writerStandalone opts 75 | then \bs -> text ("Pandoc (" ++ show meta ++ ")") $$ 76 | bs $$ cr 77 | else id 78 | in render colwidth $ withHead $ prettyList $ map prettyBlock blocks 79 | -------------------------------------------------------------------------------- /src/Text/Pandoc/Writers/Shared.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE OverloadedStrings #-} 2 | {- 3 | Copyright (C) 2013-2014 John MacFarlane 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | -} 19 | 20 | {- | 21 | Module : Text.Pandoc.Writers.Shared 22 | Copyright : Copyright (C) 2013-2014 John MacFarlane 23 | License : GNU GPL, version 2 or above 24 | 25 | Maintainer : John MacFarlane 26 | Stability : alpha 27 | Portability : portable 28 | 29 | Shared utility functions for pandoc writers. 30 | -} 31 | module Text.Pandoc.Writers.Shared ( 32 | metaToJSON 33 | , getField 34 | , setField 35 | , defField 36 | , tagWithAttrs 37 | , fixDisplayMath 38 | ) 39 | where 40 | import Text.Pandoc.Definition 41 | import Text.Pandoc.Pretty 42 | import Text.Pandoc.XML (escapeStringForXML) 43 | import Control.Monad (liftM) 44 | import Text.Pandoc.Options (WriterOptions(..)) 45 | import qualified Data.HashMap.Strict as H 46 | import qualified Data.Map as M 47 | import qualified Data.Text as T 48 | import Data.Aeson (FromJSON(..), fromJSON, ToJSON (..), Value(Object), Result(..)) 49 | import qualified Data.Traversable as Traversable 50 | import Data.List ( groupBy ) 51 | 52 | -- | Create JSON value for template from a 'Meta' and an association list 53 | -- of variables, specified at the command line or in the writer. 54 | -- Variables overwrite metadata fields with the same names. 55 | -- If multiple variables are set with the same name, a list is 56 | -- assigned. 57 | metaToJSON :: Monad m 58 | => WriterOptions 59 | -> ([Block] -> m String) 60 | -> ([Inline] -> m String) 61 | -> Meta 62 | -> m Value 63 | metaToJSON opts blockWriter inlineWriter (Meta metamap) 64 | | writerStandalone opts = do 65 | let baseContext = foldl (\acc (x,y) -> setField x y acc) (Object H.empty) 66 | $ writerVariables opts 67 | renderedMap <- Traversable.mapM 68 | (metaValueToJSON blockWriter inlineWriter) 69 | metamap 70 | return $ M.foldWithKey defField baseContext renderedMap 71 | | otherwise = return (Object H.empty) 72 | 73 | metaValueToJSON :: Monad m 74 | => ([Block] -> m String) 75 | -> ([Inline] -> m String) 76 | -> MetaValue 77 | -> m Value 78 | metaValueToJSON blockWriter inlineWriter (MetaMap metamap) = liftM toJSON $ 79 | Traversable.mapM (metaValueToJSON blockWriter inlineWriter) metamap 80 | metaValueToJSON blockWriter inlineWriter (MetaList xs) = liftM toJSON $ 81 | Traversable.mapM (metaValueToJSON blockWriter inlineWriter) xs 82 | metaValueToJSON _ _ (MetaBool b) = return $ toJSON b 83 | metaValueToJSON _ _ (MetaString s) = return $ toJSON s 84 | metaValueToJSON blockWriter _ (MetaBlocks bs) = liftM toJSON $ blockWriter bs 85 | metaValueToJSON _ inlineWriter (MetaInlines bs) = liftM toJSON $ inlineWriter bs 86 | 87 | -- | Retrieve a field value from a JSON object. 88 | getField :: FromJSON a 89 | => String 90 | -> Value 91 | -> Maybe a 92 | getField field (Object hashmap) = do 93 | result <- H.lookup (T.pack field) hashmap 94 | case fromJSON result of 95 | Success x -> return x 96 | _ -> fail "Could not convert from JSON" 97 | getField _ _ = fail "Not a JSON object" 98 | 99 | setField :: ToJSON a 100 | => String 101 | -> a 102 | -> Value 103 | -> Value 104 | -- | Set a field of a JSON object. If the field already has a value, 105 | -- convert it into a list with the new value appended to the old value(s). 106 | -- This is a utility function to be used in preparing template contexts. 107 | setField field val (Object hashmap) = 108 | Object $ H.insertWith combine (T.pack field) (toJSON val) hashmap 109 | where combine newval oldval = 110 | case fromJSON oldval of 111 | Success xs -> toJSON $ xs ++ [newval] 112 | _ -> toJSON [oldval, newval] 113 | setField _ _ x = x 114 | 115 | defField :: ToJSON a 116 | => String 117 | -> a 118 | -> Value 119 | -> Value 120 | -- | Set a field of a JSON object if it currently has no value. 121 | -- If it has a value, do nothing. 122 | -- This is a utility function to be used in preparing template contexts. 123 | defField field val (Object hashmap) = 124 | Object $ H.insertWith f (T.pack field) (toJSON val) hashmap 125 | where f _newval oldval = oldval 126 | defField _ _ x = x 127 | 128 | -- Produce an HTML tag with the given pandoc attributes. 129 | tagWithAttrs :: String -> Attr -> Doc 130 | tagWithAttrs tag (ident,classes,kvs) = hsep 131 | ["<" <> text tag 132 | ,if null ident 133 | then empty 134 | else "id=" <> doubleQuotes (text ident) 135 | ,if null classes 136 | then empty 137 | else "class=" <> doubleQuotes (text (unwords classes)) 138 | ,hsep (map (\(k,v) -> text k <> "=" <> 139 | doubleQuotes (text (escapeStringForXML v))) kvs) 140 | ] <> ">" 141 | 142 | isDisplayMath :: Inline -> Bool 143 | isDisplayMath (Math (DisplayMath _) _) = True 144 | isDisplayMath _ = False 145 | 146 | stripLeadingTrailingSpace :: [Inline] -> [Inline] 147 | stripLeadingTrailingSpace = go . reverse . go . reverse 148 | where go (Space:xs) = xs 149 | go xs = xs 150 | 151 | -- Put display math in its own block (for ODT/DOCX). 152 | fixDisplayMath :: Block -> Block 153 | fixDisplayMath (Plain lst) 154 | | any isDisplayMath lst && not (all isDisplayMath lst) = 155 | -- chop into several paragraphs so each displaymath is its own 156 | Div ("",["math"],[]) $ map (Plain . stripLeadingTrailingSpace) $ 157 | groupBy (\x y -> (isDisplayMath x && isDisplayMath y) || 158 | not (isDisplayMath x || isDisplayMath y)) lst 159 | fixDisplayMath (Para lst) 160 | | any isDisplayMath lst && not (all isDisplayMath lst) = 161 | -- chop into several paragraphs so each displaymath is its own 162 | Div ("",["math"],[]) $ map (Para . stripLeadingTrailingSpace) $ 163 | groupBy (\x y -> (isDisplayMath x && isDisplayMath y) || 164 | not (isDisplayMath x || isDisplayMath y)) lst 165 | fixDisplayMath x = x 166 | -------------------------------------------------------------------------------- /src/Text/Pandoc/XML.hs: -------------------------------------------------------------------------------- 1 | {- 2 | Copyright (C) 2006-2014 John MacFarlane 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program; if not, write to the Free Software 16 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | -} 18 | 19 | {- | 20 | Module : Text.Pandoc.XML 21 | Copyright : Copyright (C) 2006-2014 John MacFarlane 22 | License : GNU GPL, version 2 or above 23 | 24 | Maintainer : John MacFarlane 25 | Stability : alpha 26 | Portability : portable 27 | 28 | Functions for escaping and formatting XML. 29 | -} 30 | module Text.Pandoc.XML ( escapeCharForXML, 31 | escapeStringForXML, 32 | inTags, 33 | selfClosingTag, 34 | inTagsSimple, 35 | inTagsIndented, 36 | toEntities, 37 | fromEntities ) where 38 | 39 | import Text.Pandoc.Pretty 40 | import Data.Char (ord, isAscii, isSpace) 41 | import Text.Pandoc.Compat.TagSoupEntity (lookupEntity) 42 | 43 | -- | Escape one character as needed for XML. 44 | escapeCharForXML :: Char -> String 45 | escapeCharForXML x = case x of 46 | '&' -> "&" 47 | '<' -> "<" 48 | '>' -> ">" 49 | '"' -> """ 50 | c -> [c] 51 | 52 | -- | Escape string as needed for XML. Entity references are not preserved. 53 | escapeStringForXML :: String -> String 54 | escapeStringForXML = concatMap escapeCharForXML 55 | 56 | -- | Escape newline characters as 57 | escapeNls :: String -> String 58 | escapeNls (x:xs) 59 | | x == '\n' = " " ++ escapeNls xs 60 | | otherwise = x : escapeNls xs 61 | escapeNls [] = [] 62 | 63 | -- | Return a text object with a string of formatted XML attributes. 64 | attributeList :: [(String, String)] -> Doc 65 | attributeList = hcat . map 66 | (\(a, b) -> text (' ' : escapeStringForXML a ++ "=\"" ++ 67 | escapeNls (escapeStringForXML b) ++ "\"")) 68 | 69 | -- | Put the supplied contents between start and end tags of tagType, 70 | -- with specified attributes and (if specified) indentation. 71 | inTags:: Bool -> String -> [(String, String)] -> Doc -> Doc 72 | inTags isIndented tagType attribs contents = 73 | let openTag = char '<' <> text tagType <> attributeList attribs <> 74 | char '>' 75 | closeTag = text " text tagType <> char '>' 76 | in if isIndented 77 | then openTag $$ nest 2 contents $$ closeTag 78 | else openTag <> contents <> closeTag 79 | 80 | -- | Return a self-closing tag of tagType with specified attributes 81 | selfClosingTag :: String -> [(String, String)] -> Doc 82 | selfClosingTag tagType attribs = 83 | char '<' <> text tagType <> attributeList attribs <> text " />" 84 | 85 | -- | Put the supplied contents between start and end tags of tagType. 86 | inTagsSimple :: String -> Doc -> Doc 87 | inTagsSimple tagType = inTags False tagType [] 88 | 89 | -- | Put the supplied contents in indented block btw start and end tags. 90 | inTagsIndented :: String -> Doc -> Doc 91 | inTagsIndented tagType = inTags True tagType [] 92 | 93 | -- | Escape all non-ascii characters using numerical entities. 94 | toEntities :: String -> String 95 | toEntities [] = "" 96 | toEntities (c:cs) 97 | | isAscii c = c : toEntities cs 98 | | otherwise = "&#" ++ show (ord c) ++ ";" ++ toEntities cs 99 | 100 | -- Unescapes XML entities 101 | fromEntities :: String -> String 102 | fromEntities ('&':xs) = 103 | case lookupEntity ent of 104 | Just c -> c : fromEntities rest 105 | Nothing -> '&' : fromEntities xs 106 | where (ent, rest) = case break (\c -> isSpace c || c == ';') xs of 107 | (zs,';':ys) -> (zs,ys) 108 | _ -> ("",xs) 109 | fromEntities (x:xs) = x : fromEntities xs 110 | fromEntities [] = [] 111 | -------------------------------------------------------------------------------- /tests/Tests/Arbitrary.hs: -------------------------------------------------------------------------------- 1 | {-# OPTIONS_GHC -fno-warn-orphans #-} 2 | {-# LANGUAGE TypeSynonymInstances, FlexibleInstances, ScopedTypeVariables #-} 3 | -- provides Arbitrary instance for Pandoc types 4 | module Tests.Arbitrary () 5 | where 6 | import Test.QuickCheck.Gen 7 | import Test.QuickCheck.Arbitrary 8 | import Control.Monad (liftM, liftM2) 9 | import Text.Pandoc.Definition 10 | import Text.Pandoc.Shared (normalize, escapeURI) 11 | import Text.Pandoc.Builder 12 | 13 | realString :: Gen String 14 | realString = resize 8 $ listOf $ frequency [ (9, elements [' '..'\127']) 15 | , (1, elements ['\128'..'\9999']) ] 16 | 17 | arbAttr :: Gen Attr 18 | arbAttr = do 19 | id' <- elements ["","loc"] 20 | classes <- elements [[],["haskell"],["c","numberLines"]] 21 | keyvals <- elements [[],[("start","22")],[("a","11"),("b_2","a b c")]] 22 | return (id',classes,keyvals) 23 | 24 | instance Arbitrary Inlines where 25 | arbitrary = liftM (fromList :: [Inline] -> Inlines) arbitrary 26 | 27 | instance Arbitrary Blocks where 28 | arbitrary = liftM (fromList :: [Block] -> Blocks) arbitrary 29 | 30 | instance Arbitrary Inline where 31 | arbitrary = resize 3 $ arbInline 2 32 | 33 | arbInlines :: Int -> Gen [Inline] 34 | arbInlines n = listOf1 (arbInline n) `suchThat` (not . startsWithSpace) 35 | where startsWithSpace (Space:_) = True 36 | startsWithSpace _ = False 37 | 38 | -- restrict to 3 levels of nesting max; otherwise we get 39 | -- bogged down in indefinitely large structures 40 | arbInline :: Int -> Gen Inline 41 | arbInline n = frequency $ [ (60, liftM Str realString) 42 | , (60, return Space) 43 | , (10, liftM2 Code arbAttr realString) 44 | , (5, elements [ RawInline (Format "html") "" 45 | , RawInline (Format "latex") "\\my{command}" ]) 46 | ] ++ [ x | x <- nesters, n > 1] 47 | where nesters = [ (10, liftM Emph $ arbInlines (n-1)) 48 | , (10, liftM Strong $ arbInlines (n-1)) 49 | , (10, liftM Strikeout $ arbInlines (n-1)) 50 | , (10, liftM Superscript $ arbInlines (n-1)) 51 | , (10, liftM Subscript $ arbInlines (n-1)) 52 | , (10, liftM SmallCaps $ arbInlines (n-1)) 53 | , (10, do x1 <- arbitrary 54 | x2 <- arbInlines (n-1) 55 | return $ Quoted x1 x2) 56 | , (10, do x1 <- arbitrary 57 | x2 <- realString 58 | return $ Math x1 x2) 59 | , (10, do x1 <- arbInlines (n-1) 60 | x3 <- realString 61 | x2 <- liftM escapeURI realString 62 | return $ Link x1 (x2,x3)) 63 | , (10, do x1 <- arbInlines (n-1) 64 | x3 <- realString 65 | x2 <- liftM escapeURI realString 66 | atr <- arbAttr 67 | return $ Image atr x1 (x2,x3)) 68 | , (2, liftM2 Cite arbitrary (arbInlines 1)) 69 | , (2, liftM Note $ resize 3 $ listOf1 $ arbBlock (n-1)) 70 | ] 71 | 72 | instance Arbitrary Block where 73 | arbitrary = resize 3 $ arbBlock 2 74 | 75 | arbBlock :: Int -> Gen Block 76 | arbBlock n = frequency $ [ (10, liftM Plain $ arbInlines (n-1)) 77 | , (15, liftM Para $ arbInlines (n-1)) 78 | , (5, liftM2 CodeBlock arbAttr realString) 79 | , (2, elements [ RawBlock (Format "html") 80 | "
\n*&*\n
" 81 | , RawBlock (Format "latex") 82 | "\\begin[opt]{env}\nhi\n{\\end{env}" 83 | ]) 84 | , (5, do x1 <- choose (1 :: Int, 6) 85 | x2 <- arbInlines (n-1) 86 | return (Header x1 nullAttr x2)) 87 | , (2, return HorizontalRule) 88 | ] ++ [x | x <- nesters, n > 0] 89 | where nesters = [ (5, liftM BlockQuote $ listOf1 $ arbBlock (n-1)) 90 | , (5, do x2 <- arbitrary 91 | x3 <- arbitrary 92 | x1 <- arbitrary `suchThat` (> 0) 93 | x4 <- listOf1 $ listOf1 $ arbBlock (n-1) 94 | return $ OrderedList (x1,x2,x3) x4 ) 95 | , (5, liftM BulletList $ (listOf1 $ listOf1 $ arbBlock (n-1))) 96 | , (5, do items <- listOf1 $ do 97 | x1 <- listOf1 $ listOf1 $ arbBlock (n-1) 98 | x2 <- arbInlines (n-1) 99 | return (x2,x1) 100 | return $ DefinitionList items) 101 | , (2, do rs <- choose (1 :: Int, 4) 102 | cs <- choose (1 :: Int, 4) 103 | x1 <- arbInlines (n-1) 104 | x2 <- vector cs 105 | x3 <- vectorOf cs $ elements [0, 0.25] 106 | x4 <- vectorOf cs $ listOf $ arbBlock (n-1) 107 | x5 <- vectorOf rs $ vectorOf cs 108 | $ listOf $ arbBlock (n-1) 109 | return (Table x1 x2 x3 x4 x5)) 110 | ] 111 | 112 | instance Arbitrary Pandoc where 113 | arbitrary = resize 8 $ liftM normalize 114 | $ liftM2 Pandoc arbitrary arbitrary 115 | 116 | instance Arbitrary CitationMode where 117 | arbitrary 118 | = do x <- choose (0 :: Int, 2) 119 | case x of 120 | 0 -> return AuthorInText 121 | 1 -> return SuppressAuthor 122 | 2 -> return NormalCitation 123 | _ -> error "FATAL ERROR: Arbitrary instance, logic bug" 124 | 125 | instance Arbitrary Citation where 126 | arbitrary 127 | = do x1 <- listOf $ elements $ ['a'..'z'] ++ ['0'..'9'] ++ ['_'] 128 | x2 <- arbInlines 1 129 | x3 <- arbInlines 1 130 | x4 <- arbitrary 131 | x5 <- arbitrary 132 | x6 <- arbitrary 133 | return (Citation x1 x2 x3 x4 x5 x6) 134 | 135 | instance Arbitrary MathType where 136 | arbitrary 137 | = do x <- choose (0 :: Int, 1) 138 | case x of 139 | 0 -> liftM DisplayMath arbAttr 140 | 1 -> return InlineMath 141 | _ -> error "FATAL ERROR: Arbitrary instance, logic bug" 142 | 143 | instance Arbitrary QuoteType where 144 | arbitrary 145 | = do x <- choose (0 :: Int, 1) 146 | case x of 147 | 0 -> return SingleQuote 148 | 1 -> return DoubleQuote 149 | _ -> error "FATAL ERROR: Arbitrary instance, logic bug" 150 | 151 | instance Arbitrary Meta where 152 | arbitrary 153 | = do (x1 :: Inlines) <- arbitrary 154 | (x2 :: [Inlines]) <- liftM (filter (not . isNull)) arbitrary 155 | (x3 :: Inlines) <- arbitrary 156 | return $ setMeta "title" x1 157 | $ setMeta "author" x2 158 | $ setMeta "date" x3 159 | $ nullMeta 160 | 161 | instance Arbitrary Alignment where 162 | arbitrary 163 | = do x <- choose (0 :: Int, 3) 164 | case x of 165 | 0 -> return AlignLeft 166 | 1 -> return AlignRight 167 | 2 -> return AlignCenter 168 | 3 -> return AlignDefault 169 | _ -> error "FATAL ERROR: Arbitrary instance, logic bug" 170 | 171 | instance Arbitrary ListNumberStyle where 172 | arbitrary 173 | = do x <- choose (0 :: Int, 6) 174 | case x of 175 | 0 -> return DefaultStyle 176 | 1 -> return Example 177 | 2 -> return Decimal 178 | 3 -> return LowerRoman 179 | 4 -> return UpperRoman 180 | 5 -> return LowerAlpha 181 | 6 -> return UpperAlpha 182 | _ -> error "FATAL ERROR: Arbitrary instance, logic bug" 183 | 184 | instance Arbitrary ListNumberDelim where 185 | arbitrary 186 | = do x <- choose (0 :: Int, 3) 187 | case x of 188 | 0 -> return DefaultDelim 189 | 1 -> return Period 190 | 2 -> return OneParen 191 | 3 -> return TwoParens 192 | _ -> error "FATAL ERROR: Arbitrary instance, logic bug" 193 | 194 | -------------------------------------------------------------------------------- /tests/Tests/Helpers.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE TypeSynonymInstances, FlexibleInstances #-} 2 | -- Utility functions for the test suite. 3 | 4 | module Tests.Helpers ( test 5 | , (=?>) 6 | , property 7 | , ToString(..) 8 | , ToPandoc(..) 9 | ) 10 | where 11 | 12 | import Text.Pandoc.Definition 13 | import Text.Pandoc.Builder (Inlines, Blocks, doc, plain) 14 | import Test.Framework 15 | import Test.Framework.Providers.HUnit 16 | import Test.Framework.Providers.QuickCheck2 17 | import Test.HUnit (assertBool) 18 | import Text.Pandoc.Shared (normalize, trimr) 19 | import Text.Pandoc.Options 20 | import Text.Pandoc.Writers.Native (writeNative) 21 | import qualified Test.QuickCheck.Property as QP 22 | import Data.Algorithm.Diff 23 | import qualified Data.Map as M 24 | 25 | test :: (ToString a, ToString b, ToString c) 26 | => (a -> b) -- ^ function to test 27 | -> String -- ^ name of test case 28 | -> (a, c) -- ^ (input, expected value) 29 | -> Test 30 | test fn name (input, expected) = 31 | testCase name $ assertBool msg (actual' == expected') 32 | where msg = nl ++ dashes "input" ++ nl ++ input' ++ nl ++ 33 | dashes "result" ++ nl ++ 34 | unlines (map vividize diff) ++ 35 | dashes "" 36 | nl = "\n" 37 | input' = toString input 38 | actual' = lines $ toString $ fn input 39 | expected' = lines $ toString expected 40 | diff = getDiff expected' actual' 41 | dashes "" = replicate 72 '-' 42 | dashes x = replicate (72 - length x - 5) '-' ++ " " ++ x ++ " ---" 43 | 44 | vividize :: Diff String -> String 45 | vividize (Both s _) = " " ++ s 46 | vividize (First s) = "- " ++ s 47 | vividize (Second s) = "+ " ++ s 48 | 49 | property :: QP.Testable a => TestName -> a -> Test 50 | property = testProperty 51 | 52 | infix 5 =?> 53 | (=?>) :: a -> b -> (a,b) 54 | x =?> y = (x, y) 55 | 56 | class ToString a where 57 | toString :: a -> String 58 | 59 | instance ToString Pandoc where 60 | toString d = writeNative def{ writerStandalone = s } $ toPandoc d 61 | where s = case d of 62 | (Pandoc (Meta m) _) 63 | | M.null m -> False 64 | | otherwise -> True 65 | 66 | instance ToString Blocks where 67 | toString = writeNative def . toPandoc 68 | 69 | instance ToString Inlines where 70 | toString = trimr . writeNative def . toPandoc 71 | 72 | instance ToString String where 73 | toString = id 74 | 75 | class ToPandoc a where 76 | toPandoc :: a -> Pandoc 77 | 78 | instance ToPandoc Pandoc where 79 | toPandoc = normalize 80 | 81 | instance ToPandoc Blocks where 82 | toPandoc = normalize . doc 83 | 84 | instance ToPandoc Inlines where 85 | toPandoc = normalize . doc . plain 86 | -------------------------------------------------------------------------------- /tests/Tests/Old.hs: -------------------------------------------------------------------------------- 1 | module Tests.Old (tests) where 2 | 3 | import Test.Framework (testGroup, Test ) 4 | import Test.Framework.Providers.HUnit 5 | import Test.HUnit ( assertBool ) 6 | import System.Environment.Executable (getExecutablePath) 7 | import System.IO ( openTempFile, stderr ) 8 | import System.Process ( runProcess, waitForProcess ) 9 | import System.FilePath ( (), (<.>), takeDirectory, splitDirectories, joinPath ) 10 | import System.Directory 11 | import System.Exit 12 | import Data.Algorithm.Diff 13 | import Text.Pandoc.Shared ( normalize ) 14 | import Text.Pandoc.Options 15 | import Text.Pandoc.Writers.Native ( writeNative ) 16 | import Text.Pandoc.Readers.Native ( readNative ) 17 | import Prelude hiding ( readFile ) 18 | import qualified Data.ByteString.Lazy as B 19 | import Text.Pandoc.UTF8 (toStringLazy) 20 | import Text.Printf 21 | 22 | readFileUTF8 :: FilePath -> IO String 23 | readFileUTF8 f = B.readFile f >>= return . toStringLazy 24 | 25 | data TestResult = TestPassed 26 | | TestError ExitCode 27 | | TestFailed String FilePath [Diff String] 28 | deriving (Eq) 29 | 30 | instance Show TestResult where 31 | show TestPassed = "PASSED" 32 | show (TestError ec) = "ERROR " ++ show ec 33 | show (TestFailed cmd file d) = '\n' : dash ++ 34 | "\n--- " ++ file ++ 35 | "\n+++ " ++ cmd ++ "\n" ++ showDiff (1,1) d ++ 36 | dash 37 | where dash = replicate 72 '-' 38 | 39 | showDiff :: (Int,Int) -> [Diff String] -> String 40 | showDiff _ [] = "" 41 | showDiff (l,r) (First ln : ds) = 42 | printf "+%4d " l ++ ln ++ "\n" ++ showDiff (l+1,r) ds 43 | showDiff (l,r) (Second ln : ds) = 44 | printf "-%4d " r ++ ln ++ "\n" ++ showDiff (l,r+1) ds 45 | showDiff (l,r) (Both _ _ : ds) = 46 | showDiff (l+1,r+1) ds 47 | 48 | tests :: [Test] 49 | tests = [ testGroup "markdown" 50 | [ testGroup "writer" 51 | $ writerTests "markdown" ++ lhsWriterTests "markdown" 52 | , testGroup "reader" 53 | [ test "basic" ["-r", "markdown", "-w", "native", "-s", "-S"] 54 | "testsuite.txt" "testsuite.native" 55 | , test "tables" ["-r", "markdown", "-w", "native", "--columns=80"] 56 | "tables.txt" "tables.native" 57 | , test "pipe tables" ["-r", "markdown", "-w", "native", "--columns=80"] 58 | "pipe-tables.txt" "pipe-tables.native" 59 | , test "more" ["-r", "markdown", "-w", "native", "-S"] 60 | "markdown-reader-more.txt" "markdown-reader-more.native" 61 | , test "scholdoc" ["-r", "markdown_scholarly", "-w", "native", "-s", "-S", "-R"] 62 | "scholdoc.txt" "scholdoc.native" 63 | , lhsReaderTest "markdown+lhs" 64 | ] 65 | , testGroup "citations" 66 | [ test "citations" ["-r", "markdown", "-w", "native"] 67 | "markdown-citations.txt" "markdown-citations.native" 68 | ] 69 | ] 70 | , testGroup "latex" 71 | [ testGroup "writer" (writerTests "latex" ++ lhsWriterTests "latex" ++ 72 | [ test "scholdoc" ["-r", "markdown_scholarly", "-w", "latex", "-S", "-R", 73 | "--chapters", "--columns=72"] 74 | "scholdoc.txt" "scholdoc.latex" 75 | ]) 76 | ] 77 | , testGroup "html" 78 | [ testGroup "writer" (writerTests "html" ++ lhsWriterTests "html" ++ 79 | [ test "scholdoc" ["-r", "markdown_scholarly", "-w", "html5", "-S", "-R", 80 | "--template=scholmdTemplate_bodyOnly.html5", 81 | "--mathjax", "--no-mathjax-cdn", "--columns=72"] 82 | "scholdoc.txt" "scholdoc.html" 83 | ]) 84 | ] 85 | , testGroup "s5" 86 | [ s5WriterTest "basic" ["-s"] "s5" 87 | , s5WriterTest "fancy" ["-s","-m","-i"] "s5" 88 | , s5WriterTest "fragment" [] "html" 89 | , s5WriterTest "inserts" ["-s", "-H", "insert", 90 | "-B", "insert", "-A", "insert", "-c", "main.css"] "html" 91 | ] 92 | , testGroup "native" 93 | [ testGroup "writer" $ writerTests "native" 94 | , test "reader" ["-r", "native", "-w", "native", "-s"] 95 | "testsuite.native" "testsuite.native" 96 | ] 97 | , testGroup "haddock" 98 | [ testGroup "writer" $ writerTests "haddock" 99 | ] 100 | , testGroup "other writers" $ map (\f -> testGroup f $ writerTests f) 101 | [ "man" , "plain" 102 | ] 103 | ] 104 | 105 | -- makes sure file is fully closed after reading 106 | readFile' :: FilePath -> IO String 107 | readFile' f = do s <- readFileUTF8 f 108 | return $! (length s `seq` s) 109 | 110 | lhsWriterTests :: String -> [Test] 111 | lhsWriterTests format 112 | = [ t "lhs to normal" format 113 | , t "lhs to lhs" (format ++ "+lhs") 114 | ] 115 | where 116 | t n f = test n ["--columns=78", "-r", "native", "-s", "-w", f] 117 | "lhs-test.native" ("lhs-test" <.> f) 118 | 119 | lhsReaderTest :: String -> Test 120 | lhsReaderTest format = 121 | testWithNormalize normalizer "lhs" ["-r", format, "-w", "native"] 122 | ("lhs-test" <.> format) norm 123 | where normalizer = writeNative def . normalize . readNative 124 | norm = if format == "markdown+lhs" 125 | then "lhs-test-markdown.native" 126 | else "lhs-test.native" 127 | 128 | writerTests :: String -> [Test] 129 | writerTests format 130 | = [ test "basic" (opts ++ ["-s"]) "testsuite.native" ("writer" <.> format) 131 | , test "tables" opts "tables.native" ("tables" <.> format) 132 | ] 133 | where 134 | opts = ["-r", "native", "-w", format, "--columns=78"] 135 | 136 | s5WriterTest :: String -> [String] -> String -> Test 137 | s5WriterTest modifier opts format 138 | = test (format ++ " writer (" ++ modifier ++ ")") 139 | (["-r", "native", "-w", format] ++ opts) 140 | "s5.native" ("s5-" ++ modifier <.> "html") 141 | 142 | -- | Run a test without normalize function, return True if test passed. 143 | test :: String -- ^ Title of test 144 | -> [String] -- ^ Options to pass to scholdoc 145 | -> String -- ^ Input filepath 146 | -> FilePath -- ^ Norm (for test results) filepath 147 | -> Test 148 | test = testWithNormalize id 149 | 150 | -- | Run a test with normalize function, return True if test passed. 151 | testWithNormalize :: (String -> String) -- ^ Normalize function for output 152 | -> String -- ^ Title of test 153 | -> [String] -- ^ Options to pass to scholdoc 154 | -> String -- ^ Input filepath 155 | -> FilePath -- ^ Norm (for test results) filepath 156 | -> Test 157 | testWithNormalize normalizer testname opts inp norm = testCase testname $ do 158 | -- find scholdoc executable relative to test-scholdoc 159 | -- First, try in same directory (e.g. if both in ~/.cabal/bin) 160 | -- Second, try ../scholdoc (e.g. if in dist/XXX/build/test-scholdoc) 161 | scholdocPath <- do 162 | testExePath <- getExecutablePath 163 | let testExeDir = takeDirectory testExePath 164 | found <- doesFileExist (testExeDir "scholdoc") 165 | return $ if found 166 | then testExeDir "scholdoc" 167 | else case splitDirectories testExeDir of 168 | [] -> error "test-scholdoc: empty testExeDir" 169 | xs -> joinPath (init xs) "scholdoc" "scholdoc" 170 | (outputPath, hOut) <- openTempFile "" "scholdoc-test" 171 | let inpPath = inp 172 | let normPath = norm 173 | let options = ["--emulate-pandoc", "--data-dir", ".." "data"] ++ [inpPath] ++ opts 174 | let cmd = scholdocPath ++ " " ++ unwords options 175 | ph <- runProcess scholdocPath options Nothing 176 | (Just [("TMP","."),("LANG","en_US.UTF-8"),("HOME", "./")]) Nothing (Just hOut) 177 | (Just stderr) 178 | ec <- waitForProcess ph 179 | result <- if ec == ExitSuccess 180 | then do 181 | -- filter \r so the tests will work on Windows machines 182 | outputContents <- readFile' outputPath >>= 183 | return . filter (/='\r') . normalizer 184 | normContents <- readFile' normPath >>= 185 | return . filter (/='\r') . normalizer 186 | if outputContents == normContents 187 | then return TestPassed 188 | else return 189 | $ TestFailed cmd normPath 190 | $ getDiff (lines outputContents) (lines normContents) 191 | else return $ TestError ec 192 | removeFile outputPath 193 | assertBool (show result) (result == TestPassed) 194 | -------------------------------------------------------------------------------- /tests/Tests/Shared.hs: -------------------------------------------------------------------------------- 1 | module Tests.Shared (tests) where 2 | 3 | import Text.Pandoc.Definition 4 | import Text.Pandoc.Shared 5 | import Test.Framework 6 | import Tests.Helpers 7 | import Tests.Arbitrary() 8 | import Test.Framework.Providers.HUnit 9 | import Test.HUnit ( assertBool, (@?=) ) 10 | import Text.Pandoc.Builder 11 | import Data.Monoid 12 | import System.FilePath (joinPath) 13 | 14 | tests :: [Test] 15 | tests = [ testGroup "normalize" 16 | [ property "p_normalize_blocks_rt" p_normalize_blocks_rt 17 | , property "p_normalize_inlines_rt" p_normalize_inlines_rt 18 | , property "p_normalize_no_trailing_spaces" 19 | p_normalize_no_trailing_spaces 20 | ] 21 | , testGroup "compactify'DL" 22 | [ testCase "compactify'DL with empty def" $ 23 | assertBool "compactify'DL" 24 | (let x = [(str "word", [para (str "def"), mempty])] 25 | in compactify'DL x == x) 26 | ] 27 | , testGroup "collapseFilePath" testCollapse 28 | ] 29 | 30 | p_normalize_blocks_rt :: [Block] -> Bool 31 | p_normalize_blocks_rt bs = 32 | normalizeBlocks bs == normalizeBlocks (normalizeBlocks bs) 33 | 34 | p_normalize_inlines_rt :: [Inline] -> Bool 35 | p_normalize_inlines_rt ils = 36 | normalizeInlines ils == normalizeInlines (normalizeInlines ils) 37 | 38 | p_normalize_no_trailing_spaces :: [Inline] -> Bool 39 | p_normalize_no_trailing_spaces ils = null ils' || last ils' /= Space 40 | where ils' = normalizeInlines $ ils ++ [Space] 41 | 42 | testCollapse :: [Test] 43 | testCollapse = map (testCase "collapse") 44 | [ (collapseFilePath (joinPath [ ""]) @?= (joinPath [ ""])) 45 | , (collapseFilePath (joinPath [ ".","foo"]) @?= (joinPath [ "foo"])) 46 | , (collapseFilePath (joinPath [ ".",".","..","foo"]) @?= (joinPath [ joinPath ["..", "foo"]])) 47 | , (collapseFilePath (joinPath [ "..","foo"]) @?= (joinPath [ "..","foo"])) 48 | , (collapseFilePath (joinPath [ "","bar","..","baz"]) @?= (joinPath [ "","baz"])) 49 | , (collapseFilePath (joinPath [ "","..","baz"]) @?= (joinPath [ "","..","baz"])) 50 | , (collapseFilePath (joinPath [ ".","foo","..",".","bar","..",".",".","baz"]) @?= (joinPath [ "baz"])) 51 | , (collapseFilePath (joinPath [ ".",""]) @?= (joinPath [ ""])) 52 | , (collapseFilePath (joinPath [ ".",".",""]) @?= (joinPath [ ""])) 53 | , (collapseFilePath (joinPath [ "..",""]) @?= (joinPath [ ".."])) 54 | , (collapseFilePath (joinPath [ "..",".",""]) @?= (joinPath [ ".."])) 55 | , (collapseFilePath (joinPath [ ".","..",""]) @?= (joinPath [ ".."])) 56 | , (collapseFilePath (joinPath [ "..","..",""]) @?= (joinPath [ "..",".."])) 57 | , (collapseFilePath (joinPath [ "parent","foo","baz","..","bar"]) @?= (joinPath [ "parent","foo","bar"])) 58 | , (collapseFilePath (joinPath [ "parent","foo","baz","..","..","bar"]) @?= (joinPath [ "parent","bar"])) 59 | , (collapseFilePath (joinPath [ "parent","foo",".."]) @?= (joinPath [ "parent"])) 60 | , (collapseFilePath (joinPath [ "","parent","foo","..","..","bar"]) @?= (joinPath [ "","bar"])) 61 | , (collapseFilePath (joinPath [ "",".","parent","foo"]) @?= (joinPath [ "","parent","foo"]))] 62 | -------------------------------------------------------------------------------- /tests/Tests/Walk.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE ScopedTypeVariables, FlexibleContexts #-} 2 | module Tests.Walk (tests) where 3 | 4 | import Text.Pandoc.Definition 5 | import Text.Pandoc.Walk 6 | import Test.Framework 7 | import Tests.Helpers 8 | import Data.Char (toUpper) 9 | import Tests.Arbitrary() 10 | import Data.Generics 11 | import Data.Monoid 12 | 13 | tests :: [Test] 14 | tests = [ testGroup "Walk" 15 | [ property "p_walk inlineTrans" (p_walk inlineTrans) 16 | , property "p_walk blockTrans" (p_walk blockTrans) 17 | , property "p_query inlineQuery" (p_query inlineQuery) 18 | , property "p_query blockQuery" (p_query blockQuery) 19 | ] 20 | ] 21 | 22 | p_walk :: (Typeable a, Walkable a Pandoc) 23 | => (a -> a) -> Pandoc -> Bool 24 | p_walk f d = everywhere (mkT f) d == walk f d 25 | 26 | p_query :: (Eq a, Typeable a1, Monoid a, Walkable a1 Pandoc) 27 | => (a1 -> a) -> Pandoc -> Bool 28 | p_query f d = everything mappend (mempty `mkQ` f) d == query f d 29 | 30 | inlineTrans :: Inline -> Inline 31 | inlineTrans (Str xs) = Str $ map toUpper xs 32 | inlineTrans (Emph xs) = Strong xs 33 | inlineTrans x = x 34 | 35 | blockTrans :: Block -> Block 36 | blockTrans (Plain xs) = Para xs 37 | blockTrans (BlockQuote xs) = Div ("",["special"],[]) xs 38 | blockTrans x = x 39 | 40 | inlineQuery :: Inline -> String 41 | inlineQuery (Str xs) = xs 42 | inlineQuery _ = "" 43 | 44 | blockQuery :: Block -> [Int] 45 | blockQuery (Header lev _ _) = [lev] 46 | blockQuery _ = [] 47 | 48 | -------------------------------------------------------------------------------- /tests/Tests/Writers/HTML.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE OverloadedStrings #-} 2 | module Tests.Writers.HTML (tests) where 3 | 4 | import Test.Framework 5 | import Text.Pandoc.Builder 6 | import Text.Pandoc 7 | import Tests.Helpers 8 | import Tests.Arbitrary() 9 | 10 | html :: (ToString a, ToPandoc a) => a -> String 11 | html = writeHtmlString def{ writerWrapText = False } . toPandoc 12 | 13 | {- 14 | "my test" =: X =?> Y 15 | 16 | is shorthand for 17 | 18 | test html "my test" $ X =?> Y 19 | 20 | which is in turn shorthand for 21 | 22 | test html "my test" (X,Y) 23 | -} 24 | 25 | infix 4 =: 26 | (=:) :: (ToString a, ToPandoc a) 27 | => String -> (a, String) -> Test 28 | (=:) = test html 29 | 30 | tests :: [Test] 31 | tests = [ testGroup "inline code" 32 | [ "basic" =: code "@&" =?> "@&" 33 | , "haskell" =: codeWith ("",["haskell"],[]) ">>=" 34 | =?> ">>=" 35 | , "nolanguage" =: codeWith ("",["nolanguage"],[]) ">>=" 36 | =?> ">>=" 37 | ] 38 | , testGroup "images" 39 | [ "alt with formatting" =: 40 | image "/url" "title" ("my " <> emph "image") 41 | =?> "\"my" 42 | ] 43 | ] 44 | -------------------------------------------------------------------------------- /tests/Tests/Writers/LaTeX.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE OverloadedStrings #-} 2 | module Tests.Writers.LaTeX (tests) where 3 | 4 | import Test.Framework 5 | import Text.Pandoc.Builder 6 | import Text.Pandoc 7 | import Tests.Helpers 8 | import Tests.Arbitrary() 9 | 10 | latex :: (ToString a, ToPandoc a) => a -> String 11 | latex = writeLaTeX def{ writerHighlight = True } . toPandoc 12 | 13 | latexListing :: (ToString a, ToPandoc a) => a -> String 14 | latexListing = writeLaTeX def{ writerListings = True } . toPandoc 15 | 16 | {- 17 | "my test" =: X =?> Y 18 | 19 | is shorthand for 20 | 21 | test latex "my test" $ X =?> Y 22 | 23 | which is in turn shorthand for 24 | 25 | test latex "my test" (X,Y) 26 | -} 27 | 28 | infix 4 =: 29 | (=:) :: (ToString a, ToPandoc a) 30 | => String -> (a, String) -> Test 31 | (=:) = test latex 32 | 33 | tests :: [Test] 34 | tests = [ testGroup "code blocks" 35 | [ "in footnotes" =: note (para "hi" <> codeBlock "hi") =?> 36 | "\\footnote{hi\n\n\\begin{Verbatim}\nhi\n\\end{Verbatim}\n}" 37 | , test latexListing "identifier" $ codeBlockWith ("id",[],[]) "hi" =?> 38 | ("\\begin{lstlisting}[label=id]\nhi\n\\end{lstlisting}" :: String) 39 | , test latexListing "no identifier" $ codeBlock "hi" =?> 40 | ("\\begin{lstlisting}\nhi\n\\end{lstlisting}" :: String) 41 | ] 42 | , testGroup "definition lists" 43 | [ "with internal link" =: definitionList [(link "#go" "" (str "testing"), 44 | [plain (text "hi there")])] =?> 45 | "\\begin{description}\n\\itemsep1pt\\parskip0pt\\parsep0pt\n\\item[{\\hyperref[go]{testing}}]\nhi there\n\\end{description}" 46 | ] 47 | , testGroup "math" 48 | [ "escape |" =: para (math "\\sigma|_{\\{x\\}}") =?> 49 | "$\\sigma|_{\\{x\\}}$" 50 | ] 51 | , testGroup "headers" 52 | [ "unnumbered header" =: 53 | headerWith ("foo",["unnumbered"],[]) 1 54 | (text "Header 1" <> note (plain $ text "note")) =?> 55 | "\\section*{\\texorpdfstring{Header 1\\footnote{note}}{Header 1}}\\label{foo}\n\\addcontentsline{toc}{section}{Header 1}\n" 56 | , "in list item" =: 57 | bulletList [header 2 (text "foo")] =?> 58 | "\\begin{itemize}\n\\item ~\n \\subsection{foo}\n\\end{itemize}" 59 | , "in definition list item" =: 60 | definitionList [(text "foo", [header 2 (text "bar"), 61 | para $ text "baz"])] =?> 62 | "\\begin{description}\n\\item[foo] ~ \n\\subsection{bar}\n\nbaz\n\\end{description}" 63 | , "containing image" =: 64 | header 1 (image "imgs/foo.jpg" "" (text "Alt text")) =?> 65 | "\\section{\\texorpdfstring{\\protect\\includegraphics[]{imgs/foo.jpg}}{Alt text}}" 66 | ] 67 | , testGroup "inline code" 68 | [ "struck out and highlighted" =: 69 | strikeout (codeWith ("",["haskell"],[]) "foo" <> space 70 | <> str "bar") =?> 71 | "\\sout{\\mbox{\\VERB|\\NormalTok{foo}|} bar}" 72 | , "struck out and not highlighted" =: 73 | strikeout (code "foo" <> space 74 | <> str "bar") =?> 75 | "\\sout{\\texttt{foo} bar}" 76 | , "single quotes" =: 77 | code "dog's" =?> "\\texttt{dog\\textquotesingle{}s}" 78 | ] 79 | ] 80 | -------------------------------------------------------------------------------- /tests/Tests/Writers/Markdown.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE OverloadedStrings #-} 2 | module Tests.Writers.Markdown (tests) where 3 | 4 | import Test.Framework 5 | import Text.Pandoc.Builder 6 | import Text.Pandoc 7 | import Tests.Helpers 8 | import Tests.Arbitrary() 9 | 10 | markdown :: (ToString a, ToPandoc a) => a -> String 11 | markdown = writeMarkdown def . toPandoc 12 | 13 | {- 14 | "my test" =: X =?> Y 15 | 16 | is shorthand for 17 | 18 | test markdown "my test" $ X =?> Y 19 | 20 | which is in turn shorthand for 21 | 22 | test markdown "my test" (X,Y) 23 | -} 24 | 25 | infix 4 =: 26 | (=:) :: (ToString a, ToPandoc a) 27 | => String -> (a, String) -> Test 28 | (=:) = test markdown 29 | 30 | tests :: [Test] 31 | tests = [ "indented code after list" 32 | =: (orderedList [ para "one" <> para "two" ] <> codeBlock "test") 33 | =?> "1. one\n\n two\n\n\n\n test" 34 | , "list with tight sublist" 35 | =: bulletList [ plain "foo" <> bulletList [ plain "bar" ], 36 | plain "baz" ] 37 | =?> "- foo\n - bar\n- baz\n" 38 | ] 39 | -------------------------------------------------------------------------------- /tests/Tests/Writers/Native.hs: -------------------------------------------------------------------------------- 1 | module Tests.Writers.Native (tests) where 2 | 3 | import Test.Framework 4 | import Text.Pandoc.Builder 5 | import Text.Pandoc 6 | import Tests.Helpers 7 | import Tests.Arbitrary() 8 | 9 | p_write_rt :: Pandoc -> Bool 10 | p_write_rt d = 11 | read (writeNative def{ writerStandalone = True } d) == d 12 | 13 | p_write_blocks_rt :: [Block] -> Bool 14 | p_write_blocks_rt bs = length bs > 20 || 15 | read (writeNative def (Pandoc nullMeta bs)) == 16 | bs 17 | 18 | tests :: [Test] 19 | tests = [ property "p_write_rt" p_write_rt 20 | , property "p_write_blocks_rt" p_write_blocks_rt 21 | ] 22 | -------------------------------------------------------------------------------- /tests/Tests/Writers/Plain.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE OverloadedStrings #-} 2 | module Tests.Writers.Plain (tests) where 3 | 4 | import Test.Framework 5 | import Text.Pandoc.Builder 6 | import Text.Pandoc 7 | import Tests.Helpers 8 | import Tests.Arbitrary() 9 | 10 | 11 | infix 4 =: 12 | (=:) :: (ToString a, ToPandoc a) 13 | => String -> (a, String) -> Test 14 | (=:) = test (writePlain def . toPandoc) 15 | 16 | 17 | tests :: [Test] 18 | tests = [ "strongly emphasized text to uppercase" 19 | =: strong "Straße" 20 | =?> "STRASSE" 21 | ] 22 | -------------------------------------------------------------------------------- /tests/bodybg.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/timtylin/scholdoc/2620c8abccd544795d0b9f6687811102c21f21a6/tests/bodybg.gif -------------------------------------------------------------------------------- /tests/docx/image_vml.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/timtylin/scholdoc/2620c8abccd544795d0b9f6687811102c21f21a6/tests/docx/image_vml.docx -------------------------------------------------------------------------------- /tests/docx/image_vml.native: -------------------------------------------------------------------------------- 1 | [Header 1 ("vml-image",[],[]) [Strong [Str "VML",Space,Str "Image"]] 2 | ,BlockQuote 3 | [Para [Str "It",Space,Str "should",Space,Str "follow",Space,Str "below:"] 4 | ,Para [Image [] ("media/image4.jpeg","")]]] 5 | -------------------------------------------------------------------------------- /tests/dokuwiki_external_images.dokuwiki: -------------------------------------------------------------------------------- 1 | {{https://cooluri.com/image.png|HTTPS image}} {{http://cooluri.com/image.png|HTTP image}} {{ftp://ftp.cooluri.com/image.png|FTP image}} {{file:///tmp/coolimage.png|Filesystem image}} {{:/image.jpg|Relative image 1}} {{:image.jpg|Relative image 2}} 2 | -------------------------------------------------------------------------------- /tests/dokuwiki_external_images.native: -------------------------------------------------------------------------------- 1 | [Para [Image [Str "HTTPS",Space,Str "image"] ("https://cooluri.com/image.png",""),Space,Image [Str "HTTP",Space,Str "image"] ("http://cooluri.com/image.png",""),Space,Image [Str "FTP",Space,Str "image"] ("ftp://ftp.cooluri.com/image.png",""),Space,Image [Str "Filesystem",Space,Str "image"] ("file:///tmp/coolimage.png",""),Space,Image [Str "Relative",Space,Str "image",Space,Str "1"] ("/image.jpg",""),Space,Image [Str "Relative",Space,Str "image",Space,Str "2"] ("image.jpg","")]] 2 | -------------------------------------------------------------------------------- /tests/insert: -------------------------------------------------------------------------------- 1 | STUFF INSERTED 2 | -------------------------------------------------------------------------------- /tests/lalune.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/timtylin/scholdoc/2620c8abccd544795d0b9f6687811102c21f21a6/tests/lalune.jpg -------------------------------------------------------------------------------- /tests/lhs-test-markdown.native: -------------------------------------------------------------------------------- 1 | [Header 1 ("lhs-test",[],[]) [Str "lhs",Space,Str "test"] 2 | ,Para [Code ("",[],[]) "unsplit",Space,Str "is",Space,Str "an",Space,Str "arrow",Space,Str "that",Space,Str "takes",Space,Str "a",Space,Str "pair",Space,Str "of",Space,Str "values",Space,Str "and",Space,Str "combines",Space,Str "them",Space,Str "to",Space,Str "return",Space,Str "a",Space,Str "single",Space,Str "value:"] 3 | ,CodeBlock ("",["sourceCode","literate","haskell"],[]) "unsplit :: (Arrow a) => (b -> c -> d) -> a (b, c) d\nunsplit = arr . uncurry\n -- arr (\\op (x,y) -> x `op` y)" 4 | ,Para [Code ("",[],[]) "(***)",Space,Str "combines",Space,Str "two",Space,Str "arrows",Space,Str "into",Space,Str "a",Space,Str "new",Space,Str "arrow",Space,Str "by",Space,Str "running",Space,Str "the",Space,Str "two",Space,Str "arrows",Space,Str "on",Space,Str "a",Space,Str "pair",Space,Str "of",Space,Str "values",Space,Str "(one",Space,Str "arrow",Space,Str "on",Space,Str "the",Space,Str "first",Space,Str "item",Space,Str "of",Space,Str "the",Space,Str "pair",Space,Str "and",Space,Str "one",Space,Str "arrow",Space,Str "on",Space,Str "the",Space,Str "second",Space,Str "item",Space,Str "of",Space,Str "the",Space,Str "pair)."] 5 | ,CodeBlock ("",[],[]) "f *** g = first f >>> second g" 6 | ,Para [Str "Block",Space,Str "quote:"] 7 | ,BlockQuote 8 | [Para [Str "foo",Space,Str "bar"]]] 9 | -------------------------------------------------------------------------------- /tests/lhs-test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 28 | 29 | 30 |

lhs test

31 |

unsplit is an arrow that takes a pair of values and combines them to return a single value:

32 |
unsplit :: (Arrow a) => (b -> c -> d) -> a (b, c) d
33 | unsplit = arr . uncurry
34 |           -- arr (\op (x,y) -> x `op` y)
35 |

(***) combines two arrows into a new arrow by running the two arrows on a pair of values (one arrow on the first item of the pair and one arrow on the second item of the pair).

36 |
f *** g = first f >>> second g
37 |

Block quote:

38 |
39 |

foo bar

40 |
41 | 42 | 43 | -------------------------------------------------------------------------------- /tests/lhs-test.html+lhs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 28 | 29 | 30 |

lhs test

31 |

unsplit is an arrow that takes a pair of values and combines them to return a single value:

32 |
> unsplit :: (Arrow a) => (b -> c -> d) -> a (b, c) d
33 | > unsplit = arr . uncurry
34 | >           -- arr (\op (x,y) -> x `op` y)
35 |

(***) combines two arrows into a new arrow by running the two arrows on a pair of values (one arrow on the first item of the pair and one arrow on the second item of the pair).

36 |
f *** g = first f >>> second g
37 |

Block quote:

38 |
39 |

foo bar

40 |
41 | 42 | 43 | -------------------------------------------------------------------------------- /tests/lhs-test.latex: -------------------------------------------------------------------------------- 1 | \documentclass[]{article} 2 | \usepackage{lmodern} 3 | \usepackage{amssymb,amsmath} 4 | \usepackage{ifxetex,ifluatex} 5 | \usepackage{fixltx2e} % provides \textsubscript 6 | \ifnum 0\ifxetex 1\fi\ifluatex 1\fi=0 % if pdftex 7 | \usepackage[T1]{fontenc} 8 | \usepackage[utf8]{inputenc} 9 | \else % if luatex or xelatex 10 | \ifxetex 11 | \usepackage{mathspec} 12 | \usepackage{xltxtra,xunicode} 13 | \else 14 | \usepackage{fontspec} 15 | \fi 16 | \defaultfontfeatures{Mapping=tex-text,Scale=MatchLowercase} 17 | \newcommand{\euro}{€} 18 | \fi 19 | % use upquote if available, for straight quotes in verbatim environments 20 | \IfFileExists{upquote.sty}{\usepackage{upquote}}{} 21 | % use microtype if available 22 | \IfFileExists{microtype.sty}{% 23 | \usepackage{microtype} 24 | \UseMicrotypeSet[protrusion]{basicmath} % disable protrusion for tt fonts 25 | }{} 26 | \usepackage{color} 27 | \usepackage{fancyvrb} 28 | \newcommand{\VerbBar}{|} 29 | \newcommand{\VERB}{\Verb[commandchars=\\\{\}]} 30 | \DefineVerbatimEnvironment{Highlighting}{Verbatim}{commandchars=\\\{\}} 31 | % Add ',fontsize=\small' for more characters per line 32 | \newenvironment{Shaded}{}{} 33 | \newcommand{\KeywordTok}[1]{\textcolor[rgb]{0.00,0.44,0.13}{\textbf{{#1}}}} 34 | \newcommand{\DataTypeTok}[1]{\textcolor[rgb]{0.56,0.13,0.00}{{#1}}} 35 | \newcommand{\DecValTok}[1]{\textcolor[rgb]{0.25,0.63,0.44}{{#1}}} 36 | \newcommand{\BaseNTok}[1]{\textcolor[rgb]{0.25,0.63,0.44}{{#1}}} 37 | \newcommand{\FloatTok}[1]{\textcolor[rgb]{0.25,0.63,0.44}{{#1}}} 38 | \newcommand{\CharTok}[1]{\textcolor[rgb]{0.25,0.44,0.63}{{#1}}} 39 | \newcommand{\StringTok}[1]{\textcolor[rgb]{0.25,0.44,0.63}{{#1}}} 40 | \newcommand{\CommentTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textit{{#1}}}} 41 | \newcommand{\OtherTok}[1]{\textcolor[rgb]{0.00,0.44,0.13}{{#1}}} 42 | \newcommand{\AlertTok}[1]{\textcolor[rgb]{1.00,0.00,0.00}{\textbf{{#1}}}} 43 | \newcommand{\FunctionTok}[1]{\textcolor[rgb]{0.02,0.16,0.49}{{#1}}} 44 | \newcommand{\RegionMarkerTok}[1]{{#1}} 45 | \newcommand{\ErrorTok}[1]{\textcolor[rgb]{1.00,0.00,0.00}{\textbf{{#1}}}} 46 | \newcommand{\NormalTok}[1]{{#1}} 47 | \ifxetex 48 | \usepackage[setpagesize=false, % page size defined by xetex 49 | unicode=false, % unicode breaks when used with xetex 50 | xetex]{hyperref} 51 | \else 52 | \usepackage[unicode=true]{hyperref} 53 | \fi 54 | \hypersetup{breaklinks=true, 55 | bookmarks=true, 56 | pdfauthor={}, 57 | pdftitle={}, 58 | colorlinks=true, 59 | citecolor=blue, 60 | urlcolor=blue, 61 | linkcolor=magenta, 62 | pdfborder={0 0 0}} 63 | \urlstyle{same} % don't use monospace font for urls 64 | \setlength{\parindent}{0pt} 65 | \setlength{\parskip}{6pt plus 2pt minus 1pt} 66 | \setlength{\emergencystretch}{3em} % prevent overfull lines 67 | \setcounter{secnumdepth}{0} 68 | 69 | \date{} 70 | 71 | \begin{document} 72 | 73 | \section{lhs test}\label{lhs-test} 74 | 75 | \texttt{unsplit} is an arrow that takes a pair of values and combines them to 76 | return a single value: 77 | 78 | \begin{Shaded} 79 | \begin{Highlighting}[] 80 | \OtherTok{unsplit ::} \NormalTok{(}\DataTypeTok{Arrow} \NormalTok{a) }\OtherTok{=>} \NormalTok{(b }\OtherTok{->} \NormalTok{c }\OtherTok{->} \NormalTok{d) }\OtherTok{->} \NormalTok{a (b, c) d} 81 | \NormalTok{unsplit }\FunctionTok{=} \NormalTok{arr }\FunctionTok{.} \NormalTok{uncurry} 82 | \CommentTok{-- arr (\textbackslash{}op (x,y) -> x `op` y)} 83 | \end{Highlighting} 84 | \end{Shaded} 85 | 86 | \texttt{(***)} combines two arrows into a new arrow by running the two arrows 87 | on a pair of values (one arrow on the first item of the pair and one arrow on 88 | the second item of the pair). 89 | 90 | \begin{verbatim} 91 | f *** g = first f >>> second g 92 | \end{verbatim} 93 | 94 | Block quote: 95 | 96 | \begin{quote} 97 | foo bar 98 | \end{quote} 99 | 100 | \end{document} 101 | -------------------------------------------------------------------------------- /tests/lhs-test.latex+lhs: -------------------------------------------------------------------------------- 1 | \documentclass[]{article} 2 | \usepackage{lmodern} 3 | \usepackage{amssymb,amsmath} 4 | \usepackage{ifxetex,ifluatex} 5 | \usepackage{fixltx2e} % provides \textsubscript 6 | \ifnum 0\ifxetex 1\fi\ifluatex 1\fi=0 % if pdftex 7 | \usepackage[T1]{fontenc} 8 | \usepackage[utf8]{inputenc} 9 | \else % if luatex or xelatex 10 | \ifxetex 11 | \usepackage{mathspec} 12 | \usepackage{xltxtra,xunicode} 13 | \else 14 | \usepackage{fontspec} 15 | \fi 16 | \defaultfontfeatures{Mapping=tex-text,Scale=MatchLowercase} 17 | \newcommand{\euro}{€} 18 | \fi 19 | % use upquote if available, for straight quotes in verbatim environments 20 | \IfFileExists{upquote.sty}{\usepackage{upquote}}{} 21 | % use microtype if available 22 | \IfFileExists{microtype.sty}{% 23 | \usepackage{microtype} 24 | \UseMicrotypeSet[protrusion]{basicmath} % disable protrusion for tt fonts 25 | }{} 26 | \usepackage{listings} 27 | \lstnewenvironment{code}{\lstset{language=Haskell,basicstyle=\small\ttfamily}}{} 28 | \ifxetex 29 | \usepackage[setpagesize=false, % page size defined by xetex 30 | unicode=false, % unicode breaks when used with xetex 31 | xetex]{hyperref} 32 | \else 33 | \usepackage[unicode=true]{hyperref} 34 | \fi 35 | \hypersetup{breaklinks=true, 36 | bookmarks=true, 37 | pdfauthor={}, 38 | pdftitle={}, 39 | colorlinks=true, 40 | citecolor=blue, 41 | urlcolor=blue, 42 | linkcolor=magenta, 43 | pdfborder={0 0 0}} 44 | \urlstyle{same} % don't use monospace font for urls 45 | \setlength{\parindent}{0pt} 46 | \setlength{\parskip}{6pt plus 2pt minus 1pt} 47 | \setlength{\emergencystretch}{3em} % prevent overfull lines 48 | \setcounter{secnumdepth}{0} 49 | 50 | \date{} 51 | 52 | \begin{document} 53 | 54 | \section{lhs test}\label{lhs-test} 55 | 56 | \texttt{unsplit} is an arrow that takes a pair of values and combines them to 57 | return a single value: 58 | 59 | \begin{code} 60 | unsplit :: (Arrow a) => (b -> c -> d) -> a (b, c) d 61 | unsplit = arr . uncurry 62 | -- arr (\op (x,y) -> x `op` y) 63 | \end{code} 64 | 65 | \texttt{(***)} combines two arrows into a new arrow by running the two arrows 66 | on a pair of values (one arrow on the first item of the pair and one arrow on 67 | the second item of the pair). 68 | 69 | \begin{verbatim} 70 | f *** g = first f >>> second g 71 | \end{verbatim} 72 | 73 | Block quote: 74 | 75 | \begin{quote} 76 | foo bar 77 | \end{quote} 78 | 79 | \end{document} 80 | -------------------------------------------------------------------------------- /tests/lhs-test.markdown: -------------------------------------------------------------------------------- 1 | lhs test 2 | ======== 3 | 4 | `unsplit` is an arrow that takes a pair of values and combines them to return 5 | a single value: 6 | 7 | ``` {.sourceCode .literate .haskell} 8 | unsplit :: (Arrow a) => (b -> c -> d) -> a (b, c) d 9 | unsplit = arr . uncurry 10 | -- arr (\op (x,y) -> x `op` y) 11 | ``` 12 | 13 | `(***)` combines two arrows into a new arrow by running the two arrows on a 14 | pair of values (one arrow on the first item of the pair and one arrow on the 15 | second item of the pair). 16 | 17 | f *** g = first f >>> second g 18 | 19 | Block quote: 20 | 21 | > foo bar 22 | -------------------------------------------------------------------------------- /tests/lhs-test.markdown+lhs: -------------------------------------------------------------------------------- 1 | lhs test 2 | ======== 3 | 4 | `unsplit` is an arrow that takes a pair of values and combines them to return 5 | a single value: 6 | 7 | > unsplit :: (Arrow a) => (b -> c -> d) -> a (b, c) d 8 | > unsplit = arr . uncurry 9 | > -- arr (\op (x,y) -> x `op` y) 10 | 11 | `(***)` combines two arrows into a new arrow by running the two arrows on a 12 | pair of values (one arrow on the first item of the pair and one arrow on the 13 | second item of the pair). 14 | 15 | f *** g = first f >>> second g 16 | 17 | Block quote: 18 | 19 | > foo bar 20 | -------------------------------------------------------------------------------- /tests/lhs-test.native: -------------------------------------------------------------------------------- 1 | [Header 1 ("lhs-test",[],[]) [Str "lhs",Space,Str "test"] 2 | ,Para [Code ("",[],[]) "unsplit",Space,Str "is",Space,Str "an",Space,Str "arrow",Space,Str "that",Space,Str "takes",Space,Str "a",Space,Str "pair",Space,Str "of",Space,Str "values",Space,Str "and",Space,Str "combines",Space,Str "them",Space,Str "to",Space,Str "return",Space,Str "a",Space,Str "single",Space,Str "value:"] 3 | ,CodeBlock ("",["sourceCode","literate","haskell"],[]) "unsplit :: (Arrow a) => (b -> c -> d) -> a (b, c) d\nunsplit = arr . uncurry\n -- arr (\\op (x,y) -> x `op` y)" 4 | ,Para [Code ("",[],[]) "(***)",Space,Str "combines",Space,Str "two",Space,Str "arrows",Space,Str "into",Space,Str "a",Space,Str "new",Space,Str "arrow",Space,Str "by",Space,Str "running",Space,Str "the",Space,Str "two",Space,Str "arrows",Space,Str "on",Space,Str "a",Space,Str "pair",Space,Str "of",Space,Str "values",Space,Str "(one",Space,Str "arrow",Space,Str "on",Space,Str "the",Space,Str "first",Space,Str "item",Space,Str "of",Space,Str "the",Space,Str "pair",Space,Str "and",Space,Str "one",Space,Str "arrow",Space,Str "on",Space,Str "the",Space,Str "second",Space,Str "item",Space,Str "of",Space,Str "the",Space,Str "pair)."] 5 | ,CodeBlock ("",[],[]) "f *** g = first f >>> second g" 6 | ,Para [Str "Block",Space,Str "quote:"] 7 | ,BlockQuote 8 | [Para [Str "foo",Space,Str "bar"]]] 9 | -------------------------------------------------------------------------------- /tests/markdown-citations.native: -------------------------------------------------------------------------------- 1 | [Header 1 ("pandoc-with-citeproc-hs",[],[]) [Str "Pandoc",Space,Str "with",Space,Str "citeproc-hs"] 2 | ,BulletList 3 | [[Para [Cite [Citation {citationId = "nonexistent", citationPrefix = [], citationSuffix = [], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@nonexistent]"]]] 4 | ,[Para [Cite [Citation {citationId = "nonexistent", citationPrefix = [], citationSuffix = [], citationMode = AuthorInText, citationNoteNum = 0, citationHash = 0}] [Str "@nonexistent"]]] 5 | ,[Para [Cite [Citation {citationId = "item1", citationPrefix = [], citationSuffix = [], citationMode = AuthorInText, citationNoteNum = 0, citationHash = 0}] [Str "@item1"],Space,Str "says",Space,Str "blah."]] 6 | ,[Para [Cite [Citation {citationId = "item1", citationPrefix = [], citationSuffix = [Str "p.",Space,Str "30"], citationMode = AuthorInText, citationNoteNum = 0, citationHash = 0}] [Str "@item1",Space,Str "[p.",Space,Str "30]"],Space,Str "says",Space,Str "blah."]] 7 | ,[Para [Cite [Citation {citationId = "item1", citationPrefix = [], citationSuffix = [Str "p.",Space,Str "30,",Space,Str "with",Space,Str "suffix"], citationMode = AuthorInText, citationNoteNum = 0, citationHash = 0}] [Str "@item1",Space,Str "[p.",Space,Str "30,",Space,Str "with",Space,Str "suffix]"],Space,Str "says",Space,Str "blah."]] 8 | ,[Para [Cite [Citation {citationId = "item1", citationPrefix = [], citationSuffix = [], citationMode = AuthorInText, citationNoteNum = 0, citationHash = 0},Citation {citationId = "item2", citationPrefix = [], citationSuffix = [Space,Str "p.",Space,Str "30"], citationMode = SuppressAuthor, citationNoteNum = 0, citationHash = 0},Citation {citationId = "\1087\1091\1085\1082\1090\&3", citationPrefix = [Str "see",Space,Str "also"], citationSuffix = [], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "@item1",Space,Str "[-@item2",Space,Str "p.",Space,Str "30;",Space,Str "see",Space,Str "also",Space,Str "@\1087\1091\1085\1082\1090\&3]"],Space,Str "says",Space,Str "blah."]] 9 | ,[Para [Str "In",Space,Str "a",Space,Str "note.",Note [Para [Cite [Citation {citationId = "\1087\1091\1085\1082\1090\&3", citationPrefix = [], citationSuffix = [Str "p.",Space,Str "12"], citationMode = AuthorInText, citationNoteNum = 0, citationHash = 0}] [Str "@\1087\1091\1085\1082\1090\&3",Space,Str "[p.",Space,Str "12]"],Space,Str "and",Space,Str "a",Space,Str "citation",Space,Str "without",Space,Str "locators",Space,Cite [Citation {citationId = "\1087\1091\1085\1082\1090\&3", citationPrefix = [], citationSuffix = [], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@\1087\1091\1085\1082\1090\&3]"],Str "."]]]] 10 | ,[Para [Str "A",Space,Str "citation",Space,Str "group",Space,Cite [Citation {citationId = "item1", citationPrefix = [Str "see"], citationSuffix = [Space,Str "chap.",Space,Str "3"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0},Citation {citationId = "\1087\1091\1085\1082\1090\&3", citationPrefix = [Str "also"], citationSuffix = [Space,Str "p.",Space,Str "34-35"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[see",Space,Str "@item1",Space,Str "chap.",Space,Str "3;",Space,Str "also",Space,Str "@\1087\1091\1085\1082\1090\&3",Space,Str "p.",Space,Str "34-35]"],Str "."]] 11 | ,[Para [Str "Another",Space,Str "one",Space,Cite [Citation {citationId = "item1", citationPrefix = [Str "see"], citationSuffix = [Space,Str "p.",Space,Str "34-35"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[see",Space,Str "@item1",Space,Str "p.",Space,Str "34-35]"],Str "."]] 12 | ,[Para [Str "And",Space,Str "another",Space,Str "one",Space,Str "in",Space,Str "a",Space,Str "note.",Note [Para [Str "Some",Space,Str "citations",Space,Cite [Citation {citationId = "item1", citationPrefix = [Str "see"], citationSuffix = [Space,Str "chap.",Space,Str "3"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0},Citation {citationId = "\1087\1091\1085\1082\1090\&3", citationPrefix = [], citationSuffix = [], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0},Citation {citationId = "item2", citationPrefix = [], citationSuffix = [], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[see",Space,Str "@item1",Space,Str "chap.",Space,Str "3;",Space,Str "@\1087\1091\1085\1082\1090\&3;",Space,Str "@item2]"],Str "."]]]] 13 | ,[Para [Str "Citation",Space,Str "with",Space,Str "a",Space,Str "suffix",Space,Str "and",Space,Str "locator",Space,Cite [Citation {citationId = "item1", citationPrefix = [], citationSuffix = [Space,Str "pp.",Space,Str "33,",Space,Str "35-37,",Space,Str "and",Space,Str "nowhere",Space,Str "else"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@item1",Space,Str "pp.",Space,Str "33,",Space,Str "35-37,",Space,Str "and",Space,Str "nowhere",Space,Str "else]"],Str "."]] 14 | ,[Para [Str "Citation",Space,Str "with",Space,Str "suffix",Space,Str "only",Space,Cite [Citation {citationId = "item1", citationPrefix = [], citationSuffix = [Space,Str "and",Space,Str "nowhere",Space,Str "else"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@item1",Space,Str "and",Space,Str "nowhere",Space,Str "else]"],Str "."]] 15 | ,[Para [Str "Now",Space,Str "some",Space,Str "modifiers.",Note [Para [Str "Like",Space,Str "a",Space,Str "citation",Space,Str "without",Space,Str "author:",Space,Cite [Citation {citationId = "item1", citationPrefix = [], citationSuffix = [], citationMode = SuppressAuthor, citationNoteNum = 0, citationHash = 0}] [Str "[-@item1]"],Str ",",Space,Str "and",Space,Str "now",Space,Str "Doe",Space,Str "with",Space,Str "a",Space,Str "locator",Space,Cite [Citation {citationId = "item2", citationPrefix = [], citationSuffix = [Space,Str "p.",Space,Str "44"], citationMode = SuppressAuthor, citationNoteNum = 0, citationHash = 0}] [Str "[-@item2",Space,Str "p.",Space,Str "44]"],Str "."]]]] 16 | ,[Para [Str "With",Space,Str "some",Space,Str "markup",Space,Cite [Citation {citationId = "item1", citationPrefix = [Emph [Str "see"]], citationSuffix = [Space,Str "p.",Space,Strong [Str "32"]], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[*see*",Space,Str "@item1",Space,Str "p.",Space,Str "**32**]"],Str "."]]] 17 | ,Header 1 ("references",[],[]) [Str "References"]] 18 | -------------------------------------------------------------------------------- /tests/markdown-citations.txt: -------------------------------------------------------------------------------- 1 | Pandoc with citeproc-hs 2 | ======================= 3 | 4 | - [@nonexistent] 5 | 6 | - @nonexistent 7 | 8 | - @item1 says blah. 9 | 10 | - @item1 [p. 30] says blah. 11 | 12 | - @item1 [p. 30, with suffix] says blah. 13 | 14 | - @item1 [-@item2 p. 30; see also @пункт3] says blah. 15 | 16 | - In a note.[^1] 17 | 18 | - A citation group [see @item1 chap. 3; also @пункт3 p. 34-35]. 19 | 20 | - Another one [see @item1 p. 34-35]. 21 | 22 | - And another one in a note.[^2] 23 | 24 | - Citation with a suffix and locator [@item1 pp. 33, 35-37, and nowhere else]. 25 | 26 | - Citation with suffix only [@item1 and nowhere else]. 27 | 28 | - Now some modifiers.[^3] 29 | 30 | - With some markup [*see* @item1 p. **32**]. 31 | 32 | References 33 | ========== 34 | 35 | [^1]: @пункт3 [p. 12] and a citation without locators [@пункт3]. 36 | 37 | [^2]: Some citations [see @item1 chap. 3; @пункт3; @item2]. 38 | 39 | [^3]: Like a citation without author: [-@item1], and now Doe with a locator [-@item2 p. 44]. 40 | -------------------------------------------------------------------------------- /tests/markdown-reader-more.txt: -------------------------------------------------------------------------------- 1 | % Title 2 | spanning multiple lines 3 | % Author One 4 | Author Two; Author Three; 5 | Author Four 6 | 7 | # Additional markdown reader tests 8 | 9 | ## Blank line before URL in link reference 10 | 11 | [foo] and [bar] 12 | 13 | [foo]: 14 | /url 15 | 16 | [bar]: 17 | /url 18 | "title" 19 | 20 | ## Raw ConTeXt environments 21 | 22 | \placeformula \startformula 23 | L_{1} = L_{2} 24 | \stopformula 25 | 26 | \start[a2] 27 | \start[a2] 28 | \stop[a2] 29 | \stop[a2] 30 | 31 | ## URLs with spaces and punctuation 32 | 33 | [foo](/bar and baz) 34 | [foo](/bar 35 | and baz ) 36 | [foo]( /bar and baz ) 37 | [foo](bar baz "title" ) 38 | 39 | [baz][] [bam][] [bork][] 40 | 41 | [baz]: /foo foo 42 | [bam]: /foo fee 43 | [bork]: /foo/zee zob (title) 44 | 45 | [Ward's method.](http://en.wikipedia.org/wiki/Ward's_method) 46 | 47 | ## Horizontal rules with spaces at end 48 | 49 | * * * * * 50 | 51 | -- - -- -- - 52 | 53 | ## Raw HTML before header 54 | 55 |
56 | 57 | ### my header 58 | 59 | ## $ in math 60 | 61 | $\$2 + \$3$ 62 | 63 | $x = \text{the $n$th root of $y$}$ 64 | 65 | This should not be math: 66 | 67 | $PATH 90 $PATH 68 | 69 | ## Commented-out list item 70 | 71 | - one 72 | 75 | - three 76 | 77 | ## Indented code at beginning of list 78 | 79 | - code 80 | code 81 | 82 | 1. code 83 | code 84 | 85 | 12345678. code 86 | code 87 | 88 | - code 89 | code 90 | 91 | - no code 92 | 93 | ## Backslash newline 94 | 95 | hi\ 96 | there 97 | 98 | ## Code spans 99 | 100 | `hi\` 101 | 102 | `hi 103 | there` 104 | 105 | `` hi````there `` 106 | 107 | `hi 108 | 109 | there` 110 | 111 | ## Multilingual URLs 112 | 113 | 114 | 115 | [foo](/bar/测?x=测 "title") 116 | 117 | <测@foo.测.baz> 118 | 119 | ## Numbered examples 120 | 121 | (@) First example. 122 | (@foo) Second example. 123 | 124 | Explanation of examples (@foo) and (@bar). 125 | 126 | (@bar) Third example. 127 | 128 | ## Macros 129 | 130 | \newcommand{\tuple}[1]{\langle #1 \rangle} 131 | 132 | $\tuple{x,y}$ 133 | 134 | ## Case-insensitive references 135 | 136 | [Fum] 137 | 138 | [FUM] 139 | 140 | [bat] 141 | 142 | [fum]: /fum 143 | [BAT]: /bat 144 | 145 | ## Curly smart quotes 146 | 147 | “Hi” 148 | 149 | ‘Hi’ 150 | 151 | ## Consecutive lists 152 | 153 | - one 154 | - two 155 | 1. one 156 | 2. two 157 | 158 | a. one 159 | b. two 160 | 161 | ## Implicit header references 162 | 163 | ### My header 164 | 165 | ### My other header 166 | 167 | A link to [My header]. 168 | 169 | Another link to [it][My header]. 170 | 171 | Link to [Explicit header attributes]. 172 | 173 | [my other header]: /foo 174 | 175 | But this is not a link to [My other header], since the reference is defined. 176 | 177 | ## Explicit header attributes {#foobar .baz key="val"} 178 | 179 | > ## Header attributes inside block quote {#foobar .baz key="val"} 180 | 181 | ## Line blocks 182 | 183 | | But can a bee be said to be 184 | | or not to be an entire bee, 185 | | when half the bee is not a bee, 186 | | due to some ancient injury? 187 | | 188 | | Continuation 189 | line 190 | | and 191 | another 192 | 193 | ## Grid Tables 194 | 195 | +------------------+-----------+------------+ 196 | | col 1 | col 2 | col 3 | 197 | +==================+===========+============+ 198 | | r1 a | b | c | 199 | | r1 bis | b 2 | c 2 | 200 | +------------------+-----------+------------+ 201 | | r2 d | e | f | 202 | +------------------+-----------+------------+ 203 | 204 | Headless 205 | 206 | +------------------+-----------+------------+ 207 | | r1 a | b | c | 208 | | r1 bis | b 2 | c 2 | 209 | +------------------+-----------+------------+ 210 | | r2 d | e | f | 211 | +------------------+-----------+------------+ 212 | 213 | Spaces at ends of lines 214 | 215 | +------------------+-----------+------------+ 216 | | r1 a | b | c | 217 | | r1 bis | b 2 | c 2 | 218 | +------------------+-----------+------------+ 219 | | r2 d | e | f | 220 | +------------------+-----------+------------+ 221 | 222 | Multiple blocks in a cell 223 | 224 | +------------------+-----------+------------+ 225 | | # col 1 | # col 2 | # col 3 | 226 | | col 1 | col 2 | col 3 | 227 | +------------------+-----------+------------+ 228 | | r1 a | - b | c | 229 | | | - b 2 | c 2 | 230 | | r1 bis | - b 2 | c 2 | 231 | +------------------+-----------+------------+ 232 | 233 | Empty cells 234 | 235 | +---+---+ 236 | | | | 237 | +---+---+ 238 | 239 | ## Entities in links and titles 240 | 241 | [link](/ürl "öö!") 242 | 243 | 244 | 245 | 246 | 247 | [foobar] 248 | 249 | [foobar]: /ürl "öö!" 250 | 251 | ## Parentheses in URLs 252 | 253 | [link](/hi(there)) 254 | 255 | [link](/hithere\)) 256 | 257 | [linky] 258 | 259 | [linky]: hi_(there_(nested)) 260 | 261 | ## Reference link fallbacks 262 | 263 | [*not a link*] [*nope*]... 264 | 265 | ## Reference link followed by a citation 266 | 267 | MapReduce is a paradigm popularized by [Google] [@mapreduce] as its 268 | most vocal proponent. 269 | 270 | [Google]: http://google.com 271 | 272 | ## Empty reference links 273 | 274 | [foo2]: 275 | 276 | bar 277 | 278 | [foo2] 279 | -------------------------------------------------------------------------------- /tests/movie.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/timtylin/scholdoc/2620c8abccd544795d0b9f6687811102c21f21a6/tests/movie.jpg -------------------------------------------------------------------------------- /tests/pipe-tables.native: -------------------------------------------------------------------------------- 1 | [Para [Str "Simplest",Space,Str "table",Space,Str "without",Space,Str "caption:"] 2 | ,Table [] [AlignDefault,AlignDefault,AlignDefault] [0.0,0.0,0.0] 3 | [[Plain [Str "Default1"]] 4 | ,[Plain [Str "Default2"]] 5 | ,[Plain [Str "Default3"]]] 6 | [[[Plain [Str "12"]] 7 | ,[Plain [Str "12"]] 8 | ,[Plain [Str "12"]]] 9 | ,[[Plain [Str "123"]] 10 | ,[Plain [Str "123"]] 11 | ,[Plain [Str "123"]]] 12 | ,[[Plain [Str "1"]] 13 | ,[Plain [Str "1"]] 14 | ,[Plain [Str "1"]]]] 15 | ,Para [Str "Simple",Space,Str "table",Space,Str "with",Space,Str "caption:"] 16 | ,Table [Str "Demonstration",Space,Str "of",Space,Str "simple",Space,Str "table",Space,Str "syntax."] [AlignRight,AlignLeft,AlignDefault,AlignCenter] [0.0,0.0,0.0,0.0] 17 | [[Plain [Str "Right"]] 18 | ,[Plain [Str "Left"]] 19 | ,[Plain [Str "Default"]] 20 | ,[Plain [Str "Center"]]] 21 | [[[Plain [Str "12"]] 22 | ,[Plain [Str "12"]] 23 | ,[Plain [Str "12"]] 24 | ,[Plain [Str "12"]]] 25 | ,[[Plain [Str "123"]] 26 | ,[Plain [Str "123"]] 27 | ,[Plain [Str "123"]] 28 | ,[Plain [Str "123"]]] 29 | ,[[Plain [Str "1"]] 30 | ,[Plain [Str "1"]] 31 | ,[Plain [Str "1"]] 32 | ,[Plain [Str "1"]]]] 33 | ,Para [Str "Simple",Space,Str "table",Space,Str "without",Space,Str "caption:"] 34 | ,Table [] [AlignRight,AlignLeft,AlignCenter] [0.0,0.0,0.0] 35 | [[Plain [Str "Right"]] 36 | ,[Plain [Str "Left"]] 37 | ,[Plain [Str "Center"]]] 38 | [[[Plain [Str "12"]] 39 | ,[Plain [Str "12"]] 40 | ,[Plain [Str "12"]]] 41 | ,[[Plain [Str "123"]] 42 | ,[Plain [Str "123"]] 43 | ,[Plain [Str "123"]]] 44 | ,[[Plain [Str "1"]] 45 | ,[Plain [Str "1"]] 46 | ,[Plain [Str "1"]]]] 47 | ,Para [Str "Headerless",Space,Str "table",Space,Str "without",Space,Str "caption:"] 48 | ,Table [] [AlignRight,AlignLeft,AlignCenter] [0.0,0.0,0.0] 49 | [[] 50 | ,[] 51 | ,[]] 52 | [[[Plain [Str "12"]] 53 | ,[Plain [Str "12"]] 54 | ,[Plain [Str "12"]]] 55 | ,[[Plain [Str "123"]] 56 | ,[Plain [Str "123"]] 57 | ,[Plain [Str "123"]]] 58 | ,[[Plain [Str "1"]] 59 | ,[Plain [Str "1"]] 60 | ,[Plain [Str "1"]]]] 61 | ,Para [Str "Table",Space,Str "without",Space,Str "sides:"] 62 | ,Table [] [AlignDefault,AlignRight] [0.0,0.0] 63 | [[Plain [Str "Fruit"]] 64 | ,[Plain [Str "Quantity"]]] 65 | [[[Plain [Str "apple"]] 66 | ,[Plain [Str "5"]]] 67 | ,[[Plain [Str "orange"]] 68 | ,[Plain [Str "17"]]] 69 | ,[[Plain [Str "pear"]] 70 | ,[Plain [Str "302"]]]] 71 | ,Para [Str "One-column:"] 72 | ,Table [] [AlignDefault] [0.0] 73 | [[Plain [Str "hi"]]] 74 | [[[Plain [Str "lo"]]]] 75 | ,Para [Str "Header-less",Space,Str "one-column:"] 76 | ,Table [] [AlignCenter] [0.0] 77 | [[]] 78 | [[[Plain [Str "hi"]]]]] 79 | -------------------------------------------------------------------------------- /tests/pipe-tables.txt: -------------------------------------------------------------------------------- 1 | Simplest table without caption: 2 | 3 | | Default1 | Default2 | Default3 | 4 | |----------|----------|----------| 5 | |12|12|12| 6 | |123|123|123| 7 | |1|1|1| 8 | 9 | Simple table with caption: 10 | 11 | | Right | Left | Default | Center | 12 | | ----: | :--- | ------- | :----: | 13 | | 12 | 12 | 12 | 12 | 14 | | 123 | 123 | 123 | 123 | 15 | | 1 | 1 | 1 | 1 | 16 | 17 | : Demonstration of simple table syntax. 18 | 19 | Simple table without caption: 20 | 21 | | Right | Left | Center | 22 | |------:|:-----|:------:| 23 | |12|12|12| 24 | |123|123|123| 25 | |1|1|1| 26 | 27 | 28 | Headerless table without caption: 29 | 30 | |------:|:-----|:------:| 31 | |12|12|12| 32 | |123|123|123| 33 | |1|1|1| 34 | 35 | Table without sides: 36 | 37 | Fruit |Quantity 38 | ------|-------: 39 | apple | 5 40 | orange| 17 41 | pear | 302 42 | 43 | One-column: 44 | 45 | |hi| 46 | |--| 47 | |lo| 48 | 49 | Header-less one-column: 50 | 51 | |:-:| 52 | |hi| 53 | -------------------------------------------------------------------------------- /tests/s5-basic.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | My S5 Document 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 |
26 |
27 | 28 | 32 |
33 |
34 |
35 |

My S5 Document

36 |

Sam Smith
Jen Jones

37 |

July 15, 2006

38 |
39 |
40 |

First slide

41 |
    42 |
  • first bullet
  • 43 |
  • second bullet
  • 44 |
45 |
46 |
47 |

Math

48 |
    49 |
  • $\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}$
  • 50 |
51 |
52 |
53 | 54 | 55 | -------------------------------------------------------------------------------- /tests/s5-fragment.html: -------------------------------------------------------------------------------- 1 |

First slide

2 |
    3 |
  • first bullet
  • 4 |
  • second bullet
  • 5 |
6 |

Math

7 |
    8 |
  • $\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}$
  • 9 |
10 | -------------------------------------------------------------------------------- /tests/s5-inserts.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | My S5 Document 11 | 12 | 13 | STUFF INSERTED 14 | 15 | 16 | STUFF INSERTED 17 | 23 |

First slide

24 |
    25 |
  • first bullet
  • 26 |
  • second bullet
  • 27 |
28 |

Math

29 |
    30 |
  • $\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}$
  • 31 |
32 | STUFF INSERTED 33 | 34 | 35 | -------------------------------------------------------------------------------- /tests/s5.native: -------------------------------------------------------------------------------- 1 | Pandoc (Meta {unMeta = fromList [("author",MetaList [MetaInlines [Str "Sam",Space,Str "Smith"],MetaInlines [Str "Jen",Space,Str "Jones"]]),("date",MetaInlines [Str "July",Space,Str "15,",Space,Str "2006"]),("title",MetaInlines [Str "My",Space,Str "S5",Space,Str "Document"])]}) 2 | [Header 1 ("first-slide",[],[]) [Str "First",Space,Str "slide"] 3 | ,BulletList 4 | [[Plain [Str "first",Space,Str "bullet"]] 5 | ,[Plain [Str "second",Space,Str "bullet"]]] 6 | ,Header 1 ("math",[],[]) [Str "Math"] 7 | ,BulletList 8 | [[Plain [Math InlineMath "\\frac{d}{dx}f(x)=\\lim_{h\\to 0}\\frac{f(x+h)-f(x)}{h}"]]]] 9 | -------------------------------------------------------------------------------- /tests/tables-rstsubset.native: -------------------------------------------------------------------------------- 1 | [Para [Str "Simple",Space,Str "table",Space,Str "with",Space,Str "caption:"] 2 | ,Table [] [AlignDefault,AlignDefault,AlignDefault,AlignDefault] [0.125,0.1125,0.1375,0.15] 3 | [[Plain [Str "Right"]] 4 | ,[Plain [Str "Left"]] 5 | ,[Plain [Str "Center"]] 6 | ,[Plain [Str "Default"]]] 7 | [[[Plain [Str "12"]] 8 | ,[Plain [Str "12"]] 9 | ,[Plain [Str "12"]] 10 | ,[Plain [Str "12"]]] 11 | ,[[Plain [Str "123"]] 12 | ,[Plain [Str "123"]] 13 | ,[Plain [Str "123"]] 14 | ,[Plain [Str "123"]]] 15 | ,[[Plain [Str "1"]] 16 | ,[Plain [Str "1"]] 17 | ,[Plain [Str "1"]] 18 | ,[Plain [Str "1"]]]] 19 | ,Para [Str "Table:",Space,Str "Demonstration",Space,Str "of",Space,Str "simple",Space,Str "table",Space,Str "syntax."] 20 | ,Para [Str "Simple",Space,Str "table",Space,Str "without",Space,Str "caption:"] 21 | ,Table [] [AlignDefault,AlignDefault,AlignDefault,AlignDefault] [0.125,0.1125,0.1375,0.15] 22 | [[Plain [Str "Right"]] 23 | ,[Plain [Str "Left"]] 24 | ,[Plain [Str "Center"]] 25 | ,[Plain [Str "Default"]]] 26 | [[[Plain [Str "12"]] 27 | ,[Plain [Str "12"]] 28 | ,[Plain [Str "12"]] 29 | ,[Plain [Str "12"]]] 30 | ,[[Plain [Str "123"]] 31 | ,[Plain [Str "123"]] 32 | ,[Plain [Str "123"]] 33 | ,[Plain [Str "123"]]] 34 | ,[[Plain [Str "1"]] 35 | ,[Plain [Str "1"]] 36 | ,[Plain [Str "1"]] 37 | ,[Plain [Str "1"]]]] 38 | ,Para [Str "Simple",Space,Str "table",Space,Str "indented",Space,Str "two",Space,Str "spaces:"] 39 | ,Table [] [AlignDefault,AlignDefault,AlignDefault,AlignDefault] [0.125,0.1125,0.1375,0.15] 40 | [[Plain [Str "Right"]] 41 | ,[Plain [Str "Left"]] 42 | ,[Plain [Str "Center"]] 43 | ,[Plain [Str "Default"]]] 44 | [[[Plain [Str "12"]] 45 | ,[Plain [Str "12"]] 46 | ,[Plain [Str "12"]] 47 | ,[Plain [Str "12"]]] 48 | ,[[Plain [Str "123"]] 49 | ,[Plain [Str "123"]] 50 | ,[Plain [Str "123"]] 51 | ,[Plain [Str "123"]]] 52 | ,[[Plain [Str "1"]] 53 | ,[Plain [Str "1"]] 54 | ,[Plain [Str "1"]] 55 | ,[Plain [Str "1"]]]] 56 | ,Para [Str "Table:",Space,Str "Demonstration",Space,Str "of",Space,Str "simple",Space,Str "table",Space,Str "syntax."] 57 | ,Para [Str "Multiline",Space,Str "table",Space,Str "with",Space,Str "caption:"] 58 | ,Table [] [AlignDefault,AlignDefault,AlignDefault,AlignDefault] [0.175,0.1625,0.1875,0.3625] 59 | [[Plain [Str "Centered",Space,Str "Header"]] 60 | ,[Plain [Str "Left",Space,Str "Aligned"]] 61 | ,[Plain [Str "Right",Space,Str "Aligned"]] 62 | ,[Plain [Str "Default",Space,Str "aligned"]]] 63 | [[[Plain [Str "First"]] 64 | ,[Plain [Str "row"]] 65 | ,[Plain [Str "12.0"]] 66 | ,[Plain [Str "Example",Space,Str "of",Space,Str "a",Space,Str "row",Space,Str "that",Space,Str "spans",Space,Str "multiple",Space,Str "lines."]]] 67 | ,[[Plain [Str "Second"]] 68 | ,[Plain [Str "row"]] 69 | ,[Plain [Str "5.0"]] 70 | ,[Plain [Str "Here's",Space,Str "another",Space,Str "one.",Space,Str "Note",Space,Str "the",Space,Str "blank",Space,Str "line",Space,Str "between",Space,Str "rows."]]]] 71 | ,Para [Str "Table:",Space,Str "Here's",Space,Str "the",Space,Str "caption.",Space,Str "It",Space,Str "may",Space,Str "span",Space,Str "multiple",Space,Str "lines."] 72 | ,Para [Str "Multiline",Space,Str "table",Space,Str "without",Space,Str "caption:"] 73 | ,Table [] [AlignDefault,AlignDefault,AlignDefault,AlignDefault] [0.175,0.1625,0.1875,0.3625] 74 | [[Plain [Str "Centered",Space,Str "Header"]] 75 | ,[Plain [Str "Left",Space,Str "Aligned"]] 76 | ,[Plain [Str "Right",Space,Str "Aligned"]] 77 | ,[Plain [Str "Default",Space,Str "aligned"]]] 78 | [[[Plain [Str "First"]] 79 | ,[Plain [Str "row"]] 80 | ,[Plain [Str "12.0"]] 81 | ,[Plain [Str "Example",Space,Str "of",Space,Str "a",Space,Str "row",Space,Str "that",Space,Str "spans",Space,Str "multiple",Space,Str "lines."]]] 82 | ,[[Plain [Str "Second"]] 83 | ,[Plain [Str "row"]] 84 | ,[Plain [Str "5.0"]] 85 | ,[Plain [Str "Here's",Space,Str "another",Space,Str "one.",Space,Str "Note",Space,Str "the",Space,Str "blank",Space,Str "line",Space,Str "between",Space,Str "rows."]]]] 86 | ,Para [Str "Table",Space,Str "without",Space,Str "column",Space,Str "headers:"] 87 | ,Table [] [AlignDefault,AlignDefault,AlignDefault,AlignDefault] [0.1,0.1,0.1,0.1] 88 | [[] 89 | ,[] 90 | ,[] 91 | ,[]] 92 | [[[Plain [Str "12"]] 93 | ,[Plain [Str "12"]] 94 | ,[Plain [Str "12"]] 95 | ,[Plain [Str "12"]]] 96 | ,[[Plain [Str "123"]] 97 | ,[Plain [Str "123"]] 98 | ,[Plain [Str "123"]] 99 | ,[Plain [Str "123"]]] 100 | ,[[Plain [Str "1"]] 101 | ,[Plain [Str "1"]] 102 | ,[Plain [Str "1"]] 103 | ,[Plain [Str "1"]]]] 104 | ,Para [Str "Multiline",Space,Str "table",Space,Str "without",Space,Str "column",Space,Str "headers:"] 105 | ,Table [] [AlignDefault,AlignDefault,AlignDefault,AlignDefault] [0.175,0.1625,0.1875,0.3625] 106 | [[] 107 | ,[] 108 | ,[] 109 | ,[]] 110 | [[[Plain [Str "First"]] 111 | ,[Plain [Str "row"]] 112 | ,[Plain [Str "12.0"]] 113 | ,[Plain [Str "Example",Space,Str "of",Space,Str "a",Space,Str "row",Space,Str "that",Space,Str "spans",Space,Str "multiple",Space,Str "lines."]]] 114 | ,[[Plain [Str "Second"]] 115 | ,[Plain [Str "row"]] 116 | ,[Plain [Str "5.0"]] 117 | ,[Plain [Str "Here's",Space,Str "another",Space,Str "one.",Space,Str "Note",Space,Str "the",Space,Str "blank",Space,Str "line",Space,Str "between",Space,Str "rows."]]]]] 118 | -------------------------------------------------------------------------------- /tests/tables.haddock: -------------------------------------------------------------------------------- 1 | Simple table with caption: 2 | 3 | > Right Left Center Default 4 | > ------- ------ -------- --------- 5 | > 12 12 12 12 6 | > 123 123 123 123 7 | > 1 1 1 1 8 | > 9 | > Demonstration of simple table syntax. 10 | 11 | Simple table without caption: 12 | 13 | > Right Left Center Default 14 | > ------- ------ -------- --------- 15 | > 12 12 12 12 16 | > 123 123 123 123 17 | > 1 1 1 1 18 | 19 | Simple table indented two spaces: 20 | 21 | > Right Left Center Default 22 | > ------- ------ -------- --------- 23 | > 12 12 12 12 24 | > 123 123 123 123 25 | > 1 1 1 1 26 | > 27 | > Demonstration of simple table syntax. 28 | 29 | Multiline table with caption: 30 | 31 | > -------------------------------------------------------------- 32 | > Centered Left Right Default aligned 33 | > Header Aligned Aligned 34 | > ----------- ---------- ------------ -------------------------- 35 | > First row 12.0 Example of a row that 36 | > spans multiple lines. 37 | > 38 | > Second row 5.0 Here\'s another one. Note 39 | > the blank line between 40 | > rows. 41 | > -------------------------------------------------------------- 42 | > 43 | > Here\'s the caption. It may span multiple lines. 44 | 45 | Multiline table without caption: 46 | 47 | > -------------------------------------------------------------- 48 | > Centered Left Right Default aligned 49 | > Header Aligned Aligned 50 | > ----------- ---------- ------------ -------------------------- 51 | > First row 12.0 Example of a row that 52 | > spans multiple lines. 53 | > 54 | > Second row 5.0 Here\'s another one. Note 55 | > the blank line between 56 | > rows. 57 | > -------------------------------------------------------------- 58 | 59 | Table without column headers: 60 | 61 | > ----- ----- ----- ----- 62 | > 12 12 12 12 63 | > 123 123 123 123 64 | > 1 1 1 1 65 | > ----- ----- ----- ----- 66 | 67 | Multiline table without column headers: 68 | 69 | > ----------- ---------- ------------ -------------------------- 70 | > First row 12.0 Example of a row that 71 | > spans multiple lines. 72 | > 73 | > Second row 5.0 Here\'s another one. Note 74 | > the blank line between 75 | > rows. 76 | > ----------- ---------- ------------ -------------------------- 77 | -------------------------------------------------------------------------------- /tests/tables.html: -------------------------------------------------------------------------------- 1 |

Simple table with caption:

2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 |
Demonstration of simple table syntax.
RightLeftCenterDefault
12121212
123123123123
1111
33 |

Simple table without caption:

34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 |
RightLeftCenterDefault
12121212
123123123123
1111
64 |

Simple table indented two spaces:

65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 |
Demonstration of simple table syntax.
RightLeftCenterDefault
12121212
123123123123
1111
96 |

Multiline table with caption:

97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 |
Here's the caption. It may span multiple lines.
Centered HeaderLeft AlignedRight AlignedDefault aligned
Firstrow12.0Example of a row that spans multiple lines.
Secondrow5.0Here's another one. Note the blank line between rows.
128 |

Multiline table without caption:

129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 |
Centered HeaderLeft AlignedRight AlignedDefault aligned
Firstrow12.0Example of a row that spans multiple lines.
Secondrow5.0Here's another one. Note the blank line between rows.
159 |

Table without column headers:

160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 |
12121212
123123123123
1111
182 |

Multiline table without column headers:

183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 |
Firstrow12.0Example of a row that spans multiple lines.
Secondrow5.0Here's another one. Note the blank line between rows.
205 | -------------------------------------------------------------------------------- /tests/tables.latex: -------------------------------------------------------------------------------- 1 | Simple table with caption: 2 | 3 | \begin{longtable}[c]{@{}rlcl@{}} 4 | \caption{Demonstration of simple table syntax.}\tabularnewline 5 | \toprule 6 | Right & Left & Center & Default\tabularnewline 7 | \midrule 8 | \endfirsthead 9 | \toprule 10 | Right & Left & Center & Default\tabularnewline 11 | \midrule 12 | \endhead 13 | 12 & 12 & 12 & 12\tabularnewline 14 | 123 & 123 & 123 & 123\tabularnewline 15 | 1 & 1 & 1 & 1\tabularnewline 16 | \bottomrule 17 | \end{longtable} 18 | 19 | Simple table without caption: 20 | 21 | \begin{longtable}[c]{@{}rlcl@{}} 22 | \toprule 23 | Right & Left & Center & Default\tabularnewline 24 | \midrule 25 | \endhead 26 | 12 & 12 & 12 & 12\tabularnewline 27 | 123 & 123 & 123 & 123\tabularnewline 28 | 1 & 1 & 1 & 1\tabularnewline 29 | \bottomrule 30 | \end{longtable} 31 | 32 | Simple table indented two spaces: 33 | 34 | \begin{longtable}[c]{@{}rlcl@{}} 35 | \caption{Demonstration of simple table syntax.}\tabularnewline 36 | \toprule 37 | Right & Left & Center & Default\tabularnewline 38 | \midrule 39 | \endfirsthead 40 | \toprule 41 | Right & Left & Center & Default\tabularnewline 42 | \midrule 43 | \endhead 44 | 12 & 12 & 12 & 12\tabularnewline 45 | 123 & 123 & 123 & 123\tabularnewline 46 | 1 & 1 & 1 & 1\tabularnewline 47 | \bottomrule 48 | \end{longtable} 49 | 50 | Multiline table with caption: 51 | 52 | \begin{longtable}[c]{@{}clrl@{}} 53 | \caption{Here's the caption. It may span multiple lines.}\tabularnewline 54 | \toprule 55 | \begin{minipage}[b]{0.13\hsize}\centering\strut 56 | Centered Header 57 | \strut\end{minipage} & \begin{minipage}[b]{0.12\hsize}\raggedright\strut 58 | Left Aligned 59 | \strut\end{minipage} & \begin{minipage}[b]{0.14\hsize}\raggedleft\strut 60 | Right Aligned 61 | \strut\end{minipage} & \begin{minipage}[b]{0.30\hsize}\raggedright\strut 62 | Default aligned 63 | \strut\end{minipage}\tabularnewline 64 | \midrule 65 | \endfirsthead 66 | \toprule 67 | \begin{minipage}[b]{0.13\hsize}\centering\strut 68 | Centered Header 69 | \strut\end{minipage} & \begin{minipage}[b]{0.12\hsize}\raggedright\strut 70 | Left Aligned 71 | \strut\end{minipage} & \begin{minipage}[b]{0.14\hsize}\raggedleft\strut 72 | Right Aligned 73 | \strut\end{minipage} & \begin{minipage}[b]{0.30\hsize}\raggedright\strut 74 | Default aligned 75 | \strut\end{minipage}\tabularnewline 76 | \midrule 77 | \endhead 78 | \begin{minipage}[t]{0.13\hsize}\centering\strut 79 | First 80 | \strut\end{minipage} & \begin{minipage}[t]{0.12\hsize}\raggedright\strut 81 | row 82 | \strut\end{minipage} & \begin{minipage}[t]{0.14\hsize}\raggedleft\strut 83 | 12.0 84 | \strut\end{minipage} & \begin{minipage}[t]{0.30\hsize}\raggedright\strut 85 | Example of a row that spans multiple lines. 86 | \strut\end{minipage}\tabularnewline 87 | \begin{minipage}[t]{0.13\hsize}\centering\strut 88 | Second 89 | \strut\end{minipage} & \begin{minipage}[t]{0.12\hsize}\raggedright\strut 90 | row 91 | \strut\end{minipage} & \begin{minipage}[t]{0.14\hsize}\raggedleft\strut 92 | 5.0 93 | \strut\end{minipage} & \begin{minipage}[t]{0.30\hsize}\raggedright\strut 94 | Here's another one. Note the blank line between rows. 95 | \strut\end{minipage}\tabularnewline 96 | \bottomrule 97 | \end{longtable} 98 | 99 | Multiline table without caption: 100 | 101 | \begin{longtable}[c]{@{}clrl@{}} 102 | \toprule 103 | \begin{minipage}[b]{0.13\hsize}\centering\strut 104 | Centered Header 105 | \strut\end{minipage} & \begin{minipage}[b]{0.12\hsize}\raggedright\strut 106 | Left Aligned 107 | \strut\end{minipage} & \begin{minipage}[b]{0.14\hsize}\raggedleft\strut 108 | Right Aligned 109 | \strut\end{minipage} & \begin{minipage}[b]{0.30\hsize}\raggedright\strut 110 | Default aligned 111 | \strut\end{minipage}\tabularnewline 112 | \midrule 113 | \endhead 114 | \begin{minipage}[t]{0.13\hsize}\centering\strut 115 | First 116 | \strut\end{minipage} & \begin{minipage}[t]{0.12\hsize}\raggedright\strut 117 | row 118 | \strut\end{minipage} & \begin{minipage}[t]{0.14\hsize}\raggedleft\strut 119 | 12.0 120 | \strut\end{minipage} & \begin{minipage}[t]{0.30\hsize}\raggedright\strut 121 | Example of a row that spans multiple lines. 122 | \strut\end{minipage}\tabularnewline 123 | \begin{minipage}[t]{0.13\hsize}\centering\strut 124 | Second 125 | \strut\end{minipage} & \begin{minipage}[t]{0.12\hsize}\raggedright\strut 126 | row 127 | \strut\end{minipage} & \begin{minipage}[t]{0.14\hsize}\raggedleft\strut 128 | 5.0 129 | \strut\end{minipage} & \begin{minipage}[t]{0.30\hsize}\raggedright\strut 130 | Here's another one. Note the blank line between rows. 131 | \strut\end{minipage}\tabularnewline 132 | \bottomrule 133 | \end{longtable} 134 | 135 | Table without column headers: 136 | 137 | \begin{longtable}[c]{@{}rlcr@{}} 138 | \toprule 139 | 12 & 12 & 12 & 12\tabularnewline 140 | 123 & 123 & 123 & 123\tabularnewline 141 | 1 & 1 & 1 & 1\tabularnewline 142 | \bottomrule 143 | \end{longtable} 144 | 145 | Multiline table without column headers: 146 | 147 | \begin{longtable}[c]{@{}clrl@{}} 148 | \toprule 149 | \begin{minipage}[t]{0.13\hsize}\centering\strut 150 | First 151 | \strut\end{minipage} & \begin{minipage}[t]{0.12\hsize}\raggedright\strut 152 | row 153 | \strut\end{minipage} & \begin{minipage}[t]{0.14\hsize}\raggedleft\strut 154 | 12.0 155 | \strut\end{minipage} & \begin{minipage}[t]{0.30\hsize}\raggedright\strut 156 | Example of a row that spans multiple lines. 157 | \strut\end{minipage}\tabularnewline 158 | \begin{minipage}[t]{0.13\hsize}\centering\strut 159 | Second 160 | \strut\end{minipage} & \begin{minipage}[t]{0.12\hsize}\raggedright\strut 161 | row 162 | \strut\end{minipage} & \begin{minipage}[t]{0.14\hsize}\raggedleft\strut 163 | 5.0 164 | \strut\end{minipage} & \begin{minipage}[t]{0.30\hsize}\raggedright\strut 165 | Here's another one. Note the blank line between rows. 166 | \strut\end{minipage}\tabularnewline 167 | \bottomrule 168 | \end{longtable} 169 | -------------------------------------------------------------------------------- /tests/tables.man: -------------------------------------------------------------------------------- 1 | .PP 2 | Simple table with caption: 3 | .PP 4 | Demonstration of simple table syntax. 5 | .TS 6 | tab(@); 7 | r l c l. 8 | T{ 9 | Right 10 | T}@T{ 11 | Left 12 | T}@T{ 13 | Center 14 | T}@T{ 15 | Default 16 | T} 17 | _ 18 | T{ 19 | 12 20 | T}@T{ 21 | 12 22 | T}@T{ 23 | 12 24 | T}@T{ 25 | 12 26 | T} 27 | T{ 28 | 123 29 | T}@T{ 30 | 123 31 | T}@T{ 32 | 123 33 | T}@T{ 34 | 123 35 | T} 36 | T{ 37 | 1 38 | T}@T{ 39 | 1 40 | T}@T{ 41 | 1 42 | T}@T{ 43 | 1 44 | T} 45 | .TE 46 | .PP 47 | Simple table without caption: 48 | .PP 49 | .TS 50 | tab(@); 51 | r l c l. 52 | T{ 53 | Right 54 | T}@T{ 55 | Left 56 | T}@T{ 57 | Center 58 | T}@T{ 59 | Default 60 | T} 61 | _ 62 | T{ 63 | 12 64 | T}@T{ 65 | 12 66 | T}@T{ 67 | 12 68 | T}@T{ 69 | 12 70 | T} 71 | T{ 72 | 123 73 | T}@T{ 74 | 123 75 | T}@T{ 76 | 123 77 | T}@T{ 78 | 123 79 | T} 80 | T{ 81 | 1 82 | T}@T{ 83 | 1 84 | T}@T{ 85 | 1 86 | T}@T{ 87 | 1 88 | T} 89 | .TE 90 | .PP 91 | Simple table indented two spaces: 92 | .PP 93 | Demonstration of simple table syntax. 94 | .TS 95 | tab(@); 96 | r l c l. 97 | T{ 98 | Right 99 | T}@T{ 100 | Left 101 | T}@T{ 102 | Center 103 | T}@T{ 104 | Default 105 | T} 106 | _ 107 | T{ 108 | 12 109 | T}@T{ 110 | 12 111 | T}@T{ 112 | 12 113 | T}@T{ 114 | 12 115 | T} 116 | T{ 117 | 123 118 | T}@T{ 119 | 123 120 | T}@T{ 121 | 123 122 | T}@T{ 123 | 123 124 | T} 125 | T{ 126 | 1 127 | T}@T{ 128 | 1 129 | T}@T{ 130 | 1 131 | T}@T{ 132 | 1 133 | T} 134 | .TE 135 | .PP 136 | Multiline table with caption: 137 | .PP 138 | Here\[aq]s the caption. It may span multiple lines. 139 | .TS 140 | tab(@); 141 | cw(10.5n) lw(9.6n) rw(11.4n) lw(23.6n). 142 | T{ 143 | Centered Header 144 | T}@T{ 145 | Left Aligned 146 | T}@T{ 147 | Right Aligned 148 | T}@T{ 149 | Default aligned 150 | T} 151 | _ 152 | T{ 153 | First 154 | T}@T{ 155 | row 156 | T}@T{ 157 | 12.0 158 | T}@T{ 159 | Example of a row that spans multiple lines. 160 | T} 161 | T{ 162 | Second 163 | T}@T{ 164 | row 165 | T}@T{ 166 | 5.0 167 | T}@T{ 168 | Here\[aq]s another one. 169 | Note the blank line between rows. 170 | T} 171 | .TE 172 | .PP 173 | Multiline table without caption: 174 | .PP 175 | .TS 176 | tab(@); 177 | cw(10.5n) lw(9.6n) rw(11.4n) lw(23.6n). 178 | T{ 179 | Centered Header 180 | T}@T{ 181 | Left Aligned 182 | T}@T{ 183 | Right Aligned 184 | T}@T{ 185 | Default aligned 186 | T} 187 | _ 188 | T{ 189 | First 190 | T}@T{ 191 | row 192 | T}@T{ 193 | 12.0 194 | T}@T{ 195 | Example of a row that spans multiple lines. 196 | T} 197 | T{ 198 | Second 199 | T}@T{ 200 | row 201 | T}@T{ 202 | 5.0 203 | T}@T{ 204 | Here\[aq]s another one. 205 | Note the blank line between rows. 206 | T} 207 | .TE 208 | .PP 209 | Table without column headers: 210 | .PP 211 | .TS 212 | tab(@); 213 | r l c r. 214 | T{ 215 | 12 216 | T}@T{ 217 | 12 218 | T}@T{ 219 | 12 220 | T}@T{ 221 | 12 222 | T} 223 | T{ 224 | 123 225 | T}@T{ 226 | 123 227 | T}@T{ 228 | 123 229 | T}@T{ 230 | 123 231 | T} 232 | T{ 233 | 1 234 | T}@T{ 235 | 1 236 | T}@T{ 237 | 1 238 | T}@T{ 239 | 1 240 | T} 241 | .TE 242 | .PP 243 | Multiline table without column headers: 244 | .PP 245 | .TS 246 | tab(@); 247 | cw(10.5n) lw(9.6n) rw(11.4n) lw(23.6n). 248 | T{ 249 | First 250 | T}@T{ 251 | row 252 | T}@T{ 253 | 12.0 254 | T}@T{ 255 | Example of a row that spans multiple lines. 256 | T} 257 | T{ 258 | Second 259 | T}@T{ 260 | row 261 | T}@T{ 262 | 5.0 263 | T}@T{ 264 | Here\[aq]s another one. 265 | Note the blank line between rows. 266 | T} 267 | .TE 268 | -------------------------------------------------------------------------------- /tests/tables.markdown: -------------------------------------------------------------------------------- 1 | Simple table with caption: 2 | 3 | Right Left Center Default 4 | ------- ------ -------- --------- 5 | 12 12 12 12 6 | 123 123 123 123 7 | 1 1 1 1 8 | 9 | : Demonstration of simple table syntax. 10 | 11 | Simple table without caption: 12 | 13 | Right Left Center Default 14 | ------- ------ -------- --------- 15 | 12 12 12 12 16 | 123 123 123 123 17 | 1 1 1 1 18 | 19 | Simple table indented two spaces: 20 | 21 | Right Left Center Default 22 | ------- ------ -------- --------- 23 | 12 12 12 12 24 | 123 123 123 123 25 | 1 1 1 1 26 | 27 | : Demonstration of simple table syntax. 28 | 29 | Multiline table with caption: 30 | 31 | -------------------------------------------------------------- 32 | Centered Left Right Default aligned 33 | Header Aligned Aligned 34 | ----------- ---------- ------------ -------------------------- 35 | First row 12.0 Example of a row that 36 | spans multiple lines. 37 | 38 | Second row 5.0 Here's another one. Note 39 | the blank line between 40 | rows. 41 | -------------------------------------------------------------- 42 | 43 | : Here's the caption. It may span multiple lines. 44 | 45 | Multiline table without caption: 46 | 47 | -------------------------------------------------------------- 48 | Centered Left Right Default aligned 49 | Header Aligned Aligned 50 | ----------- ---------- ------------ -------------------------- 51 | First row 12.0 Example of a row that 52 | spans multiple lines. 53 | 54 | Second row 5.0 Here's another one. Note 55 | the blank line between 56 | rows. 57 | -------------------------------------------------------------- 58 | 59 | Table without column headers: 60 | 61 | ----- ----- ----- ----- 62 | 12 12 12 12 63 | 123 123 123 123 64 | 1 1 1 1 65 | ----- ----- ----- ----- 66 | 67 | Multiline table without column headers: 68 | 69 | ----------- ---------- ------------ -------------------------- 70 | First row 12.0 Example of a row that 71 | spans multiple lines. 72 | 73 | Second row 5.0 Here's another one. Note 74 | the blank line between 75 | rows. 76 | ----------- ---------- ------------ -------------------------- 77 | 78 | 79 | -------------------------------------------------------------------------------- /tests/tables.native: -------------------------------------------------------------------------------- 1 | [Para [Str "Simple",Space,Str "table",Space,Str "with",Space,Str "caption:"] 2 | ,Table [Str "Demonstration",Space,Str "of",Space,Str "simple",Space,Str "table",Space,Str "syntax."] [AlignRight,AlignLeft,AlignCenter,AlignDefault] [0.0,0.0,0.0,0.0] 3 | [[Plain [Str "Right"]] 4 | ,[Plain [Str "Left"]] 5 | ,[Plain [Str "Center"]] 6 | ,[Plain [Str "Default"]]] 7 | [[[Plain [Str "12"]] 8 | ,[Plain [Str "12"]] 9 | ,[Plain [Str "12"]] 10 | ,[Plain [Str "12"]]] 11 | ,[[Plain [Str "123"]] 12 | ,[Plain [Str "123"]] 13 | ,[Plain [Str "123"]] 14 | ,[Plain [Str "123"]]] 15 | ,[[Plain [Str "1"]] 16 | ,[Plain [Str "1"]] 17 | ,[Plain [Str "1"]] 18 | ,[Plain [Str "1"]]]] 19 | ,Para [Str "Simple",Space,Str "table",Space,Str "without",Space,Str "caption:"] 20 | ,Table [] [AlignRight,AlignLeft,AlignCenter,AlignDefault] [0.0,0.0,0.0,0.0] 21 | [[Plain [Str "Right"]] 22 | ,[Plain [Str "Left"]] 23 | ,[Plain [Str "Center"]] 24 | ,[Plain [Str "Default"]]] 25 | [[[Plain [Str "12"]] 26 | ,[Plain [Str "12"]] 27 | ,[Plain [Str "12"]] 28 | ,[Plain [Str "12"]]] 29 | ,[[Plain [Str "123"]] 30 | ,[Plain [Str "123"]] 31 | ,[Plain [Str "123"]] 32 | ,[Plain [Str "123"]]] 33 | ,[[Plain [Str "1"]] 34 | ,[Plain [Str "1"]] 35 | ,[Plain [Str "1"]] 36 | ,[Plain [Str "1"]]]] 37 | ,Para [Str "Simple",Space,Str "table",Space,Str "indented",Space,Str "two",Space,Str "spaces:"] 38 | ,Table [Str "Demonstration",Space,Str "of",Space,Str "simple",Space,Str "table",Space,Str "syntax."] [AlignRight,AlignLeft,AlignCenter,AlignDefault] [0.0,0.0,0.0,0.0] 39 | [[Plain [Str "Right"]] 40 | ,[Plain [Str "Left"]] 41 | ,[Plain [Str "Center"]] 42 | ,[Plain [Str "Default"]]] 43 | [[[Plain [Str "12"]] 44 | ,[Plain [Str "12"]] 45 | ,[Plain [Str "12"]] 46 | ,[Plain [Str "12"]]] 47 | ,[[Plain [Str "123"]] 48 | ,[Plain [Str "123"]] 49 | ,[Plain [Str "123"]] 50 | ,[Plain [Str "123"]]] 51 | ,[[Plain [Str "1"]] 52 | ,[Plain [Str "1"]] 53 | ,[Plain [Str "1"]] 54 | ,[Plain [Str "1"]]]] 55 | ,Para [Str "Multiline",Space,Str "table",Space,Str "with",Space,Str "caption:"] 56 | ,Table [Str "Here's",Space,Str "the",Space,Str "caption.",Space,Str "It",Space,Str "may",Space,Str "span",Space,Str "multiple",Space,Str "lines."] [AlignCenter,AlignLeft,AlignRight,AlignLeft] [0.15,0.1375,0.1625,0.3375] 57 | [[Plain [Str "Centered",Space,Str "Header"]] 58 | ,[Plain [Str "Left",Space,Str "Aligned"]] 59 | ,[Plain [Str "Right",Space,Str "Aligned"]] 60 | ,[Plain [Str "Default",Space,Str "aligned"]]] 61 | [[[Plain [Str "First"]] 62 | ,[Plain [Str "row"]] 63 | ,[Plain [Str "12.0"]] 64 | ,[Plain [Str "Example",Space,Str "of",Space,Str "a",Space,Str "row",Space,Str "that",Space,Str "spans",Space,Str "multiple",Space,Str "lines."]]] 65 | ,[[Plain [Str "Second"]] 66 | ,[Plain [Str "row"]] 67 | ,[Plain [Str "5.0"]] 68 | ,[Plain [Str "Here's",Space,Str "another",Space,Str "one.",Space,Str "Note",Space,Str "the",Space,Str "blank",Space,Str "line",Space,Str "between",Space,Str "rows."]]]] 69 | ,Para [Str "Multiline",Space,Str "table",Space,Str "without",Space,Str "caption:"] 70 | ,Table [] [AlignCenter,AlignLeft,AlignRight,AlignLeft] [0.15,0.1375,0.1625,0.3375] 71 | [[Plain [Str "Centered",Space,Str "Header"]] 72 | ,[Plain [Str "Left",Space,Str "Aligned"]] 73 | ,[Plain [Str "Right",Space,Str "Aligned"]] 74 | ,[Plain [Str "Default",Space,Str "aligned"]]] 75 | [[[Plain [Str "First"]] 76 | ,[Plain [Str "row"]] 77 | ,[Plain [Str "12.0"]] 78 | ,[Plain [Str "Example",Space,Str "of",Space,Str "a",Space,Str "row",Space,Str "that",Space,Str "spans",Space,Str "multiple",Space,Str "lines."]]] 79 | ,[[Plain [Str "Second"]] 80 | ,[Plain [Str "row"]] 81 | ,[Plain [Str "5.0"]] 82 | ,[Plain [Str "Here's",Space,Str "another",Space,Str "one.",Space,Str "Note",Space,Str "the",Space,Str "blank",Space,Str "line",Space,Str "between",Space,Str "rows."]]]] 83 | ,Para [Str "Table",Space,Str "without",Space,Str "column",Space,Str "headers:"] 84 | ,Table [] [AlignRight,AlignLeft,AlignCenter,AlignRight] [0.0,0.0,0.0,0.0] 85 | [[] 86 | ,[] 87 | ,[] 88 | ,[]] 89 | [[[Plain [Str "12"]] 90 | ,[Plain [Str "12"]] 91 | ,[Plain [Str "12"]] 92 | ,[Plain [Str "12"]]] 93 | ,[[Plain [Str "123"]] 94 | ,[Plain [Str "123"]] 95 | ,[Plain [Str "123"]] 96 | ,[Plain [Str "123"]]] 97 | ,[[Plain [Str "1"]] 98 | ,[Plain [Str "1"]] 99 | ,[Plain [Str "1"]] 100 | ,[Plain [Str "1"]]]] 101 | ,Para [Str "Multiline",Space,Str "table",Space,Str "without",Space,Str "column",Space,Str "headers:"] 102 | ,Table [] [AlignCenter,AlignLeft,AlignRight,AlignDefault] [0.15,0.1375,0.1625,0.3375] 103 | [[] 104 | ,[] 105 | ,[] 106 | ,[]] 107 | [[[Plain [Str "First"]] 108 | ,[Plain [Str "row"]] 109 | ,[Plain [Str "12.0"]] 110 | ,[Plain [Str "Example",Space,Str "of",Space,Str "a",Space,Str "row",Space,Str "that",Space,Str "spans",Space,Str "multiple",Space,Str "lines."]]] 111 | ,[[Plain [Str "Second"]] 112 | ,[Plain [Str "row"]] 113 | ,[Plain [Str "5.0"]] 114 | ,[Plain [Str "Here's",Space,Str "another",Space,Str "one.",Space,Str "Note",Space,Str "the",Space,Str "blank",Space,Str "line",Space,Str "between",Space,Str "rows."]]]]] 115 | -------------------------------------------------------------------------------- /tests/tables.plain: -------------------------------------------------------------------------------- 1 | Simple table with caption: 2 | 3 | Right Left Center Default 4 | ------- ------ -------- --------- 5 | 12 12 12 12 6 | 123 123 123 123 7 | 1 1 1 1 8 | 9 | : Demonstration of simple table syntax. 10 | 11 | Simple table without caption: 12 | 13 | Right Left Center Default 14 | ------- ------ -------- --------- 15 | 12 12 12 12 16 | 123 123 123 123 17 | 1 1 1 1 18 | 19 | Simple table indented two spaces: 20 | 21 | Right Left Center Default 22 | ------- ------ -------- --------- 23 | 12 12 12 12 24 | 123 123 123 123 25 | 1 1 1 1 26 | 27 | : Demonstration of simple table syntax. 28 | 29 | Multiline table with caption: 30 | 31 | -------------------------------------------------------------- 32 | Centered Left Right Default aligned 33 | Header Aligned Aligned 34 | ----------- ---------- ------------ -------------------------- 35 | First row 12.0 Example of a row that 36 | spans multiple lines. 37 | 38 | Second row 5.0 Here's another one. Note 39 | the blank line between 40 | rows. 41 | -------------------------------------------------------------- 42 | 43 | : Here's the caption. It may span multiple lines. 44 | 45 | Multiline table without caption: 46 | 47 | -------------------------------------------------------------- 48 | Centered Left Right Default aligned 49 | Header Aligned Aligned 50 | ----------- ---------- ------------ -------------------------- 51 | First row 12.0 Example of a row that 52 | spans multiple lines. 53 | 54 | Second row 5.0 Here's another one. Note 55 | the blank line between 56 | rows. 57 | -------------------------------------------------------------- 58 | 59 | Table without column headers: 60 | 61 | ----- ----- ----- ----- 62 | 12 12 12 12 63 | 123 123 123 123 64 | 1 1 1 1 65 | ----- ----- ----- ----- 66 | 67 | Multiline table without column headers: 68 | 69 | ----------- ---------- ------------ -------------------------- 70 | First row 12.0 Example of a row that 71 | spans multiple lines. 72 | 73 | Second row 5.0 Here's another one. Note 74 | the blank line between 75 | rows. 76 | ----------- ---------- ------------ -------------------------- 77 | 78 | 79 | -------------------------------------------------------------------------------- /tests/tables.txt: -------------------------------------------------------------------------------- 1 | Simple table with caption: 2 | 3 | Right Left Center Default 4 | ------- ------ ---------- ------- 5 | 12 12 12 12 6 | 123 123 123 123 7 | 1 1 1 1 8 | 9 | Table: Demonstration of simple table syntax. 10 | 11 | Simple table without caption: 12 | 13 | Right Left Center Default 14 | ------- ------ ---------- ------- 15 | 12 12 12 12 16 | 123 123 123 123 17 | 1 1 1 1 18 | 19 | Simple table indented two spaces: 20 | 21 | Right Left Center Default 22 | ------- ------ ---------- ------- 23 | 12 12 12 12 24 | 123 123 123 123 25 | 1 1 1 1 26 | 27 | : Demonstration of simple table syntax. 28 | 29 | Multiline table with caption: 30 | 31 | : Here's the caption. 32 | It may span multiple lines. 33 | 34 | --------------------------------------------------------------- 35 | Centered Left Right 36 | Header Aligned Aligned Default aligned 37 | ---------- --------- ----------- --------------------------- 38 | First row 12.0 Example of a row that spans 39 | multiple lines. 40 | 41 | Second row 5.0 Here's another one. Note 42 | the blank line between rows. 43 | --------------------------------------------------------------- 44 | 45 | Multiline table without caption: 46 | 47 | --------------------------------------------------------------- 48 | Centered Left Right 49 | Header Aligned Aligned Default aligned 50 | ---------- --------- ----------- --------------------------- 51 | First row 12.0 Example of a row that spans 52 | multiple lines. 53 | 54 | Second row 5.0 Here's another one. Note 55 | the blank line between rows. 56 | --------------------------------------------------------------- 57 | 58 | Table without column headers: 59 | 60 | ------- ------ ---------- ------- 61 | 12 12 12 12 62 | 123 123 123 123 63 | 1 1 1 1 64 | ------- ------ ---------- ------- 65 | 66 | Multiline table without column headers: 67 | 68 | ---------- --------- ----------- --------------------------- 69 | First row 12.0 Example of a row that spans 70 | multiple lines. 71 | 72 | Second row 5.0 Here's another one. Note 73 | the blank line between rows. 74 | ---------- --------- ----------- --------------------------- 75 | 76 | -------------------------------------------------------------------------------- /tests/test-scholdoc.hs: -------------------------------------------------------------------------------- 1 | {-# OPTIONS_GHC -Wall #-} 2 | 3 | module Main where 4 | 5 | import Test.Framework 6 | import GHC.IO.Encoding 7 | import qualified Tests.Old 8 | import qualified Tests.Readers.LaTeX 9 | import qualified Tests.Readers.Markdown 10 | import qualified Tests.Writers.LaTeX 11 | import qualified Tests.Writers.HTML 12 | import qualified Tests.Writers.Native 13 | import qualified Tests.Writers.Markdown 14 | import qualified Tests.Writers.Plain 15 | import qualified Tests.Shared 16 | import qualified Tests.Walk 17 | import Text.Pandoc.Shared (inDirectory) 18 | import System.Environment (getArgs) 19 | 20 | tests :: [Test] 21 | tests = [ testGroup "Old" Tests.Old.tests 22 | , testGroup "Shared" Tests.Shared.tests 23 | , testGroup "Walk" Tests.Walk.tests 24 | , testGroup "Writers" 25 | [ testGroup "Native" Tests.Writers.Native.tests 26 | , testGroup "LaTeX" Tests.Writers.LaTeX.tests 27 | , testGroup "HTML" Tests.Writers.HTML.tests 28 | , testGroup "Markdown" Tests.Writers.Markdown.tests 29 | , testGroup "Plain" Tests.Writers.Plain.tests 30 | ] 31 | , testGroup "Readers" 32 | [ testGroup "LaTeX" Tests.Readers.LaTeX.tests 33 | , testGroup "Markdown" Tests.Readers.Markdown.tests 34 | ] 35 | ] 36 | 37 | main :: IO () 38 | main = do 39 | setLocaleEncoding utf8 40 | args <- getArgs 41 | inDirectory "tests" $ defaultMainWithArgs tests args 42 | -------------------------------------------------------------------------------- /tryscholdoc/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Dingus | ScholarlyMarkdown 6 | 7 | 8 | 9 | 49 | 60 | 61 | 62 |
63 |
64 |

ScholarlyMarkdown Dingus

65 |
66 |
67 |
68 | 71 |
72 | 73 |
74 |
75 | 78 | 83 |   84 | 85 |
86 |

87 |     
88 |
89 |
90 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /tryscholdoc/tryscholdoc.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE OverloadedStrings #-} 2 | module Main where 3 | import Network.Wai.Handler.CGI 4 | import Network.Wai 5 | import Control.Applicative ((<$>)) 6 | import Data.Maybe (mapMaybe, fromMaybe) 7 | import Network.HTTP.Types.Status (status200) 8 | import Network.HTTP.Types.Header (hContentType) 9 | import Network.HTTP.Types.URI (queryToQueryText) 10 | import Text.Pandoc 11 | import Text.Pandoc.Shared (tabFilter) 12 | import Text.Highlighting.Kate (pygments) 13 | import Data.Aeson 14 | import qualified Data.Text as T 15 | import Data.Text (Text) 16 | 17 | main :: IO () 18 | main = run app 19 | 20 | app :: Application 21 | app req respond = do 22 | let query = queryToQueryText $ queryString req 23 | let getParam x = maybe (error $ T.unpack x ++ " paramater not set") 24 | return $ lookup x query 25 | text <- getParam "text" >>= checkLength . fromMaybe T.empty 26 | fromFormat <- fromMaybe "" <$> getParam "from" 27 | toFormat <- fromMaybe "" <$> getParam "to" 28 | reader <- maybe (error $ "could not find reader for " ++ T.unpack fromFormat) return 29 | $ lookup fromFormat fromFormats 30 | let writer = maybe (error $ "could not find writer for " ++ T.unpack toFormat) id 31 | $ lookup toFormat toFormats 32 | let result = T.pack $ writer $ reader $ tabFilter 4 $ T.unpack text 33 | let output = encode $ object [ T.pack "result" .= result 34 | , T.pack "name" .= 35 | if fromFormat == "markdown_strict" 36 | then T.pack "scholdoc (strict)" 37 | else T.pack "scholdoc" 38 | , T.pack "version" .= scholdocVersion] 39 | respond $ responseLBS status200 [(hContentType,"text/json; charset=UTF-8")] output 40 | 41 | checkLength :: Text -> IO Text 42 | checkLength t = 43 | if T.length t > 10000 44 | then error "exceeds length limit of 10,000 characters" 45 | else return t 46 | 47 | writerOpts :: WriterOptions 48 | writerOpts = def { writerReferenceLinks = True, 49 | writerEmailObfuscation = NoObfuscation, 50 | writerHTMLMathMethod = MathJax "https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS_HTML-full", 51 | writerScholarly = True, 52 | writerHighlight = True, 53 | writerHighlightStyle = pygments } 54 | 55 | readerOpts :: ReaderOptions 56 | readerOpts = def { readerParseRaw = True, 57 | readerSmart = True } 58 | 59 | fromFormats :: [(Text, String -> Pandoc)] 60 | fromFormats = [ 61 | ("native" , readNative) 62 | ,("json" , Text.Pandoc.readJSON readerOpts) 63 | ,("markdown_scholarly", readMarkdown readerOpts{ 64 | readerExtensions = scholarlyMarkdownExtensions}) 65 | ] 66 | 67 | toFormats :: [(Text, Pandoc -> String)] 68 | toFormats = mapMaybe (\(x,y) -> 69 | case y of 70 | PureStringWriter w -> Just (T.pack x, w writerOpts{ 71 | writerExtensions = 72 | case x of 73 | "markdown_strict" -> strictExtensions 74 | "markdown_phpextra" -> phpMarkdownExtraExtensions 75 | "markdown_mmd" -> multimarkdownExtensions 76 | "markdown_github" -> githubMarkdownExtensions 77 | "markdown" -> pandocExtensions 78 | _ -> scholarlyMarkdownExtensions 79 | }) 80 | _ -> Nothing) writers 81 | 82 | -------------------------------------------------------------------------------- /windows/make-windows-installer.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | cd .. 3 | cabal update 4 | cabal sandbox init 5 | cabal clean 6 | cabal install hsb2hs 7 | if %errorlevel% neq 0 exit /b %errorlevel% 8 | cabal install -v1 --force --reinstall --flags="embed_data_files" . scholdoc-citeproc 9 | if %errorlevel% neq 0 exit /b %errorlevel% 10 | strip .\.cabal-sandbox\bin\scholdoc.exe 11 | strip .\.cabal-sandbox\bin\scholdoc-citeproc.exe 12 | copy COPYRIGHT COPYRIGHT.txt 13 | :: for /f "tokens=1-2 delims= " %%a in ('.\.cabal-sandbox\bin\scholdoc --version') do ( 14 | :: @set VERSION=%%b 15 | :: goto :next 16 | :: ) 17 | @set VERSION=0.1.3 18 | :next 19 | if "%VERSION%" == "" ( 20 | echo Error: could not determine version number. 21 | exit /b 1 22 | ) 23 | echo Detected version %VERSION% 24 | cd windows 25 | echo Creating msi... 26 | candle -dVERSION=%VERSION% scholdoc.wxs 27 | if %errorlevel% neq 0 exit /b %errorlevel% 28 | light -sw1076 -ext WixUIExtension -out scholdoc-%VERSION%-alpha-windows.msi scholdoc.wixobj 29 | if %errorlevel% neq 0 exit /b %errorlevel% 30 | :: echo Starting kSign: sign, then quit kSign to complete the build... 31 | :: kSign 32 | -------------------------------------------------------------------------------- /windows/scholdoc.wxs: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 8 | 9 | 11 | 12 | 13 | 14 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | ACTION="INSTALL" AND APPLICATIONFOLDER="" AND (ALLUSERS="" OR (ALLUSERS=2 AND (NOT Privileged))) 30 | ACTION="INSTALL" AND APPLICATIONFOLDER="" AND (ALLUSERS=1 OR (ALLUSERS=2 AND Privileged)) 31 | 32 | 33 | ACTION="INSTALL" AND APPLICATIONFOLDER="" AND (ALLUSERS="" OR (ALLUSERS=2 AND (NOT Privileged))) 34 | ACTION="INSTALL" AND APPLICATIONFOLDER="" AND (ALLUSERS=1 OR (ALLUSERS=2 AND Privileged)) 35 | 36 | 37 | 38 | 39 | 40 | 41 | 43 | 45 | 46 | 48 | 50 | 52 | 53 | 54 | 56 | 58 | 60 | 61 | 62 | 64 | 65 | 67 | 69 | 70 | 71 | 73 | 74 | 76 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | --------------------------------------------------------------------------------