Compare commits

...

193 Commits

Author SHA1 Message Date
Sebastian Pfitzner 77793c775c
Merge pull request #481 from dlfivefifty/patch-2
Mention Quarto in Related Packages
2024-04-16 12:50:53 +02:00
Sheehan Olver ad0885ce00
Update README.md 2024-04-16 11:43:11 +01:00
Sebastian Pfitzner e10aaefd94
Merge pull request #469 from laborg/master
Update RelocatableFolders dependency
2023-02-10 10:39:25 +01:00
Sebastian Pfitzner 8ad4e876d3
Merge pull request #448 from xgdgsc/patch-1
display example needs to be fixed
2023-02-10 10:32:25 +01:00
Sebastian Pfitzner af2a6e14c9
Merge pull request #462 from NicholasWMRitchie/nwmr
Force deletion of the temporary figure path to address Issue #440
2023-02-10 10:32:01 +01:00
Sebastian Pfitzner 20aaefec0a
Merge pull request #465 from newptcai/font-size
Removed hard coded font size for PDF
2023-02-10 10:29:31 +01:00
Gerhard Aigner 2a78676d41 update relocatablefolders.jl dependency 2023-02-10 09:04:49 +01:00
Gerhard Aigner 59332c1768 relax dataframe displayed row counting 2023-02-10 09:02:10 +01:00
Sebastian Pfitzner db28a69d94
Merge pull request #468 from dlfivefifty/patch-1
Mention Literate.jl in README.md
2023-01-18 16:55:11 +01:00
Sheehan Olver 0b96591f39
Mention Literate.jl in README.md 2023-01-18 14:52:44 +00:00
Sebastian Pfitzner a38cec95db
0.10.11 2022-12-12 10:02:01 +01:00
Sebastian Pfitzner 562f8e4ab3
v0.10.12 2022-12-12 09:17:50 +01:00
Sebastian Pfitzner 9f666b3bb5
Merge pull request #466 from KristofferC/kc/require
avoid warning when using Weave in a sysimage
2022-12-12 09:17:27 +01:00
KristofferC a63577f69c avoid warning when using Weave in a sysimage 2022-12-07 11:14:48 +01:00
Xing Shi Cai 7e0f5641c2 Removed hard coded font size for PDF 2022-10-19 14:37:58 +08:00
Nicholas W. M. Ritchie b022a54458 Add isnothing(fig_path) check 2022-07-13 09:51:59 -04:00
Nicholas W. M. Ritchie b669a14038 Force deletion of the temporary figure path to address Issue #440 2022-07-13 09:35:48 -04:00
Sebastian Pfitzner b7941c2811
Merge pull request #457 from ExpandingMan/em/highlightup
bumped highlights version
2022-05-19 16:09:14 +02:00
ExpandingMan d40e95a4bb bumped highlights version 2022-05-19 09:43:14 -04:00
xgdgsc df47ea191f
HTML( 2022-02-14 15:33:21 +08:00
Sebastian Pfitzner 381de22c7d
Merge pull request #428 from JunoLab/compathelper/new_version/2021-06-22-00-09-55-226-3473194155
CompatHelper: add new compat entry for "RelocatableFolders" at version "0.1"
2021-06-22 10:05:31 +02:00
github-actions[bot] 06b259a7b0 CompatHelper: add new compat entry for "RelocatableFolders" at version "0.1" 2021-06-22 00:09:55 +00:00
Sebastian Pfitzner 749c0c262c
v0.10.10 2021-06-21 09:49:07 +02:00
Sebastian Pfitzner 696db1d82b
Merge pull request #426 from MichaelHatherly/mh/package-compiler-friendly-assets
Make assets `PackageCompiler`-friendly
2021-06-21 09:48:51 +02:00
Mike d4c65729e4
Use `RelocatableFolders` for assets folders. 2021-06-18 09:50:38 +01:00
Mike 1dfb8d76d6
Make assets `PackageCompiler`-friendly
A possible solution to relocatablilty issues with the hardcoded paths.

Embeds the asset folder contents into the precompiled files. When the
original folder isn't available (due to relocation) creates a
scratchspace containing the original folder contents as uses that
instead.
2021-06-12 09:21:20 +01:00
Sebastian Pfitzner 48c99c791f
0.10.9 2021-06-01 10:14:36 +02:00
Sebastian Pfitzner ec3f464c37
Merge pull request #424 from MichaelHatherly/mh/latex-method-warning
Fix #388.
2021-06-01 09:56:04 +02:00
Mike 4c60bd8d64
Fix #388.
Replaces the `IO` argument with a `Union{IOBuffer,IOContext}` which
should be the only types that are actually reachable since the code
paths pass through `sprint`, which only uses either of those.

It's still not a perfect fix due to the type piracy, as noted in the
comments, but avoids the method overwrite warning at least.
2021-06-01 08:42:02 +01:00
Sebastian Pfitzner e1d31c2ef6
v0.10.8 2021-04-29 14:49:53 +02:00
Shuhei Kadowaki 99916dd70c
Merge pull request #423 from JunoLab/sp/fix-chunk-options
fix chunk options regression
2021-04-29 21:18:16 +09:00
Sebastian Pfitzner 6b6f82bed4 fix chunk options regression 2021-04-29 13:12:08 +02:00
Shuhei Kadowaki b1de7efede
Merge pull request #416 from nateybear/patch-1
Change tex escaping to tex comments
2021-03-14 03:53:00 +09:00
Nathan Hattersley 849cc20e88
Change tex escaping to tex comments
Take more opinionated stance on TeX inside julia blocks--LaTeX belongs in comments.
2021-03-12 14:43:38 -06:00
Shuhei Kadowaki 10de1057a3 version 0.10.7 2021-03-03 18:44:23 +09:00
Shuhei Kadowaki e753f70f7a
Merge pull request #413 from pgunnink/fix-out-path
Fix for out_path only working for directories
2021-03-03 18:43:06 +09:00
PGunnink 8dc0441b90 Fix for out_path only working for directories 2021-03-02 19:37:12 +01:00
Shuhei Kadowaki c9fc740d72
Merge pull request #380 from JonasIsensee/exportaswrapper
Export formats as wrapper
2020-10-03 16:32:35 +09:00
Shuhei Kadowaki cc5913e812
Update src/rendering/htmlformats.jl 2020-10-03 16:29:44 +09:00
JonasIsensee e02d5ce2fd
Update src/rendering/exportformat.jl
Co-authored-by: Shuhei Kadowaki <40514306+aviatesk@users.noreply.github.com>
2020-10-03 08:51:22 +02:00
Shuhei Kadowaki b583ac2e40 don't end2end test for `minted2pdf` 2020-10-03 13:50:41 +09:00
Shuhei Kadowaki 955675d89a Merge branch 'master' into exportaswrapper 2020-10-03 13:38:33 +09:00
Shuhei Kadowaki 196d4ca7ce don't decl const for `WEAVE_ARGS` 2020-10-03 13:17:39 +09:00
Shuhei Kadowaki d3a7f2aea7 version 0.10.6 2020-10-03 04:50:49 +09:00
Shuhei Kadowaki 7d361bb40d
Merge pull request #401 from JunoLab/avi/fix400
fixes #400
2020-10-03 04:49:15 +09:00
Shuhei Kadowaki e927495a62 fixes #400 2020-10-03 04:44:52 +09:00
Shuhei Kadowaki 78befc61b5 version 0.10.5 2020-09-30 19:07:26 +09:00
Shuhei Kadowaki c24a262135 allow arbitrary runtime argument 2020-09-30 18:43:15 +09:00
Shuhei Kadowaki 3e8200c2f8
Merge pull request #399 from JunoLab/avi/fixmkdir
fixes #398
2020-09-30 18:42:20 +09:00
Shuhei Kadowaki 8f23084471 fixes #398 2020-09-30 18:28:22 +09:00
Shuhei Kadowaki a1830e0502 triple quote for markdown output 2020-09-28 01:10:21 +09:00
Shuhei Kadowaki 0e662ecdec
Merge pull request #397 from baggepinnen/patch-2
Import Dates
2020-09-26 15:52:23 +09:00
Fredrik Bagge Carlson fa71830479
Import Dates
One must now `import Dates` for `now, Date` to be defined.
2020-09-26 08:41:42 +02:00
Shuhei Kadowaki 21d7fbdbea version 0.10.4 2020-09-25 00:41:30 +09:00
Shuhei Kadowaki fe3711074b
Merge pull request #396 from torfjelde/patch-1
Fix for #386
2020-09-25 00:39:11 +09:00
Tor Erlend Fjelde 766847ec65
fix for #386 2020-09-24 16:09:33 +01:00
Shuhei Kadowaki 46a0f8bff4
Merge pull request #393 from odow/patch-1
Fix typo in header.md
2020-09-04 13:13:52 +09:00
Oscar Dowson 51f905ca83
Fix typo in header.md 2020-09-04 16:03:58 +12:00
Sebastian Pfitzner b5ba227e75
0.10.3 2020-08-17 10:13:39 +02:00
Sebastian Pfitzner 74768a7e0f
Merge pull request #357 from baggepinnen/patch-2
[RFC] Do not define Markdown.latex using eval
2020-08-17 10:13:20 +02:00
Jonas Isensee 90d8c8430f do the same for pandoc exports 2020-06-15 20:41:46 +02:00
Jonas Isensee a61ade7778 implement general `ExportFormat` 2020-06-15 20:39:15 +02:00
Jonas Isensee 8ac94989f1 fix rendering bug in output 2020-06-15 20:38:53 +02:00
Jonas Isensee 191282c1e5 implement LaTeXPDF as wrapper 2020-06-15 20:19:36 +02:00
Shuhei Kadowaki d8eca00fd8 fix regression 2020-06-14 22:54:27 +09:00
Shuhei Kadowaki 957d12e751
Merge pull request #377 from JunoLab/avi/simpletest
add simple end2end test
2020-06-14 21:39:18 +09:00
Shuhei Kadowaki 82c7c2a8c6 rename formats 2020-06-14 21:33:55 +09:00
Shuhei Kadowaki ba5bc9ca08
Merge pull request #376 from JunoLab/avi/preserveheader
preserve header for pandoc formats
2020-06-14 21:33:30 +09:00
Shuhei Kadowaki 5f0d9d4627 add simple end2end test 2020-06-14 21:32:04 +09:00
Shuhei Kadowaki 676ecc64f9 preserve header for pandoc formats 2020-06-14 20:57:37 +09:00
Shuhei Kadowaki 2a509d8f96 reorganize things 2020-06-14 18:15:05 +09:00
Shuhei Kadowaki 9b2a1228cd fix terminology, reorder arguments 2020-06-14 18:10:31 +09:00
Shuhei Kadowaki 785768c728
Merge pull request #374 from JunoLab/avi/write
refactor document writing
2020-06-14 18:08:01 +09:00
Shuhei Kadowaki 7e9c4fb99d dispatch-base documentation generation 2020-06-14 16:36:51 +09:00
Shuhei Kadowaki 29546b7716 more generic name 2020-06-14 15:15:11 +09:00
Shuhei Kadowaki db5308b286 reorder function definition, rename `JMarkdown2tex` to `JMarkdown2PDF` 2020-06-14 14:49:48 +09:00
Shuhei Kadowaki 174585e504
Merge pull request #362 from JonasIsensee/texpipeline
Improvements to the tex rendering pipeline
2020-06-14 14:35:46 +09:00
Shuhei Kadowaki 8206ca2d14 fix `set_chunk_options!` 2020-06-14 14:25:21 +09:00
Shuhei Kadowaki 092adb6805 update test 2020-06-14 14:25:03 +09:00
Shuhei Kadowaki 872f7c7153 construct UNICODE2LATEX at precompile time 2020-06-14 13:56:59 +09:00
Shuhei Kadowaki 5ae1fd5cf1 Merge branch 'master' into texpipeline 2020-06-14 13:36:18 +09:00
Shuhei Kadowaki bd447ec8e3 update links 2020-06-14 13:34:43 +09:00
Jonas Isensee 3dfe817584 fix bug 2020-06-13 22:56:23 +02:00
Jonas Isensee 12e148af18 move unicode2tex escape characters to struct 2020-06-13 22:16:48 +02:00
Shuhei Kadowaki 03079a5dac update README 2020-06-14 04:19:20 +09:00
Shuhei Kadowaki e179bd098e replace CI badge 2020-06-14 04:17:34 +09:00
Shuhei Kadowaki 4a96f2c19a add codecov badge 2020-06-14 04:15:45 +09:00
Shuhei Kadowaki 7955308a0a
Merge pull request #314 from JunoLab/avi/actions
use GitHub actions for tests, enable faster CI cycle
2020-06-14 04:15:08 +09:00
Shuhei Kadowaki 21835644a0 enable GitHub actions CI for faster test cycle 2020-06-14 04:08:28 +09:00
Shuhei Kadowaki 5a585f845a improve ansi character removal 2020-06-14 04:06:25 +09:00
Shuhei Kadowaki f077609798 fix repository url 2020-06-14 04:05:28 +09:00
Shuhei Kadowaki 46a0da597d
Merge pull request #373 from JunoLab/avi/fixtermresult
improve term result
2020-06-14 02:52:33 +09:00
Shuhei Kadowaki 2070610a58 🔥 Plots.jl/Gadfly.jl integration test 2020-06-14 02:25:32 +09:00
Shuhei Kadowaki 7d6fddc749 improve term result 2020-06-14 01:53:17 +09:00
Shuhei Kadowaki dadce5110c
Merge pull request #372 from JunoLab/avi/fire
🔥
2020-06-14 01:43:55 +09:00
Shuhei Kadowaki 5d3dd15733 🔥 2020-06-14 01:43:32 +09:00
Shuhei Kadowaki 608bb3df4a
Merge pull request #371 from JunoLab/avi/error
follow RMarkdown more: make `throw_error` option into chunk option
2020-06-14 00:02:54 +09:00
Shuhei Kadowaki b569740915 rm tests with "tex" format 2020-06-14 00:02:05 +09:00
Shuhei Kadowaki 972869da47 Merge branch 'master' into pr-362/JonasIsensee/texpipeline 2020-06-13 23:45:43 +09:00
Shuhei Kadowaki e0a9d044cd
Merge pull request #370 from JunoLab/avi/type
fix `Report` typings, and hooks
2020-06-13 23:19:29 +09:00
Shuhei Kadowaki 912387c331 follow RMarkdown more: make `throw_error` option into chunk option 2020-06-13 23:09:51 +09:00
Jonas Isensee 1135c5ddfa Remove "tex" format 2020-06-13 15:50:04 +02:00
Shuhei Kadowaki c1bc2fd5c5 fix weird typings of `Report` 2020-06-13 22:44:13 +09:00
Shuhei Kadowaki d586c24792 clean up:
- unused `:display` chunk option
- rm `displayed` chunk field
- rm `cur_result`, `pendind_code`, `term_state` `Report` field
- rm `:skip` config option
- rm unfunctional `include` chunk option for now
2020-06-13 22:44:13 +09:00
Shuhei Kadowaki d468912332
Merge pull request #369 from JunoLab/avi/cleanup
clean up:
2020-06-13 22:39:34 +09:00
Shuhei Kadowaki 753afe24d7
Merge pull request #368 from JunoLab/avi/config
config powerup
2020-06-13 22:23:55 +09:00
Shuhei Kadowaki c0e7e66ec3 clean up:
- unused `:display` chunk option
- rm `displayed` chunk field
- rm `cur_result`, `pendind_code`, `term_state` `Report` field
- rm `:skip` config option
2020-06-13 21:59:09 +09:00
Shuhei Kadowaki fd07d2db3f
Merge pull request #367 from JunoLab/avi/fixpath
fix paths
2020-06-13 21:52:11 +09:00
Shuhei Kadowaki 8d95e159e2 config powerup 2020-06-13 21:42:09 +09:00
Shuhei Kadowaki 9fac56f681 why `get_outname` defined in run.jl 2020-06-13 21:14:44 +09:00
Shuhei Kadowaki b709ce8aef
Merge pull request #364 from JunoLab/avi/fix263
fixes #263
2020-06-13 21:14:02 +09:00
Shuhei Kadowaki 4a89b04759 fix `get_cwd` 2020-06-13 20:48:44 +09:00
Shuhei Kadowaki ec986b387b `cd` into doc's working directory 2020-06-13 20:42:57 +09:00
Jonas Isensee 5c853150c8 fix math escapes in code and output 2020-06-13 09:14:12 +02:00
Shuhei Kadowaki f8b1c5104b more test clean up 2020-06-11 20:28:55 +09:00
Shuhei Kadowaki d88675d521 rm rich_output test
will be replaced by per-format rendering test
2020-06-11 20:26:25 +09:00
Shuhei Kadowaki e52c30f72e add test 2020-06-11 20:20:42 +09:00
Shuhei Kadowaki 66c33e6679 fixes #263 2020-06-11 20:20:30 +09:00
Shuhei Kadowaki cdd653e028 make Weave.path really path 2020-06-10 01:24:08 +09:00
Shuhei Kadowaki 8515c0dcde SandBox -> mod 2020-06-10 00:36:40 +09:00
Shuhei Kadowaki 3a7cb360af
Merge pull request #363 from JunoLab/avi/fixregression
fix header regression, add test, update test
2020-06-05 19:56:30 +09:00
Shuhei Kadowaki c7b566aaaa fix header regression, add test, update test 2020-06-05 18:59:02 +09:00
Jonas Isensee 630ac466e7 Reapply improvements to the tex rendering pipeline 2020-06-03 14:13:07 +02:00
Shuhei Kadowaki 3e6cda8950
Merge pull request #361 from JunoLab/avi/list
make `list_out_formats` return return just data structure
2020-06-02 19:57:59 +09:00
Shuhei Kadowaki f1d8838bc5
Merge pull request #360 from JunoLab/avi/refc
yet another clean up:
2020-06-02 19:52:46 +09:00
Shuhei Kadowaki 3faa8e2d95 make `list_out_formats` return return just data structure 2020-06-02 19:35:07 +09:00
Shuhei Kadowaki 3ddb1375eb yet another clean up:
- remove weird dispatches
- rm unused `result_no` field
2020-06-02 19:25:34 +09:00
Shuhei Kadowaki 73bf7fe77f
Merge pull request #350 from JonasIsensee/texexports
Reworking format.jl
2020-06-02 19:24:13 +09:00
Shuhei Kadowaki 533667b9ad type annotate API 2020-06-02 19:03:30 +09:00
Shuhei Kadowaki aa7fd311d8 use isnothing & isempty 2020-06-02 19:00:40 +09:00
Shuhei Kadowaki 0760591021 bump up to julia 1.2 2020-06-02 15:48:02 +09:00
Shuhei Kadowaki 04b24ea83b a bit more reorder 2020-06-02 15:45:38 +09:00
Shuhei Kadowaki 4b12f3da99 reorder functions again 2020-06-02 15:40:04 +09:00
Shuhei Kadowaki c6b23d4541 drop LTS support:
- first, it's really dull to keep compatibility with LTS
- and now we want to use `Base.@kwdef` for creating types with 
supertypes, and LTS can't have that for reasons
2020-06-02 15:33:17 +09:00
Shuhei Kadowaki ae48729cff use type field to restore header check 2020-06-02 15:31:41 +09:00
Shuhei Kadowaki 19b4a7974f reorder WeaveFormat field defs 2020-06-02 15:31:18 +09:00
Shuhei Kadowaki 0bdab33630 Merge branch 'master' into texexports 2020-06-01 22:45:32 +09:00
Shuhei Kadowaki 55d2c975cd set rendering options with dispatch:
- remove unused field defs
- in theory extensible, once documented
- fix test
- start to change terminology, `format` -> `render`
2020-06-01 22:36:48 +09:00
Shuhei Kadowaki ae0dc70ffa refactoring:
- reorder/move things so that format-specific rendering methods are 
defined close to the format
- separate common rendering methods from format specific methods
- fix using location
2020-06-01 21:32:18 +09:00
Jonas Isensee 543f99a915 rename files and include location + move texify 2020-05-31 18:04:40 +02:00
Jonas Isensee b5477d27ff revert improvements to tex rendering 2020-05-31 17:33:11 +02:00
Jonas Isensee 9875bc10f7 pass fewer arguments and bugfixes 2020-05-31 13:26:27 +02:00
Jonas Isensee 45adb8992f some cleanup 2020-05-31 12:07:26 +02:00
Jonas Isensee 3eba5de7f4 make `texminted` output valid texfile 2020-05-31 11:48:37 +02:00
Jonas Isensee 62d56846f4 fix lots of things I missed before 2020-05-31 09:49:20 +02:00
Jonas Isensee 770496b3af remove format dict - make everything a field of format <: WeaveFormat directly 2020-05-31 09:29:26 +02:00
Jonas Isensee 6e99822905 removing duplicate code 2020-05-30 18:02:49 +02:00
Jonas Isensee 119b3332aa move around code into separate files 2020-05-30 17:49:20 +02:00
Shuhei Kadowaki 9ccf3a2c5e
Merge pull request #359 from JunoLab/avi/figpath
respect specied `fig_path`
2020-05-30 23:57:53 +09:00
Shuhei Kadowaki db89118b4c fix typing and improve `@define_format` 2020-05-30 22:46:20 +09:00
Shuhei Kadowaki e7637de643 Merge branch 'master' into texexports 2020-05-30 22:22:10 +09:00
Shuhei Kadowaki e0e9ae8753 respect specied `fig_path`
- closes #358
2020-05-30 22:14:50 +09:00
Shuhei Kadowaki 5b959a972c
Merge pull request #355 from JunoLab/avi/refactorformatters
refactor formatters.jl
2020-05-30 22:14:38 +09:00
Shuhei Kadowaki 788f926067 move description field into `formatdict` 2020-05-30 21:16:03 +09:00
Fredrik Bagge Carlson c87782f451
[RFC] Do not define Markdown.latex using eval
This PR solves #356 at the expense of a warning:
```
WARNING: Method definition latex(IO, Markdown.LaTeX) in module Markdown at /home/fredrikb/julia/usr/share/julia/stdlib/v1.5/Markdown/src/IPython/IPython.jl:28 overwritten in module WeaveMarkdown at /home/fredrikb/.julia/dev/Weave/src/WeaveMarkdown/markdown.jl:10.
  ** incremental compilation may be fatally broken for this module **
```
2020-05-27 13:04:51 +02:00
Shuhei Kadowaki 96de887308 basic assertion 2020-05-26 10:44:30 +09:00
Shuhei Kadowaki aa63b20e7c remove unncessary :doctype field 2020-05-25 22:39:59 +09:00
Shuhei Kadowaki cc936f5377 refactor formatters.jl 2020-05-25 22:39:37 +09:00
Shuhei Kadowaki f4ed10b625 define render_doc and dispatch on it with different formats
- and load minted package for TexMinted format

Co-Authored-By: null <JonasIsensee@users.noreply.github.com>
2020-05-25 20:29:57 +09:00
Shuhei Kadowaki 2fdd09b585 introduce WeaveFormat abstract type
well, we can do much more things using this, but this commit just 
introduces this type

Co-Authored-By: null <JonasIsensee@users.noreply.github.com>
2020-05-25 20:29:57 +09:00
Jonas Isensee e20042848d introduce common supertype for JMarkdown2tex and Tex 2020-05-25 20:29:57 +09:00
Shuhei Kadowaki 1e9ba19db4 fix wording 2020-05-25 12:22:33 +09:00
Shuhei Kadowaki 14b56f1667
Merge pull request #353 from JunoLab/avi/rmarkdownchunks
RMarkdown style chunk options
2020-05-25 12:13:28 +09:00
Shuhei Kadowaki 227ab2cbf8 informative test skipping 2020-05-25 11:46:54 +09:00
Shuhei Kadowaki 84e91104d5 maybe fix type errors 2020-05-25 11:44:09 +09:00
Shuhei Kadowaki 44ed8788d5 LTS compat ... 2020-05-25 11:44:09 +09:00
Shuhei Kadowaki 022bb216eb general documentation improvements 2020-05-25 11:44:09 +09:00
Shuhei Kadowaki e43a2843af descriptions for RMarkdown style chunk option specs 2020-05-25 11:44:09 +09:00
Shuhei Kadowaki bb4ebb105e add tests cases for RMarkdown styel chunk option passing 2020-05-25 11:44:09 +09:00
Shuhei Kadowaki b0db8b991c allow RMarkdown style chunk option passing:
e.g.:
- `julia, k1 = v1`
- `{julia, k1 = v1}`
- `julia k1 = v1`
2020-05-25 11:44:09 +09:00
Shuhei Kadowaki dd0c51b6e5 improve type definition of CodeChunk 2020-05-25 11:44:09 +09:00
Shuhei Kadowaki 3d4f04902c
Merge pull request #354 from JunoLab/avi/onlyci
trigger tests for Plots.jl and Gadfly.jl only on CI
2020-05-25 10:55:06 +09:00
Shuhei Kadowaki e9c9274896 trigger tests for Plots.jl and Gadfly.jl only on CI 2020-05-25 10:14:45 +09:00
Shuhei Kadowaki 542f3e3225
Merge pull request #351 from JunoLab/avi/refactorreader
refactor /reader/
2020-05-24 23:29:53 +09:00
Shuhei Kadowaki 976d822f58 refactor /reader/ 2020-05-24 22:54:58 +09:00
Shuhei Kadowaki 819079c0f6
Merge pull request #349 from JunoLab/avi/fixunicode
fixes #348
2020-05-24 21:38:57 +09:00
Shuhei Kadowaki b62a744dfe update tests:
- create new test_inline.jl
- add tests to check inline code parser handlers unicode correctly
- create end2end.jl, which temporarily keeps old end2end tests
2020-05-24 21:11:09 +09:00
Shuhei Kadowaki eca4ed2559 handle codeunits gracefully in inline chunks 2020-05-24 18:17:58 +09:00
Shuhei Kadowaki 9b55d7e924
Merge pull request #347 from JunoLab/avi/pandochighlight
fix no highlight style error on pandoc2(html|pdf) output
2020-05-24 18:16:17 +09:00
Shuhei Kadowaki 0fc915b748 use same logic 2020-05-24 17:06:31 +09:00
Shuhei Kadowaki 39d3d8d91c fix no highlight style error on pandoc2(html|pdf) output 2020-05-24 16:18:58 +09:00
Shuhei Kadowaki 125d73982e
Merge pull request #344 from JunoLab/avi/renames
more consistent templates names, move stylesheets into ./stylesheets
2020-05-24 15:50:57 +09:00
Shuhei Kadowaki 0bc0d3b510 more consistent templates names, move stylesheets into ./stylesheets 2020-05-24 14:16:37 +09:00
Shuhei Kadowaki b8b9b095b7 fix tests:
- revert changes introduced in 1fb4065 in test suite
2020-05-24 14:05:29 +09:00
Shuhei Kadowaki 48adeff932 serious fix 2020-05-24 03:38:32 +09:00
Shuhei Kadowaki a7de8f5f58 minor fix 2020-05-24 03:17:24 +09:00
Shuhei Kadowaki 60fc450c88
Merge pull request #341 from JunoLab/avi/preprefactor
pre #338
2020-05-24 03:14:11 +09:00
Shuhei Kadowaki 1fb40645ed refactors: almost just about code styles, doesn't change any behaviour 2020-05-24 02:36:32 +09:00
Shuhei Kadowaki 9ca328f468 add TODO 2020-05-23 23:50:28 +09:00
Shuhei Kadowaki d84504267b addspaces -> addlines 2020-05-23 23:49:29 +09:00
Shuhei Kadowaki 29ff436a00 consistent and clearer terminology:
- formatted -> body/rendered
- wdate -> weave_date
- wsource (or source) -> weave_source
- wdate -> weave_date
2020-05-23 23:05:36 +09:00
Shuhei Kadowaki 3c76b804dc separate format logic from WeaveDoc:
- this is just a first step, though
2020-05-23 22:16:56 +09:00
Shuhei Kadowaki f71a491847 rm unused stuff 2020-05-23 22:04:01 +09:00
110 changed files with 2293 additions and 3430 deletions

67
.github/workflows/ci.yml vendored Normal file
View File

@ -0,0 +1,67 @@
# TODO: build docs via github-actions
name: CI
on:
push:
branches:
- master
pull_request:
jobs:
test:
name: Julia ${{ matrix.version }} - ${{ matrix.os }} - ${{ matrix.arch }}
runs-on: ${{ matrix.os }}
continue-on-error: ${{ matrix.allow-failure }}
strategy:
fail-fast: false # don't stop CI even when one of them fails
matrix:
version:
- '1.5'
os:
- ubuntu-latest
- macOS-latest
# - windows-latest # TODO: test on Windows
arch:
- x64
- x86
allow-failure: [false]
include:
# this is so verbose... any other way to simplify this ?
- version: 'nightly'
os: ubuntu-latest
arch: x64
allow-failure: true
- version: 'nightly'
os: ubuntu-latest
arch: x86
allow-failure: true
- version: 'nightly'
os: macOS-latest
arch: x64
allow-failure: true
# - version: 'nightly'
# os: windows-latest
# arch: x64
# allow-failure: true
# - version: 'nightly'
# os: windows-latest
# arch: x86
# allow-failure: true
exclude:
- os: macOS-latest
arch: x86
steps:
- uses: actions/checkout@v2
- uses: julia-actions/setup-julia@v1
with:
version: ${{ matrix.version }}
arch: ${{ matrix.arch }}
- uses: julia-actions/julia-buildpkg@latest
- uses: julia-actions/julia-runtest@latest
- uses: julia-actions/julia-processcoverage@v1
- uses: codecov/codecov-action@v1
with:
file: ./lcov.info
flags: unittests
name: codecov-umbrella
fail_ci_if_error: false
token: ${{ secrets.CODECOV_TOKEN }}

9
.gitignore vendored
View File

@ -1,6 +1,5 @@
Manifest.toml
src/*.cov
test.jl
examples/figures/
examples/*.md
examples/*.pdf
@ -22,15 +21,9 @@ test/**/*.ipynb
doc/build
doc/site
stable/
doc/Manifest.toml
Manifest.toml
tmp/
.idea
*.*~
*.aux
*.log
*.out
\#*\#
.juliahistory

View File

@ -1,23 +1,9 @@
language: julia
julia:
- 1 # current stable
- 1.0 # lts
- nightly
script:
- if [[ -a .git/shallow ]]; then git fetch --unshallow; fi
- julia --check-bounds=yes -e 'using Pkg; Pkg.build()'
- xvfb-run julia -e 'using Pkg; Pkg.test("Weave", coverage=true)'
after_success:
- julia -e 'using Pkg; cd(Pkg.dir("Weave")); Pkg.add("Coverage"); using Coverage; Coveralls.submit(Coveralls.process_folder())'
jobs:
allow_failures:
- julia: nightly
include:
- stage: "Documentation"
julia: 1
julia: 1.5
os: linux
script:
- julia --project=doc/ -e 'using Pkg; Pkg.develop(PackageSpec(path=pwd())); Pkg.instantiate()'

15
NEWS.md
View File

@ -1,6 +1,19 @@
## Release notes for Weave.jl
### v0.10 - 2020/05/18
### v0.10.6 2020/10/03
improvements:
- cleaned up chunk rendering (removed unnecessary extra newlines): #401
- `WEAVE_ARGS` now can take arbitrary objects: https://github.com/JunoLab/Weave.jl/commit/c24a2621359b5d0af1bb6825f488e58cc11b8a9e
- improved docs: #397 by @baggepinnen
bug fixes
- fixed #398: #399
- removed unnecessary quote for markdown output: https://github.com/JunoLab/Weave.jl/commit/a1830e05029f33195627ec5dedbacb30af23947e
- fixed #386: #396 by @torfjelde
### v0.10 2020/05/18
improvements:
- `weave` is now integrated with Juno's progress bar; just call `weave` function inside Juno or use `julia-client: weave-to-html(pdf)` command (#331)

View File

@ -1,6 +1,6 @@
name = "Weave"
uuid = "44d3d7a6-8a23-5bf8-98c5-b353f8df5ec9"
version = "0.10.2"
version = "0.10.12"
[deps]
Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"
@ -12,27 +12,26 @@ Mustache = "ffc61752-8dc7-55ee-8c37-f3e9cdd09e70"
Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7"
REPL = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb"
RelocatableFolders = "05181044-ff0b-4ac5-8273-598c1e38db00"
Requires = "ae029012-a4dd-5104-9daa-d747884805df"
Serialization = "9e88b42a-f829-5b0c-bbe9-9e923198166b"
YAML = "ddb6d928-2868-570f-bddf-ab3f9cf99eb6"
[compat]
Highlights = "0.3.1, 0.4"
Highlights = "0.3.1, 0.4, 0.5"
JSON = "0.21"
Mustache = "0.4.1, 0.5, 1"
Plots = "0.28, 0.29, 1.0"
RelocatableFolders = "0.1,0.2,0.3,1"
Requires = "1.0"
YAML = "0.3, 0.4"
julia = "1"
julia = "1.2"
[extras]
Cairo = "159f3aea-2a34-519c-b102-8c37f9878175"
Conda = "8f4d0f93-b110-5947-807f-2305c1781a2d"
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
Gadfly = "c91e804a-d5a3-530f-b6f0-dfbca275c004"
IJulia = "7073ff75-c697-5162-941a-fcdaad2a7d2a"
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
[targets]
test = ["Cairo", "Conda", "DataFrames", "Gadfly", "IJulia", "Plots", "Test"]
test = ["DataFrames", "Test"]

View File

@ -1,12 +1,12 @@
# Weave
[![Build Status](https://travis-ci.org/JunoLab/Weave.jl.svg?branch=master)](https://travis-ci.org/JunoLab/Weave.jl)
![CI](https://github.com/JunoLab/Weave.jl/workflows/CI/badge.svg)
[![codecov](https://codecov.io/gh/JunoLab/Weave.jl/branch/master/graph/badge.svg)](https://codecov.io/gh/JunoLab/Weave.jl)
[![](https://img.shields.io/badge/docs-stable-blue.svg)](http://weavejl.mpastell.com/stable/)
[![](https://img.shields.io/badge/docs-dev-blue.svg)](http://weavejl.mpastell.com/dev/)
[![](http://joss.theoj.org/papers/10.21105/joss.00204/status.svg)](http://dx.doi.org/10.21105/joss.00204)
Weave is a scientific report generator/literate programming tool
for Julia.
Weave is a scientific report generator/literate programming tool for the [Julia programming language](https://julialang.org/).
It resembles
[Pweave](http://mpastell.com/pweave),
[knitr](https://yihui.org/knitr/),
@ -97,3 +97,8 @@ Thanks for the important additions, fixes and comments.
- [DiffEqTutorials.jl](https://github.com/JuliaDiffEq/DiffEqTutorials.jl) uses Weave to output tutorials (`.jmd` documents) to html, pdf and Jupyter notebooks.
- [TuringTutorials](https://github.com/TuringLang/TuringTutorials) uses Weave to convert notebooks to html.
## Related packages
- [Literate.jl](https://github.com/fredrikekre/Literate.jl) can be used to generate Markdown and Jupyter notebooks directly from Julia source files with markdown in comments.
- [Quarto](https://quarto.org) can generate Jupyter notebooks, HTML, or PDF directly from a Markdown format containing Julia code blocks, and also works with R and Python.

View File

@ -14,8 +14,8 @@ makedocs(
"getting_started.md",
"usage.md",
"publish.md",
"header.md",
"chunk_options.md",
"header.md",
"notebooks.md",
"function_index.md",
],

View File

@ -1,43 +1,66 @@
# Chunk Options
# [Chunk Options](@id chunk-options)
I've mostly followed [Knitr](http://yihui.name/knitr/options)'s naming for chunk options, but not all options are implemented.
Options are separated using ";" and need to be valid Julia expressions. Example: markdown code chunk that saves and displays a 12 cm wide image and hides the source code:
`julia; out_width="12cm"; echo=false`
Weave currently supports the following chunk options with the following defaults:
You can use chunk options to configure how each chunk is evaluated, rendered, etc.
Most of the ideas came from [chunk options in RMarkdown](http://yihui.name/knitr/options).
## Options for Code
## Syntax
Chunk options come after [code chunk](@ref code-chunks) header.
There are two (slightly) different syntax to write them:
- (Julia's toplevel expression) options are separated by semicolon (`;`)
- (RMarkdown style) options are separated by comma (`,`)
Let's take a look at examples. All the following code chunk header are valid,
and so configured to hide the source code from generated output (`echo = false`)
and displays figures with 12cm width (`out_width = "12cm"`):
```md
```julia; echo = false; out_width = "12cm"
```{julia; echo = false; out_width = "12cm"}
```julia, echo = false, out_width = "12cm"
```{julia, echo = false, out_width = "12cm"}
```
## Weave Chunk Options
Weave currently supports the following chunk options:
we've mostly followed [RMarkdown's namings](http://yihui.name/knitr/options), but not all options are implemented.
### Evaluation
- `eval = true`: Evaluate the code chunk. If `false` the chunk wont be executed.
- `error = true`: If `true` [`weave`](@ref) won't stop on errors and rather they will be included in output document. If `false`, [`weave`](@ref) will halt on any of un-caught errors.
- `cache = false`: Cache results, depending on `cache` parameter on [`weave`](@ref) function.
- `tangle = true`: Set tangle to `false` to exclude chunk from tangled code.
### Rendering
- `echo = true`: Echo the code in the output document. If `false` the source code will be hidden.
- `results = "markup"`: The output format of the printed results. `"markup"` for literal block, `"hidden"` for hidden results, or anything else for raw output (I tend to use `"tex"` for Latex and `"rst"` for rest). Raw output is useful if you want to e.g. create tables from code chunks.
- `eval = true`: Evaluate the code chunk. If `false` the chunk wont be executed.
- `term = false`: If `true` the output emulates a REPL session. Otherwise only stdout and figures will be included in output.
- `label = nothing`: Chunk label, will be used for figure labels in Latex as `fig:label`.
- `wrap = true`: Wrap long lines from output.
- `line_width = 75`: Line width for wrapped lines.
- `cache = false`: Cache results, depending on `cache` parameter on `weave` function.
- `hold = false`: Hold all results until the end of the chunk.
- `tangle = true`: Set tangle to `false` to exclude chunk from tangled code.
### Figures
## Options for Figures
- `label = nothing`: Chunk label, will be used for figure labels in Latex as `fig:label`.
- `fig_width = 6`: Figure width passed to plotting library.
- `fig_height = 4`: Figure height passed to plotting library.
- `out_width`: Width of saved figure in output markup e.g. `"50%"`, `"12cm"`, `0.5\linewidth`
- `out_height`: Height of saved figure in output markup
- `dpi = 96`: Resolution of saved figures.
- `fig_cap`: Figure caption.
- `label`: Chunk label, will be used for figure labels in Latex as fig:label
- `fig_ext`: File extension (format) of saved figures.
- `fig_pos = "!h"`: Figure position in Latex, e.g.: `"ht"`.
- `fig_env = "figure"`: Figure environment in Latex.
## Set Default Chunk Options
## Default Chunk Options
You can set the default chunk options (and `weave` arguments) for a document using `weave_options` key in YAML [Header Configuration](@ref).
E.g. to set the default `out_width` of all figures you can use:

View File

@ -39,11 +39,11 @@ Note that `Date` is available since the chunk is evaluated first.
---
title : Header Example
author : Shuhei Kadowaki
date: `j Date(now())`
date: `j import Dates; Dates.Date(Dates.now())`
---
```julia; echo = false
using Datas
using Dates
```
```

View File

@ -30,8 +30,8 @@ Pages = [
"getting_started.md",
"usage.md",
"publish.md",
"header.md",
"chunk_options.md",
"header.md",
"notebooks.md",
"function_index.md",
]

View File

@ -41,8 +41,8 @@ e.g.: `weave("FIR_design_plots.jl", template = "custom.tpl"`.
As starting point, you can use the existing templates:
- HTML (`md2html`): [julia_html.tpl](https://github.com/mpastell/Weave.jl/blob/master/templates/julia_html.tpl)
- LaTex (`md2pdf`): [julia_tex.tpl](https://github.com/mpastell/Weave.jl/blob/master/templates/julia_tex.tpl)
- HTML (`md2html`): [`md2html.tpl`](https://github.com/JunoLab/Weave.jl/blob/master/templates/md2html.tpl)
- LaTex (`md2pdf`): [`md2pdf.tpl`](https://github.com/JunoLab/Weave.jl/blob/master/templates/md2pdf.tpl)
Templates are rendered using [Mustache.jl](https://github.com/jverzani/Mustache.jl).

View File

@ -73,62 +73,69 @@ ext == ".ipynb" && return "notebook"
return "noweb"
```
## Documentation Chunks
### Documentation Chunks
In markdown and Noweb input formats documentation chunks are the parts that aren't inside code delimiters. Documentation chunks can be written with several different markup languages.
## Code Chunks
### Markdown Format
### [Code Chunks](@id code-chunks)
Markdown code chunks are defined using fenced code blocks with options following on the same line. e.g. to hide code from output you can use:
Code chunks are written in different ways in different formats.
```
```julia; echo=false
#### Markdown Format
Weave code chunks are defined using fenced code blocks, same as with [common markdown](https://spec.commonmark.org/0.29/#fenced-code-blocks):
```markdown
```julia
code
...
```
```
[Sample document]( https://github.com/mpastell/Weave.jl/blob/master/examples/FIR_design.jmd)
Weave code chunks can optionally be followed by [chunk options](@ref) on the same line.
E.g. the chunk below will hide code itself from generated output:
```markdown
```julia, echo = false
code
...
```
```
## [Inline Code](@id inline-code)
#### Noweb Format
Code chunks start with a line marked with `<<>>=` or `<<options>>=` and end with line marked with `@`.
The code between the start and end markers is executed and the output is captured to the output document.
### [Inline Code](@id inline-code)
You can also add inline code to your documents using
```
`j juliacode`
```
or
```
! juliacode
```
syntax.
syntax. Using the `j code` syntax you can insert code anywhere in a line and with
the `!` syntax the whole line after `!` will be executed. The code will be replaced
with captured output in the weaved document.
If the code produces figures the filename or base64 encoded string will be
added to output e.g. to include a Plots figure in markdown you can use:
The former syntax allows you to insert code _anywhere_ in a line
while the `!` syntax treats the whole line as code,
and the code will be replaced with captured output in the weaved document.
If the code produces figures, the filename or base64 encoded string will be added to output,
e.g. to include a Plots figure in markdown you can use:
```
![A plot](`j plot(1:10)`)
```
or to produce any html output:
or to produce any HTML output:
```
! display("text/html", "Header from julia");
! display("text/html", HTML("Header from julia"));
```
### Noweb Format
Code chunks start with a line marked with `<<>>=` or `<<options>>=` and end with line marked with `@`. The code between the start and end markers is executed and the output is captured to the output document. See [chunk options](../chunk_options/).
### Script Format
Weave also support script input format with a markup in comments.
Weave also supports script input format with a markup in comments.
These scripts can be executed normally using Julia or published with Weave.
Lines starting with `#'`, `#%%` or `# %%` are treated as document.
@ -143,7 +150,11 @@ hoge # some code comes here
The format is identical to [Pweave](http://mpastell.com/pweave/pypublish.html) and the concept is similar to publishing documents with MATLAB or using Knitr's [spin](http://yihui.name/knitr/demo/stitch/).
Weave will remove the first empty space from each line of documentation.
[See sample document:](https://github.com/mpastell/Weave.jl/blob/master/examples/FIR_design.jl)
!!! tip
- Here are sample documents:
+ [markdown format](https://github.com/JunoLab/Weave.jl/blob/master/examples/FIR_design.jmd)
+ [script format](https://github.com/JunoLab/Weave.jl/blob/master/examples/FIR_design.jl)
- [Details about chunk options](@ref chunk-options)
## Configuration via YAML Header
@ -154,29 +165,12 @@ See [Header Configuration](@ref) section for more details.
## Passing Runtime Arguments to Documents
You can pass arguments as `Dict` to the weaved document using the `args` argument
to `weave`. The arguments will be available as `WEAVE_ARGS` variable in the document.
You can pass arbitrary object to the weaved document using [`weave`](@ref)'s optional argument `args`.
It will be available as `WEAVE_ARGS` variable in the `weave`d document.
This makes it possible to create the same report easily for e.g. different
date ranges of input data from a database or from files with similar format giving the
filename as input.
This makes it possible to create the same report easily for e.g. different date ranges of input data from a database or from files with similar format giving the filename as input.
In order to pass a filename to a document you need call `weave` using:
```julia
weave("mydoc.jmd", args = Dict("filename" => "somedata.h5"))
```
and you can access the filename from document as follows:
```
```julia
print(WEAVE_ARGS["filename"])
```
```
You can use the `out_path` argument to control the name of the
output document.
E.g. if you call `weave("weavefile.jmd", args = (datalocation = "somedata.h5",))`, and then you can retrieve the `datalocation` in `weavefile.jmd` as follows: `WEAVE_ARGS.datalocation`
## `include_weave`

View File

@ -7,7 +7,7 @@
#' # Introduction
#' This an example of a julia script that can be published using
#' [Weave](http://mpastell.github.io/Weave.jl/latest/usage/).
#' [Weave](http://weavejl.mpastell.com/dev/usage/).
#' The script can be executed normally using Julia
#' or published to HTML or pdf with Weave.
#' Text is written in markdown in lines starting with "`#'` " and code

View File

@ -9,7 +9,7 @@ date: 21th April 2016
This an example of a julia script that can be published using
[Weave](http://mpastell.github.io/Weave.jl/latest/usage/).
[Weave](http://weavejl.mpastell.com/dev/usage/).
The script can be executed normally using Julia
or published to HTML or pdf with Weave.
Text is written in markdown in lines starting with "`#'` " and code

View File

@ -7,7 +7,7 @@
#' # Introduction
#' This an example of a julia script that can be published using
#' [Weave](http://mpastell.github.io/Weave.jl/latest/usage/).
#' [Weave](http://weavejl.mpastell.com/dev/usage/).
#' The script can be executed normally using Julia
#' or published to HTML or pdf with Weave.
#' Text is written in markdown in lines starting with "`#'` " and code

View File

@ -7,7 +7,7 @@ date : 13th December 2016
# Intro
This a sample [Julia](http://julialang.org/) markdown document that can
be executed using [Weave.jl](https://github.com/mpastell/Weave.jl).
be executed using [Weave.jl](https://github.com/JunoLab/Weave.jl).
The code is delimited from docs using markdown fenced code blocks
markup which can be seen looking at the source document
@ -71,6 +71,6 @@ plot(y = cumsum(randn(1000, 1)), Geom.line)
Read the documentation:
- stable: [http://mpastell.github.io/Weave.jl/stable/](http://mpastell.github.io/Weave.jl/stable/)
- latest: [http://mpastell.github.io/Weave.jl/latest/](http://mpastell.github.io/Weave.jl/latest/)
- latest: [http://weavejl.mpastell.com/dev/](http://weavejl.mpastell.com/dev/)
See other examples in the [GitHub repo](https://github.com/mpastell/Weave.jl/tree/master/examples)
See other examples in the [GitHub repo](https://github.com/JunoLab/Weave.jl/tree/master/examples)

View File

@ -29,10 +29,10 @@
\section{Intro}
This is a minimal example on using PGF format with Gadfly plots in
\href{https://github.com/mpastell/Weave.jl}{Weave.jl} document.
\href{https://github.com/JunoLab/Weave.jl}{Weave.jl} document.
The source is in github:
\url{https://github.com/mpastell/Weave.jl/blob/master/examples/gadfly_pgf.texw}.
\url{https://github.com/JunoLab/Weave.jl/blob/master/examples/gadfly_pgf.texw}.
You can run this example with first weaving it from Julia using:

View File

@ -5,7 +5,7 @@
# Introduction
This a sample [Julia](http://julialang.org/) noweb document that can
be executed using [Weave.jl](https://github.com/mpastell/Weave.jl).
be executed using [Weave.jl](https://github.com/JunoLab/Weave.jl).
The code is delimited from docs using `<<>>=` and `@` markup which can be seen
looking at the source document `gadfly_sample.mdw` in the examples directory
@ -65,6 +65,6 @@ plot(y = cumsum(randn(1000, 1)), Geom.line)
Read the documentation:
- stable: <http://mpastell.github.io/Weave.jl/stable/>
- latest: <http://mpastell.github.io/Weave.jl/latest/>
- latest: <http://weavejl.mpastell.com/dev/>
See other examples in: <https://github.com/mpastell/Weave.jl/tree/master/examples>
See other examples in: <https://github.com/JunoLab/Weave.jl/tree/master/examples>

View File

@ -1,38 +1,57 @@
module Weave
using Highlights, Mustache, Requires
using Highlights, Mustache, Requires, Pkg, REPL, RelocatableFolders, Base64
# directories
const PKG_DIR = normpath(@__DIR__, "..")
const TEMPLATE_DIR = normpath(PKG_DIR, "templates")
const TEMPLATE_DIR = @path joinpath(PKG_DIR, "templates")
const STYLESHEET_DIR = @path joinpath(PKG_DIR, "stylesheets")
# keeps paths of sample documents for easy try
const EXAMPLE_FOLDER = @path joinpath(PKG_DIR, "examples")
# constant names
const WEAVE_OPTION_NAME = "weave_options"
const WEAVE_OPTION_NAME_DEPRECATED = "options" # remove this when tagging v0.11
const WEAVE_OPTION_DEPRECATE_ID = "weave_option_duplicate_id"
const DEFAULT_FIG_PATH = "figures"
# keeps paths of sample documents for easy try
const EXAMPLE_FOLDER = normpath(PKG_DIR, "examples")
const WEAVE_VERSION = try
'v' * Pkg.TOML.parsefile(normpath(PKG_DIR, "Project.toml"))["version"]
catch
""
end
weave_info() = WEAVE_VERSION, string(Date(now()))
function __init__()
@require Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" include("plots.jl")
@require Gadfly = "c91e804a-d5a3-530f-b6f0-dfbca275c004" include("gadfly.jl")
end
@static @isdefined(isnothing) || begin
isnothing(::Any) = false
isnothing(::Nothing) = true
end
# utilitity functions
take2string!(io) = String(take!(io))
joinlines(lines) = join(lines, '\n')
include("types.jl")
include("config.jl")
include("WeaveMarkdown/markdown.jl")
include("display_methods.jl")
include("reader/reader.jl")
include("run.jl")
include("cache.jl")
include("rendering/rendering.jl")
include("writer/writer.jl")
include("converter.jl")
get_format(doctype::AbstractString) = FORMATS[doctype]
"""
list_out_formats()
List supported output formats
List supported output formats with its description.
"""
function list_out_formats()
for format in keys(formats)
println(string(format, ": ", formats[format].description))
end
end
list_out_formats() = [k => v.description for (k,v) in FORMATS]
"""
tangle(source::AbstractString; kwargs...)
@ -55,9 +74,9 @@ function tangle(
doc = WeaveDoc(source, informat)
doc.cwd = get_cwd(doc, out_path)
outname = get_outname(out_path, doc, ext = "jl")
out_path = get_out_path(doc, out_path, "jl")
open(outname, "w") do io
open(out_path, "w") do io
for chunk in doc.chunks
if typeof(chunk) == CodeChunk
options = merge(doc.chunk_defaults, chunk.options)
@ -65,8 +84,8 @@ function tangle(
end
end
end
doc.cwd == pwd() && (outname = basename(outname))
@info("Writing to file $outname")
@info "Tangled to $(out_path)"
end
"""
@ -82,9 +101,9 @@ Weave an input document to output file.
* `:doc`: Path of the source document (default)
* `:pwd`: Julia working directory
* `"somepath"`: `String` of output directory e.g. `"~/outdir"`, or of filename e.g. `"~/outdir/outfile.tex"`
- `args::Dict = Dict()`: Arguments to be passed to the weaved document; will be available as `WEAVE_ARGS` in the document
- `args::Any = Dict()`: A runtime object that is available as `WEAVE_ARGS` while `weave`ing
- `mod::Union{Module,Nothing} = nothing`: Module where Weave `eval`s code. You can pass a `Module` object, otherwise create an new sandbox module.
- `fig_path::AbstractString = "figures"`: Where figures will be generated, relative to `out_path`
- `fig_path::Union{Nothing,AbstractString} = nothing`: Where figures will be generated, relative to `out_path`. By default (i.e. given `nothing`), Weave will automatically create `$(DEFAULT_FIG_PATH)` directory.
- `fig_ext::Union{Nothing,AbstractString} = nothing`: Extension for saved figures e.g. `".pdf"`, `".png"`. Default setting depends on `doctype`
- `cache_path::AbstractString = "cache"`: Where of cached output will be saved
- `cache::Symbol = :off`: Controls caching of code:
@ -92,12 +111,11 @@ Weave an input document to output file.
* `:all` caches everything
* `:user` caches based on chunk options
* `:refresh` runs all code chunks and save new cache
- `throw_errors::Bool = false`: If `false` errors are included in output document and the whole document is executed. If `true` errors are thrown when they occur
- `template::Union{Nothing,AbstractString,Mustache.MustacheTokens} = nothing`: Template (file path) or `Mustache.MustacheTokens`s for `md2html` or `md2tex` formats
- `css::Union{Nothing,AbstractString} = nothing`: Path of a CSS file used for md2html format
- `highlight_theme::Union{Nothing,Type{<:Highlights.AbstractTheme}} = nothing`: Theme used for syntax highlighting (defaults to `Highlights.Themes.DefaultTheme`)
- `pandoc_options::Vector{<:AbstractString} = String[]`: `String`s of options to pass to pandoc for `pandoc2html` and `pandoc2pdf` formats, e.g. `["--toc", "-N"]`
- `latex_cmd::AbstractString = "xelatex"`: The command used to make PDF file from .tex
- `pandoc_options::Vector{<:AbstractString} = $(DEFAULT_PANDOC_OPTIONS)`: `String`s of options to pass to pandoc for `pandoc2html` and `pandoc2pdf` formats, e.g. `["--toc", "-N"]`
- `latex_cmd::Vector{<:AbstractString} = $(DEFAULT_LATEX_CMD)`: The command used to make PDF file from .tex
- `keep_unicode::Bool = false`: If `true`, do not convert unicode characters to their respective latex representation. This is especially useful if a font and tex-engine with support for unicode characters are used
!!! note
@ -108,18 +126,17 @@ function weave(
doctype::Union{Nothing,AbstractString} = nothing,
informat::Union{Nothing,AbstractString} = nothing,
out_path::Union{Symbol,AbstractString} = :doc,
args::Dict = Dict(),
args::Any = Dict(),
mod::Union{Module,Nothing} = nothing,
fig_path::AbstractString = "figures",
fig_path::Union{Nothing,AbstractString} = nothing,
fig_ext::Union{Nothing,AbstractString} = nothing,
cache_path::AbstractString = "cache",
cache::Symbol = :off,
throw_errors::Bool = false,
template::Union{Nothing,AbstractString,Mustache.MustacheTokens} = nothing,
css::Union{Nothing,AbstractString} = nothing,
css::Union{Nothing,AbstractString} = nothing, # TODO: rename to `stylesheet`
highlight_theme::Union{Nothing,Type{<:Highlights.AbstractTheme}} = nothing,
pandoc_options::Vector{<:AbstractString} = String[],
latex_cmd::AbstractString = "xelatex",
pandoc_options::Vector{<:AbstractString} = DEFAULT_PANDOC_OPTIONS,
latex_cmd::Vector{<:AbstractString} = DEFAULT_LATEX_CMD,
keep_unicode::Bool = false,
)
doc = WeaveDoc(source, informat)
@ -154,7 +171,6 @@ function weave(
fig_ext = get(weave_options, "fig_ext", fig_ext)
cache_path = get(weave_options, "cache_path", cache_path)
cache = Symbol(get(weave_options, "cache", cache))
throw_errors = get(weave_options, "throw_errors", throw_errors)
end
doc = run_doc(
@ -167,69 +183,57 @@ function weave(
fig_ext = fig_ext,
cache_path = cache_path,
cache = cache,
throw_errors = throw_errors,
)
# format document
# ---------------
# overwrites options with those specified in header, that are needed for formatting document
# overwrites options with those specified in header, that are needed for rendering/writing document
# NOTE: these YAML options can be given dynamically
if !isnothing(weave_options)
if haskey(weave_options, "template")
template = weave_options["template"]
# resolve relative to this document
# resolve relative to this document
template isa AbstractString && (template = normpath(dirname(source), template))
end
if haskey(weave_options, "css")
css = weave_options["css"]
# resolve relative to this document
# resolve relative to this document
css isa AbstractString && (css = normpath(dirname(source), css))
end
highlight_theme = get(weave_options, "highlight_theme", highlight_theme)
pandoc_options = get(weave_options, "pandoc_options", pandoc_options)
latex_cmd = get(weave_options, "latex_cmd", latex_cmd)
keep_unicode = get(weave_options, "keep_unicode", keep_unicode)
latex_cmd = get(weave_options, "latex_cmd", latex_cmd)
pandoc_options = get(weave_options, "pandoc_options", pandoc_options)
end
isnothing(template) || (doc.template = template)
isnothing(highlight_theme) || (doc.highlight_theme = highlight_theme)
# isnothing(theme) || (doc.theme = theme) # Reserved for themes
isnothing(css) || (doc.css = css)
get!(doc.format.formatdict, :keep_unicode, keep_unicode)
formatted = format(doc)
set_format_options!(
doc;
# general
template = template,
highlight_theme = highlight_theme,
css = css,
# pandoc
pandoc_options = pandoc_options,
# latex
keep_unicode = keep_unicode,
latex_cmd = latex_cmd,
)
outname = get_outname(out_path, doc)
# render document
# ---------------
rendered = render_doc(doc)
open(io->write(io,formatted), outname, "w")
# write documents
# ---------------
out_path = write_doc(doc, rendered, get_out_path(doc, out_path))
# document generation via external programs
doctype = doc.doctype
if doctype == "pandoc2html"
mdname = outname
outname = get_outname(out_path, doc, ext = "html")
pandoc2html(formatted, doc, outname, pandoc_options)
rm(mdname)
elseif doctype == "pandoc2pdf"
mdname = outname
outname = get_outname(out_path, doc, ext = "pdf")
pandoc2pdf(formatted, doc, outname, pandoc_options)
rm(mdname)
elseif doctype == "md2pdf"
run_latex(doc, outname, latex_cmd)
outname = get_outname(out_path, doc, ext = "pdf")
end
doc.cwd == pwd() && (outname = basename(outname))
@info "Report weaved to $outname"
return abspath(outname)
@info "Weaved to $(out_path)"
return out_path
end
weave(doc::AbstractString, doctype::Union{Symbol,AbstractString}; kwargs...) =
weave(doc; doctype = doctype, kwargs...)
function specific_options!(weave_options, doctype)
fmts = keys(formats)
fmts = keys(FORMATS)
for (k,v) in weave_options
if k in fmts
k == doctype && merge!(weave_options, v)
@ -238,6 +242,17 @@ function specific_options!(weave_options, doctype)
end
end
get_out_path(doc, out_path, ext::Nothing = nothing) = get_out_path(doc, out_path, doc.format.extension)
function get_out_path(doc, out_path, ext)
if (out_path === :doc) || (out_path === :pwd)
abspath(get_cwd(doc, out_path), string(doc.basename, '.', ext))
elseif isempty(splitext(out_path)[2]) # directory given
abspath(get_cwd(doc, out_path), string(doc.basename, '.', ext))
else
# out_path is given, but if extension is explitly provided override this will override the extension
abspath(string(splitext(out_path)[1], '.', ext))
end
end
"""
notebook(source::AbstractString; kwargs...)
@ -257,7 +272,7 @@ using [`nbconvert`](https://nbconvert.readthedocs.io/en/latest/).
!!! warning
The code is _**not**_ executed by Weave, but by [`nbconvert`](https://nbconvert.readthedocs.io/en/latest/).
This means that the output doesn't necessarily always work properly; see [#116](https://github.com/mpastell/Weave.jl/issues/116).
This means that the output doesn't necessarily always work properly; see [#116](https://github.com/JunoLab/Weave.jl/issues/116).
!!! note
In order to _just_ convert Weave document to Jupyter Notebook,
@ -273,15 +288,13 @@ function notebook(
doc = WeaveDoc(source)
converted = convert_to_notebook(doc)
doc.cwd = get_cwd(doc, out_path)
outfile = get_outname(out_path, doc, ext = "ipynb")
out_path = get_out_path(doc, out_path, "ipynb")
open(outfile, "w") do f
write(f, converted)
end
write(out_path, converted)
@info "Running nbconvert"
@info "Running nbconvert ..."
return read(
`$jupyter_path nbconvert --ExecutePreprocessor.timeout=$timeout --to notebook --execute $outfile $nbconvert_options --output $outfile`,
`$jupyter_path nbconvert --ExecutePreprocessor.timeout=$timeout --to notebook --execute $(out_path) $nbconvert_options --output $(out_path)`,
String,
)
end
@ -300,7 +313,7 @@ function include_weave(
)
old_path = pwd()
doc = WeaveDoc(source, informat)
cd(doc.path)
cd(dirname(doc.path))
try
code = join(
[x.content for x in filter(x -> isa(x, Weave.CodeChunk), doc.chunks)],
@ -317,29 +330,6 @@ end
include_weave(source, informat = nothing) = include_weave(Main, source, informat)
# Hooks to run before and after chunks, this is form IJulia,
# but note that Weave hooks take the chunk as input
const preexecute_hooks = Function[]
push_preexecute_hook(f::Function) = push!(preexecute_hooks, f)
pop_preexecute_hook(f::Function) =
splice!(preexecute_hooks, findfirst(x -> x == f, preexecute_hooks))
const postexecute_hooks = Function[]
push_postexecute_hook(f::Function) = push!(postexecute_hooks, f)
pop_postexecute_hook(f::Function) =
splice!(postexecute_hooks, findfirst(x -> x == f, postexecute_hooks))
include("types.jl")
include("config.jl")
include("WeaveMarkdown/markdown.jl")
include("display_methods.jl")
include("reader/reader.jl")
include("run.jl")
include("cache.jl")
include("formatters.jl")
include("format.jl")
include("pandoc.jl")
include("converter.jl")
export weave,
list_out_formats,

View File

@ -1,5 +1,5 @@
# module Markdown2HTML
# Markdown to HTML writer, Modified from Julia Base.Markdown html writer
using Markdown:
MD,
Header,
@ -19,13 +19,10 @@ using Markdown:
LaTeX,
isordered
function tohtml(io::IO, m::MIME"text/html", x)
show(io, m, x)
end
function tohtml(io::IO, m::MIME"text/plain", x)
htmlesc(io, sprint(show, m, x))
end
tohtml(io::IO, m::MIME"text/html", x) = show(io, m, x)
tohtml(io::IO, m::MIME"text/plain", x) = htmlesc(io, sprint(show, m, x))
function tohtml(io::IO, m::MIME"image/png", img)
print(io, """<img src="data:image/png;base64,""")
@ -33,9 +30,7 @@ function tohtml(io::IO, m::MIME"image/png", img)
print(io, "\" />")
end
function tohtml(m::MIME"image/svg+xml", img)
show(io, m, img)
end
tohtml(m::MIME"image/svg+xml", img) = show(io, m, img)
# AbstractDisplay infrastructure
@ -168,9 +163,7 @@ function html(io::IO, md::List)
end
end
function html(io::IO, md::HorizontalRule)
tag(io, :hr)
end
html(io::IO, md::HorizontalRule) = tag(io, :hr)
function html(io::IO, tex::LaTeX)
withtag(io, :p, :class => "math") do
@ -178,9 +171,7 @@ function html(io::IO, tex::LaTeX)
end
end
function html(io::IO, comment::Comment)
write(io, "\n<!-- $(comment.text) -->\n")
end
html(io::IO, comment::Comment) = write(io, "\n<!-- $(comment.text) -->\n")
function html(io::IO, md::Table)
withtag(io, :table) do
@ -218,9 +209,7 @@ function htmlinline(io::IO, tex::LaTeX)
end
end
function htmlinline(io::IO, md::Union{Symbol,AbstractString})
htmlesc(io, md)
end
htmlinline(io::IO, md::Union{Symbol,AbstractString}) = htmlesc(io, md)
function htmlinline(io::IO, md::Bold)
withtag(io, :strong) do
@ -234,9 +223,7 @@ function htmlinline(io::IO, md::Italic)
end
end
function htmlinline(io::IO, md::Image)
tag(io, :img, :src => md.url, :alt => md.alt)
end
htmlinline(io::IO, md::Image) = tag(io, :img, :src => md.url, :alt => md.alt)
function htmlinline(io::IO, f::Footnote)
withtag(io, :a, :href => "#footnote-$(f.id)", :class => "footnote") do
@ -250,18 +237,12 @@ function htmlinline(io::IO, link::Link)
end
end
function htmlinline(io::IO, br::LineBreak)
tag(io, :br)
end
htmlinline(io::IO, br::LineBreak) = tag(io, :br)
function htmlinline(io::IO, comment::Comment)
write(io, "<!-- $(comment.text) -->")
end
htmlinline(io::IO, comment::Comment) = write(io, "<!-- $(comment.text) -->")
htmlinline(io::IO, x) = tohtml(io, x)
# API
html(md) = sprint(html, md)
# end

View File

@ -1,12 +1,9 @@
import Markdown: latex, latexinline
# Remove comments that can occur inside a line
function latexinline(io, comment::WeaveMarkdown.Comment)
write(io, "")
end
function latex(io::IO, comment::WeaveMarkdown.Comment)
function latex(io::IO, comment::Comment)
for line in split(comment.text, r"\r\n|\n")
write(io, "% $line\n")
end
end
latexinline(io, comment::Comment) = write(io, "")

View File

@ -1,24 +1,21 @@
# This module extends the julia markdown parser to improve compatibility with Jupyter, Pandoc etc.
module WeaveMarkdown
using ..Weave: isnothing, take2string!
using Markdown
import Markdown: @trigger, @breaking, Code, MD, withstream, startswith, LaTeX
function __init__()
# NOTE:
# overwriting `Markdown.latex` function should be done here in order to allow
# incremental precompilations
Markdown.eval(
quote
function latex(io::IO, tex::Markdown.LaTeX)
math_envs = ["align", "equation", "eqnarray"]
use_dollars =
!any([occursin("\\begin{$me", tex.formula) for me in math_envs])
use_dollars && write(io, "\\[")
write(io, string("\n", tex.formula, "\n"))
use_dollars && write(io, "\\]\n")
end
end,
)
# HACK: that this definition is type-piracy. It is required since `Markdown`
# does not have a built in system for contextual rendering by users. `io` here
# should always be either `IOBuffer` or `IOContext` since it is reached via
# `sprint` in all user-facing code paths in `Markdown`.
function Markdown.latex(io::Union{IOBuffer,IOContext}, tex::Markdown.LaTeX)
math_envs = ["align", "equation", "eqnarray"]
use_dollars =
!any([occursin("\\begin{$me", tex.formula) for me in math_envs])
use_dollars && write(io, "\\[")
write(io, string("\n", tex.formula, "\n"))
use_dollars && write(io, "\\]\n")
end
mutable struct Comment
@ -37,7 +34,7 @@ end
if !isempty(estr)
estr = Markdown.startswith(stream, r"^\$\$$"m)
if isempty(estr)
push!(block, LaTeX(String(take!(buffer)) |> chomp))
push!(block, LaTeX(take2string!(buffer) |> chomp))
end
return true
else
@ -58,7 +55,7 @@ end
line = readline(stream, keep = true)
write(buffer, line)
if occursin(r"-->$", line)
s = replace(String(take!(buffer)) |> chomp, r"-->$" => "")
s = replace(take2string!(buffer) |> chomp, r"-->$" => "")
push!(block, Comment(s))
return true
end
@ -71,7 +68,7 @@ end
withstream(stream) do
Markdown.startswith(stream, "<!--") || return
text = Markdown.readuntil(stream, "-->")
text nothing && return
isnothing(text) && return
return Comment(text)
end
end
@ -88,6 +85,8 @@ for key in keys(Markdown.julia.inner)
end
end
include("html.jl")
include("latex.jl")
end
end # module

View File

@ -29,7 +29,6 @@ function restore_chunk(chunk::CodeChunk, cached)
new_chunks = []
for c in chunks
newc = CodeChunk(c.content, c.number, c.start_line, c.optionstring, c.options)
newc.result_no = c.result_no
newc.figures = c.figures
newc.result = c.result
newc.output = c.output

View File

@ -1,64 +1,58 @@
# Default options
const defaultParams = Dict{Symbol,Any}(
:storeresults => false,
:chunk_defaults => Dict{Symbol,Any}(
:echo => true,
:results => "markup",
:hold => false,
:fig => true,
:include => true,
:eval => true,
:tangle => true,
:cache => false,
:fig_cap => nothing,
# Size in inches
:fig_width => 6,
:fig_height => 4,
:fig_path => "figures",
:dpi => 96,
:term => false,
:display => false,
:prompt => "\njulia> ",
:label => nothing,
:wrap => true,
:line_width => 75,
:engine => "julia",
# :option_AbstractString=> "",
# Defined in formats
:fig_ext => nothing,
:fig_pos => nothing,
:fig_env => nothing,
:out_width => nothing,
:out_height => nothing,
:skip => false,
),
# TODO: follow RMarkdown convention more
const _DEFAULT_PARAMS = Dict{Symbol,Any}(
:echo => true,
:results => "markup",
:hold => false,
:fig => true,
:eval => true,
:error => true,
:tangle => true,
:cache => false,
:fig_cap => nothing,
# NOTE: size in inches
:fig_width => 6,
:fig_height => 4,
:fig_path => DEFAULT_FIG_PATH,
:dpi => 96,
:term => false,
:prompt => "julia>",
:label => nothing,
:wrap => true,
:line_width => 75,
:fig_ext => nothing,
:fig_pos => nothing,
:fig_env => nothing,
:out_width => nothing,
:out_height => nothing,
)
# This one can be changed at runtime, initially a copy of defaults
const rcParams = deepcopy(defaultParams)
const DEFAULT_PARAMS = deepcopy(_DEFAULT_PARAMS) # might be changed at runtime
"""
set_chunk_defaults!(opts::Dict{Symbol, Any})
set_chunk_defaults!(k, v)
set_chunk_defaults!(kv::Pair...)
set_chunk_defaults!(opts::AbstractDict)
Set default options for code chunks, use [`get_chunk_defaults`](@ref) to see the current values.
E.g.: set default `dpi` to `200` and `fig_width` to `8`
```julia
julia> set_chunk_defaults!(Dict(:dpi => 200, :fig_width => 8))
```
E.g.: all the three examples below will set default `dpi` to `200` and `fig_width` to `8`:
- `set_chunk_defaults!(:dpi, 200); set_chunk_defaults!(:fig_width, 8)`
- `set_chunk_defaults!(:dpi => 200, :fig_width => 8)`
- `set_chunk_defaults!(Dict(:dpi => 200, :fig_width => 8))`
"""
set_chunk_defaults!(opts::Dict{Symbol,Any}) = merge!(rcParams[:chunk_defaults], opts)
set_chunk_defaults!(k, v) = DEFAULT_PARAMS[k]= v
set_chunk_defaults!(kv::Pair...) = for (k,v) in kv; set_chunk_defaults!(k, v); end
set_chunk_defaults!(opts::AbstractDict) = merge!(DEFAULT_PARAMS, opts)
"""
get_chunk_defaults()
Get default options used for code chunks.
"""
get_chunk_defaults() = rcParams[:chunk_defaults]
get_chunk_defaults() = DEFAULT_PARAMS
"""
restore_chunk_defaults!()
Restore Weave.jl default chunk options.
"""
restore_chunk_defaults!() = rcParams[:chunk_defaults] = defaultParams[:chunk_defaults]
restore_chunk_defaults!() = for (k,v) in _DEFAULT_PARAMS; DEFAULT_PARAMS[k] = v; end

View File

@ -102,8 +102,6 @@ function convert_to_notebook(doc)
"source" => [strip(join([repr(c) for c in chunk.content], ""))],
),
)
elseif haskey(chunk.options, :skip) && chunk.options[:skip] == "notebook"
continue
else
push!(
cells,

View File

@ -2,40 +2,20 @@ using Markdown, .WeaveMarkdown
# Contains report global properties
mutable struct Report <: AbstractDisplay
cwd::AbstractString
basename::AbstractString
formatdict::Dict{Symbol,Any}
pending_code::AbstractString
cur_result::AbstractString
rich_output::AbstractString
cwd::String
basename::String
format::WeaveFormat
rich_output::String
fignum::Int
figures::Array{AbstractString}
term_state::Symbol
cur_chunk::Any
mimetypes::Array{AbstractString}
figures::Vector{String}
cur_chunk::Union{Nothing,CodeChunk}
mimetypes::Vector{String}
first_plot::Bool
header_script::String
throw_errors::Bool
end
function Report(cwd, basename, formatdict, mimetypes, throw_errors)
Report(
cwd,
basename,
formatdict,
"",
"",
"",
1,
AbstractString[],
:text,
nothing,
mimetypes,
true,
"",
throw_errors,
)
end
Report(cwd, basename, format, mimetypes) =
Report(cwd, basename, format, "", 1, String[], nothing, mimetypes, true, "")
# Default mimetypes in order, can be overridden for some inside `run method` formats
const default_mime_types = ["image/svg+xml", "image/png", "text/html", "text/plain"]
@ -111,7 +91,7 @@ end
function Base.display(report::Report, m::MIME"text/html", data)
io = IOBuffer()
show(IOContext(io, :limit => true), m, data)
report.rich_output *= "\n" * String(take!(io))
report.rich_output *= string('\n', take2string!(io))
end
# Catch "rich_output"
@ -131,7 +111,7 @@ end
function Base.display(report::Report, m::MIME"text/latex", data)
s = repr(m, data)
report.rich_output *= "\n" * s
report.rich_output *= string('\n', s)
end
"""Add saved figure name to results and return the name"""

View File

@ -1,407 +0,0 @@
using Mustache, Highlights, .WeaveMarkdown, Markdown, Dates, Pkg
using REPL.REPLCompletions: latex_symbols
function format(doc)
format = doc.format
# Complete format dictionaries with defaults
formatdict = format.formatdict
get!(formatdict, :termstart, formatdict[:codestart])
get!(formatdict, :termend, formatdict[:codeend])
get!(formatdict, :out_width, nothing)
get!(formatdict, :out_height, nothing)
get!(formatdict, :fig_pos, nothing)
get!(formatdict, :fig_env, nothing)
formatdict[:cwd] = doc.cwd # pass wd to figure formatters
formatdict[:theme] = doc.highlight_theme
restore_header!(doc)
formatted = String[]
for chunk in copy(doc.chunks)
result = format_chunk(chunk, formatdict, format)
push!(formatted, result)
end
formatted = join(formatted, "\n")
# Render using a template if needed
return render_doc(formatted, doc)
end
render_doc(formatted, doc) = render_doc(formatted, doc, doc.format)
render_doc(formatted, doc, format) = formatted
function render_doc(formatted, doc, format::JMarkdown2HTML)
template = if isa(doc.template, Mustache.MustacheTokens)
doc.template
else
template_path = isempty(doc.template) ? normpath(TEMPLATE_DIR, "julia_html.tpl") : doc.template
Mustache.template_from_file(template_path)
end
themepath = isempty(doc.css) ? normpath(TEMPLATE_DIR, "skeleton_css.css") : doc.css
themecss = read(themepath, String)
highlightcss = stylesheet(MIME("text/html"), doc.highlight_theme)
_, source = splitdir(abspath(doc.source))
wversion, wdate = weave_info()
return Mustache.render(
template;
body = formatted,
themecss = themecss,
highlightcss = highlightcss,
header_script = doc.header_script,
source = source,
wversion = wversion,
wdate = wdate,
[Pair(Symbol(k), v) for (k, v) in doc.header]...,
)
end
function render_doc(formatted, doc, format::JMarkdown2tex)
template = if isa(doc.template, Mustache.MustacheTokens)
doc.template
else
template_path = isempty(doc.template) ? normpath(TEMPLATE_DIR, "julia_tex.tpl") : doc.template
Mustache.template_from_file(template_path)
end
highlight = stylesheet(MIME("text/latex"), doc.highlight_theme)
return Mustache.render(
template;
body = formatted,
highlight = highlight,
[Pair(Symbol(k), v) for (k, v) in doc.header]...,
)
end
stylesheet(m::MIME, theme) = sprint((io, x) -> Highlights.stylesheet(io, m, x), theme)
const WEAVE_VERSION = try
'v' * Pkg.TOML.parsefile(normpath(PKG_DIR, "Project.toml"))["version"]
catch
""
end
weave_info() = WEAVE_VERSION, string(Date(now()))
# TODO: is there any other format where we want to restore headers ?
const HEADER_PRESERVE_DOCTYPES = ("github", "hugo")
function restore_header!(doc)
doc.doctype in HEADER_PRESERVE_DOCTYPES || return # don't restore
# only strips Weave headers
delete!(doc.header, WEAVE_OPTION_NAME)
if haskey(doc.header, WEAVE_OPTION_NAME_DEPRECATED)
@warn "Weave: `options` key is deprecated. Use `weave_options` key instead." _id = WEAVE_OPTION_DEPRECATE_ID maxlog = 1
delete!(doc.header, WEAVE_OPTION_NAME_DEPRECATED)
end
isempty(doc.header) && return
# restore remained headers as `DocChunk`
header_text = "---\n$(YAML.write(doc.header))---"
pushfirst!(doc.chunks, DocChunk(header_text, 0, 0))
end
format_chunk(chunk::DocChunk, formatdict, docformat) = join((format_inline(c) for c in chunk.content))
format_inline(inline::InlineText) = inline.content
function format_inline(inline::InlineCode)
isempty(inline.rich_output) || return inline.rich_output
isempty(inline.figures) || return inline.figures[end]
return inline.output
end
function ioformat!(io::IOBuffer, out::IOBuffer, fun = WeaveMarkdown.latex)
text = String(take!(io))
if !isempty(text)
m = Markdown.parse(text, flavor = WeaveMarkdown.weavemd)
write(out, string(fun(m)))
end
end
addspace(op, inline) = (inline.ctype === :line && (op = "\n$op\n"); op)
function format_chunk(chunk::DocChunk, formatdict, docformat::JMarkdown2tex)
out = IOBuffer()
io = IOBuffer()
for inline in chunk.content
if isa(inline, InlineText)
write(io, inline.content)
elseif !isempty(inline.rich_output)
ioformat!(io, out)
write(out, addspace(inline.rich_output, inline))
elseif !isempty(inline.figures)
write(io, inline.figures[end], inline)
elseif !isempty(inline.output)
write(io, addspace(inline.output, inline))
end
end
ioformat!(io, out)
formatdict[:keep_unicode] || return uc2tex(String(take!(out)))
return String(take!(out))
end
function format_chunk(chunk::DocChunk, formatdict, docformat::JMarkdown2HTML)
out = IOBuffer()
io = IOBuffer()
fun = WeaveMarkdown.html
for inline in chunk.content
if isa(inline, InlineText)
write(io, inline.content)
elseif !isempty(inline.rich_output)
ioformat!(io, out, fun)
write(out, addspace(inline.rich_output, inline))
elseif !isempty(inline.figures)
write(io, inline.figures[end])
elseif !isempty(inline.output)
write(io, addspace(inline.output, inline))
end
end
ioformat!(io, out, fun)
return String(take!(out))
end
function format_chunk(chunk::CodeChunk, formatdict, docformat)
# Fill undefined options with format specific defaults
chunk.options[:out_width] == nothing &&
(chunk.options[:out_width] = formatdict[:out_width])
chunk.options[:fig_pos] == nothing && (chunk.options[:fig_pos] = formatdict[:fig_pos])
# Only use floats if chunk has caption or sets fig_env
if chunk.options[:fig_cap] != nothing && chunk.options[:fig_env] == nothing
(chunk.options[:fig_env] = formatdict[:fig_env])
end
if haskey(formatdict, :indent)
chunk.content = indent(chunk.content, formatdict[:indent])
end
chunk.content = format_code(chunk.content, docformat)
if !chunk.options[:eval]
if chunk.options[:echo]
result = "$(formatdict[:codestart])\n$(chunk.content)$(formatdict[:codeend])"
return result
else
r = ""
return r
end
end
if chunk.options[:term]
result = format_termchunk(chunk, formatdict, docformat)
else
if chunk.options[:echo]
# Convert to output format and highlight (html, tex...) if needed
result = "$(formatdict[:codestart])$(chunk.content)$(formatdict[:codeend])\n"
else
result = ""
end
if (strip(chunk.output) != "" || strip(chunk.rich_output) != "") &&
(chunk.options[:results] != "hidden")
if chunk.options[:results] != "markup" && chunk.options[:results] != "hold"
strip(chunk.output) "" && (result *= "$(chunk.output)\n")
strip(chunk.rich_output) "" && (result *= "$(chunk.rich_output)\n")
else
if chunk.options[:wrap]
chunk.output =
"\n" * wraplines(chunk.output, chunk.options[:line_width])
chunk.output = format_output(chunk.output, docformat)
else
chunk.output = "\n" * rstrip(chunk.output)
chunk.output = format_output(chunk.output, docformat)
end
if haskey(formatdict, :indent)
chunk.output = indent(chunk.output, formatdict[:indent])
end
strip(chunk.output) "" && (
result *= "$(formatdict[:outputstart])$(chunk.output)\n$(formatdict[:outputend])\n"
)
strip(chunk.rich_output) "" && (result *= chunk.rich_output * "\n")
end
end
end
# Handle figures
if chunk.options[:fig] && length(chunk.figures) > 0
if chunk.options[:include]
result *= formatfigures(chunk, docformat)
end
end
return result
end
format_output(result, docformat) = result
format_output(result, docformat::JMarkdown2HTML) = Markdown.htmlesc(result)
function format_output(result, docformat::JMarkdown2tex)
# Highligts has some extra escaping defined, eg of $, ", ...
result_escaped = sprint(
(io, x) ->
Highlights.Format.escape(io, MIME("text/latex"), x, charescape = true),
result,
)
docformat.formatdict[:keep_unicode] || return uc2tex(result_escaped, true)
return result_escaped
end
format_code(result, docformat) = result
function format_code(result, docformat::JMarkdown2tex)
highlighted = highlight(
MIME("text/latex"),
strip(result),
Highlights.Lexers.JuliaLexer,
docformat.formatdict[:theme],
)
docformat.formatdict[:keep_unicode] || return uc2tex(highlighted)
return highlighted
# return "\\begin{minted}[mathescape, fontsize=\\small, xleftmargin=0.5em]{julia}\n$result\n\\end{minted}\n"
end
# Convert unicode to tex, escape listings if needed
function uc2tex(s, escape = false)
for key in keys(latex_symbols)
if escape
s = replace(s, latex_symbols[key] => "(*@\\ensuremath{$(texify(key))}@*)")
else
s = replace(s, latex_symbols[key] => "\\ensuremath{$(texify(key))}")
end
end
return s
end
# Make julia symbols (\bf* etc.) valid latex
function texify(s)
ts = ""
if occursin(r"^\\bf[A-Z]$", s)
ts = replace(s, "\\bf" => "\\bm{\\mathrm{") * "}}"
elseif startswith(s, "\\bfrak")
ts = replace(s, "\\bfrak" => "\\bm{\\mathfrak{") * "}}"
elseif startswith(s, "\\bf")
ts = replace(s, "\\bf" => "\\bm{\\") * "}"
elseif startswith(s, "\\frak")
ts = replace(s, "\\frak" => "\\mathfrak{") * "}"
else
ts = s
end
return ts
end
function format_code(result, docformat::JMarkdown2HTML)
return highlight(
MIME("text/html"),
strip(result),
Highlights.Lexers.JuliaLexer,
docformat.formatdict[:theme],
)
end
function format_code(result, docformat::Pandoc2HTML)
return highlight(
MIME("text/html"),
strip(result),
Highlights.Lexers.JuliaLexer,
docformat.formatdict[:theme],
)
end
function format_termchunk(chunk, formatdict, docformat)
if chunk.options[:echo] && chunk.options[:results] != "hidden"
result = "$(formatdict[:termstart])$(chunk.output)\n" * "$(formatdict[:termend])\n"
else
result = ""
end
return result
end
function format_termchunk(chunk, formatdict, docformat::JMarkdown2HTML)
if chunk.options[:echo] && chunk.options[:results] != "hidden"
result = highlight(
MIME("text/html"),
strip(chunk.output),
Highlights.Lexers.JuliaConsoleLexer,
docformat.formatdict[:theme],
)
else
result = ""
end
return result
end
function format_termchunk(chunk, formatdict, docformat::Pandoc2HTML)
if chunk.options[:echo] && chunk.options[:results] != "hidden"
result = highlight(
MIME("text/html"),
strip(chunk.output),
Highlights.Lexers.JuliaConsoleLexer,
docformat.formatdict[:theme],
)
else
result = ""
end
return result
end
function format_termchunk(chunk, formatdict, docformat::JMarkdown2tex)
if chunk.options[:echo] && chunk.options[:results] != "hidden"
result = highlight(
MIME("text/latex"),
strip(chunk.output),
Highlights.Lexers.JuliaConsoleLexer,
docformat.formatdict[:theme],
)
# return "\\begin{minted}[mathescape, fontsize=\\small, xleftmargin=0.5em]{julia}\n$result\n\\end{minted}\n"
else
result = ""
end
return result
end
function highlight(
mime::MIME,
output,
lexer,
theme = Highlights.Themes.DefaultTheme,
)
return sprint((io, x) -> Highlights.highlight(io, mime, x, lexer, theme), output)
end
indent(text, nindent) = join(map(x -> string(repeat(' ', nindent), x), split(text, '\n')), '\n')
function wraplines(text, line_width = 75)
result = AbstractString[]
lines = split(text, "\n")
for line in lines
if length(line) > line_width
push!(result, wrapline(line, line_width))
else
push!(result, line)
end
end
return strip(join(result, "\n"))
end
function wrapline(text, line_width = 75)
result = ""
while length(text) > line_width
result *= first(text, line_width) * "\n"
text = chop(text, head = line_width, tail = 0)
end
result *= text
end

View File

@ -1,529 +0,0 @@
# so dirty, refactor
using Printf
struct Tex
description::AbstractString
formatdict::Dict{Symbol,Any}
end
const tex = Tex(
"Latex with custom code environments",
Dict{Symbol,Any}(
:codestart => "\\begin{juliacode}",
:codeend => "\\end{juliacode}",
:outputstart => "\\begin{juliaout}",
:outputend => "\\end{juliaout}",
:termstart => "\\begin{juliaterm}",
:termend => "\\end{juliaterm}",
:fig_ext => ".pdf",
:extension => "tex",
:out_width => "\\linewidth",
:fig_env => "figure",
:fig_pos => "htpb",
:doctype => "tex",
:mimetypes => ["application/pdf", "image/png", "text/latex", "text/plain"],
:keep_unicode => false,
),
)
const texminted = Tex(
"Latex using minted for highlighting",
Dict{Symbol,Any}(
:codestart =>
"\\begin{minted}[mathescape, fontsize=\\small, xleftmargin=0.5em]{julia}",
:codeend => "\\end{minted}",
:outputstart =>
"\\begin{minted}[fontsize=\\small, xleftmargin=0.5em, mathescape, frame = leftline]{text}",
:outputend => "\\end{minted}",
:termstart =>
"\\begin{minted}[fontsize=\\footnotesize, xleftmargin=0.5em, mathescape]{jlcon}",
:termend => "\\end{minted}",
:fig_ext => ".pdf",
:extension => "tex",
:out_width => "\\linewidth",
:fig_env => "figure",
:fig_pos => "htpb",
:doctype => "texminted",
:mimetypes => ["application/pdf", "image/png", "text/latex", "text/plain"],
:keep_unicode => false,
),
)
struct Pandoc
description::AbstractString
formatdict::Dict{Symbol,Any}
end
const pandoc = Pandoc(
"Pandoc markdown",
Dict{Symbol,Any}(
:codestart => "~~~~{.julia}",
:codeend => "~~~~~~~~~~~~~\n\n",
:outputstart => "~~~~",
:outputend => "~~~~\n\n",
:fig_ext => ".png",
:out_width => nothing,
:extension => "md",
# Prefer png figures for markdown conversion, svg doesn't work with latex
:mimetypes =>
["image/png", "image/jpg", "image/svg+xml", "text/markdown", "text/plain"],
:doctype => "pandoc",
),
)
struct Pandoc2HTML
description::AbstractString
formatdict::Dict{Symbol,Any}
end
const pdoc2html = Pandoc2HTML(
"Markdown to HTML (requires Pandoc 2)",
Dict{Symbol,Any}(
:codestart => "\n",
:codeend => "\n",
:outputstart => "\n",
:outputend => "\n",
:fig_ext => ".png",
:extension => "md",
:mimetypes => [
"image/png",
"image/svg+xml",
"image/jpg",
"text/html",
"text/markdown",
"text/plain",
],
:doctype => "pandoc2html",
),
)
struct GitHubMarkdown
description::AbstractString
formatdict::Dict{Symbol,Any}
end
const github = GitHubMarkdown(
"GitHub markdown",
Dict{Symbol,Any}(
:codestart => "````julia",
:codeend => "````\n\n",
:outputstart => "````",
:outputend => "````\n\n",
:fig_ext => ".png",
:extension => "md",
:mimetypes =>
["image/png", "image/svg+xml", "image/jpg", "text/markdown", "text/plain"],
:doctype => "github",
),
)
"""
Formatter for Hugo: https://gohugo.io/
When `uglyURLs` is `false`, prepend figure path by `..`.
"""
struct Hugo
description::AbstractString
formatdict::Dict{Symbol,Any}
uglyURLs::Bool
end
const hugo = Hugo(
"Hugo markdown (using shortcodes)",
Dict{Symbol,Any}(
:codestart => "````julia",
:codeend => "````\n\n",
:outputstart => "````",
:outputend => "````\n\n",
:fig_ext => ".png",
:extension => "md",
:doctype => "hugo",
),
false,
)
# Julia markdown
struct JMarkdown2HTML
description::AbstractString
formatdict::Dict{Symbol,Any}
end
const md2html = JMarkdown2HTML(
"Julia markdown to html",
Dict{Symbol,Any}(
:codestart => "\n",
:codeend => "\n",
:outputstart => "<pre class=\"output\">",
:outputend => "</pre>\n",
:fig_ext => ".png",
:mimetypes => [
"image/png",
"image/jpg",
"image/svg+xml",
"text/html",
"text/markdown",
"text/plain",
],
:extension => "html",
:doctype => "md2html",
),
)
# Julia markdown
struct JMarkdown2tex
description::AbstractString
formatdict::Dict{Symbol,Any}
end
const md2tex = JMarkdown2tex(
"Julia markdown to latex",
Dict{Symbol,Any}(
:codestart => "",
:codeend => "",
:outputstart => "\\begin{lstlisting}",
:outputend => "\\end{lstlisting}\n",
:fig_ext => ".pdf",
:extension => "tex",
:out_width => "\\linewidth",
:mimetypes => [
"application/pdf",
"image/png",
"image/jpg",
"text/latex",
"text/markdown",
"text/plain",
],
:doctype => "md2tex",
:keep_unicode => false,
),
)
struct MultiMarkdown
description::AbstractString
formatdict::Dict{Symbol,Any}
end
function formatfigures(chunk, docformat::JMarkdown2HTML)
fignames = chunk.figures
caption = chunk.options[:fig_cap]
width = chunk.options[:out_width]
height = chunk.options[:out_height]
f_pos = chunk.options[:fig_pos]
f_env = chunk.options[:fig_env]
result = ""
figstring = ""
# Set size
attribs = ""
width == nothing || (attribs = "width=\"$width\"")
(attribs != "" && height != nothing) && (attribs *= ",")
height == nothing || (attribs *= " height=\"$height\" ")
if caption != nothing
result *= """<figure>\n"""
end
for fig in fignames
figstring *= """<img src="$fig" $attribs />\n"""
end
result *= figstring
if caption != nothing
result *= """
<figcaption>$caption</figcaption>
"""
end
if caption != nothing
result *= "</figure>\n"
end
return result
end
const multimarkdown = MultiMarkdown(
"MultiMarkdown",
Dict{Symbol,Any}(
:codestart => "````julia",
:codeend => "````\n\n",
:outputstart => "````",
:outputend => "````\n\n",
:fig_ext => ".png",
:extension => "md",
:doctype => "github",
),
)
struct Rest
description::AbstractString
formatdict::Dict{Symbol,Any}
end
const rst = Rest(
"reStructuredText and Sphinx",
Dict{Symbol,Any}(
:codestart => ".. code-block:: julia\n",
:codeend => "\n\n",
:outputstart => "::\n",
:outputend => "\n\n",
:indent => 4,
:fig_ext => ".png",
:extension => "rst",
:out_width => "15 cm",
:doctype => "rst",
),
)
struct AsciiDoc
description::AbstractString
formatdict::Dict{Symbol,Any}
end
# asciidoc -b html5 -a source-highlighter=pygments ...
const adoc = AsciiDoc(
"AsciiDoc",
Dict{Symbol,Any}(
:codestart => "[source,julia]\n--------------------------------------",
:codeend => "--------------------------------------\n\n",
:outputstart => "--------------------------------------",
:outputend => "--------------------------------------\n\n",
:fig_ext => ".png",
:extension => "txt",
:out_width => "600",
:doctype => "asciidoc",
),
)
function md_length_to_latex(def, reference)
if occursin("%", def)
_def = tryparse(Float64, replace(def, "%" => ""))
_def == nothing && return def
perc = round(_def / 100, digits = 2)
return "$perc$reference"
end
return def
end
function formatfigures(chunk, docformat::Union{Tex,JMarkdown2tex})
fignames = chunk.figures
caption = chunk.options[:fig_cap]
width = chunk.options[:out_width]
height = chunk.options[:out_height]
f_pos = chunk.options[:fig_pos]
f_env = chunk.options[:fig_env]
result = ""
figstring = ""
if f_env == nothing && caption != nothing
f_env = "figure"
end
(f_pos == nothing) && (f_pos = "!h")
# Set size
attribs = ""
width == nothing || (attribs = "width=$(md_length_to_latex(width,"\\linewidth"))")
(attribs != "" && height != nothing) && (attribs *= ",")
height == nothing || (attribs *= "height=$(md_length_to_latex(height,"\\paperheight"))")
if f_env != nothing
result *= "\\begin{$f_env}"
(f_pos != "") && (result *= "[$f_pos]")
result *= "\n"
end
for fig in fignames
if splitext(fig)[2] == ".tex" # Tikz figures
figstring *= "\\resizebox{$width}{!}{\\input{$fig}}\n"
else
if isempty(attribs)
figstring *= "\\includegraphics{$fig}\n"
else
figstring *= "\\includegraphics[$attribs]{$fig}\n"
end
end
end
# Figure environment
if caption != nothing
result *= string("\\center\n", "$figstring", "\\caption{$caption}\n")
else
result *= figstring
end
if chunk.options[:label] != nothing && f_env != nothing
label = chunk.options[:label]
result *= "\\label{fig:$label}\n"
end
if f_env != nothing
result *= "\\end{$f_env}\n"
end
return result
end
formatfigures(chunk, docformat::Pandoc2HTML) = formatfigures(chunk, pandoc)
function formatfigures(chunk, docformat::Pandoc)
fignames = chunk.figures
length(fignames) > 0 || (return "")
caption = chunk.options[:fig_cap]
label = get(chunk.options, :label, nothing)
result = ""
figstring = ""
attribs = ""
width = chunk.options[:out_width]
height = chunk.options[:out_height]
# Build figure attibutes
attribs = String[]
width == nothing || push!(attribs, "width=$width")
height == nothing || push!(attribs, "height=$height")
label == nothing || push!(attribs, "#fig:$label")
attribs = isempty(attribs) ? "" : "{" * join(attribs, " ") * "}"
if caption != nothing
result *= "![$caption]($(fignames[1]))$attribs\n"
for fig in fignames[2:end]
result *= "![]($fig)$attribs\n"
println("Warning, only the first figure gets a caption\n")
end
else
for fig in fignames
result *= "![]($fig)$attribs\\ \n\n"
end
end
return result
end
function formatfigures(chunk, docformat::GitHubMarkdown)
fignames = chunk.figures
caption = chunk.options[:fig_cap]
result = ""
figstring = ""
length(fignames) > 0 || (return "")
if caption != nothing
result *= "![$caption]($(fignames[1]))\n"
for fig in fignames[2:end]
result *= "![]($fig)\n"
println("Warning, only the first figure gets a caption\n")
end
else
for fig in fignames
result *= "![]($fig)\n"
end
end
return result
end
function formatfigures(chunk, docformat::Hugo)
relpath = docformat.uglyURLs ? "" : ".."
function format_shortcode(index_and_fig)
index, fig = index_and_fig
if index > 1
@warn("Only the first figure gets a caption.")
title_spec = ""
else
caption = chunk.options[:fig_cap]
title_spec = caption == nothing ? "" : "title=\"$(caption)\" "
end
"{{< figure src=\"$(joinpath(relpath, fig))\" $(title_spec) >}}"
end
mapreduce(format_shortcode, *, enumerate(chunk.figures), init = "")
end
function formatfigures(chunk, docformat::MultiMarkdown)
fignames = chunk.figures
caption = chunk.options[:fig_cap]
result = ""
figstring = ""
if chunk.options[:out_width] == nothing
width = ""
else
width = "width=$(chunk.options[:out_width])"
end
length(fignames) > 0 || (return "")
if caption != nothing
result *= "![$caption][$(fignames[1])]\n\n"
result *= "[$(fignames[1])]: $(fignames[1]) $width\n"
for fig in fignames[2:end]
result *= "![][$fig]\n\n"
result *= "[$fig]: $fig $width\n"
println("Warning, only the first figure gets a caption\n")
end
else
for fig in fignames
result *= "![][$fig]\n\n"
result *= "[$fig]: $fig $width\n"
end
end
return result
end
function formatfigures(chunk, docformat::Rest)
fignames = chunk.figures
caption = chunk.options[:fig_cap]
width = chunk.options[:out_width]
result = ""
figstring = ""
for fig in fignames
figstring *= @sprintf(".. image:: %s\n :width: %s\n\n", fig, width)
end
if caption != nothing
result *= string(
".. figure:: $(fignames[1])\n",
" :width: $width\n\n",
" $caption\n\n",
)
else
result *= figstring
return result
end
end
function formatfigures(chunk, docformat::AsciiDoc)
fignames = chunk.figures
caption = chunk.options[:fig_cap]
width = chunk.options[:out_width]
result = ""
figstring = ""
for fig in fignames
figstring *= @sprintf("image::%s[width=%s]\n", fig, width)
end
if caption != nothing
result *= string("image::$(fignames[1])", "[width=$width,", "title=\"$caption\"]")
else
result *= figstring
return result
end
end
# Add new supported formats here
const formats = Dict(
"tex" => tex,
"texminted" => texminted,
"pandoc" => pandoc,
"pandoc2html" => pdoc2html,
"pandoc2pdf" => pandoc,
"md2pdf" => md2tex,
"github" => github,
"hugo" => hugo,
"multimarkdown" => multimarkdown,
"rst" => rst,
"asciidoc" => adoc,
"md2html" => md2html,
"md2tex" => md2tex,
)

View File

@ -1,122 +0,0 @@
"""
pandoc2html(formatted::AbstractString, doc::WeaveDoc)
Convert output from pandoc markdown to html using Weave.jl template
"""
function pandoc2html(
formatted::AbstractString,
doc::WeaveDoc,
outname::AbstractString,
pandoc_options,
)
weavedir = dirname(@__FILE__)
html_template = joinpath(weavedir, "../templates/pandoc_skeleton.html")
css_template = joinpath(weavedir, "../templates/pandoc_skeleton.css")
highlightcss = stylesheet(MIME("text/html"), doc.highlight_theme)
path, wsource = splitdir(abspath(doc.source))
wversion, wdate = weave_info()
# Header is inserted from displayed plots
header_script = doc.header_script
self_contained = (header_script "") ? [] : "--self-contained"
if haskey(doc.header, "bibliography")
filt = "--filter"
citeproc = "pandoc-citeproc"
else
filt = []
citeproc = []
end
# Change path for pandoc
cd_back = let d = pwd(); () -> cd(d); end
cd(doc.cwd)
outname = basename(outname)
try
cmd = `pandoc -f markdown+raw_html -s --mathjax=""
$filt $citeproc $pandoc_options
--template $html_template -H $css_template $self_contained
-V wversion=$wversion -V wdate=$wdate -V wsource=$wsource
-V highlightcss=$highlightcss
-V headerscript=$header_script
-o $outname`
proc = open(cmd, "r+")
println(proc.in, formatted)
close(proc.in)
proc_output = read(proc.out, String)
catch
@warn "Error converting document to HTML"
rethrow() # TODO: just show error content instead of rethrow the err
finally
cd_back()
end
end
"""
pandoc2pdf(formatted::AbstractString, doc::WeaveDoc)
Convert output from pandoc markdown to pdf using Weave.jl template
"""
function pandoc2pdf(
formatted::AbstractString,
doc::WeaveDoc,
outname::AbstractString,
pandoc_options,
)
weavedir = dirname(@__FILE__)
header_template = joinpath(weavedir, "../templates/pandoc_header.txt")
path, wsource = splitdir(abspath(doc.source))
outname = basename(outname)
# Change path for pandoc
cd_back = let d = pwd(); () -> cd(d); end
cd(doc.cwd)
if haskey(doc.header, "bibliography")
filt = "--filter"
citeproc = "pandoc-citeproc"
else
filt = []
citeproc = []
end
@info "Done executing code. Running xelatex"
try
cmd = `pandoc -f markdown+raw_tex -s --pdf-engine=xelatex --highlight-style=tango
$filt $citeproc $pandoc_options
--include-in-header=$header_template
-V fontsize=12pt -o $outname`
proc = open(cmd, "r+")
println(proc.in, formatted)
close(proc.in)
proc_output = read(proc.out, String)
catch
@warn "Error converting document to pdf"
rethrow()
finally
cd_back()
end
end
function run_latex(doc::WeaveDoc, outname, latex_cmd = "xelatex")
cd_back = let d = pwd(); () -> cd(d); end
cd(doc.cwd)
xname = basename(outname)
@info "Weaved code to $outname . Running $latex_cmd" # space before '.' added for link to be clickable in Juno terminal
textmp = mktempdir(".")
try
cmd = `$latex_cmd -shell-escape $xname -aux-directory $textmp -include-directory $(doc.cwd)`
run(cmd); run(cmd) # XXX: is twice enough for every case ?
catch
@warn "Error converting document to pdf. Try running latex manually"
rethrow()
finally
rm(xname)
rm(textmp, recursive = true)
cd_back()
end
end

View File

@ -1,24 +1,23 @@
module WeavePlots
using Base64, ..Plots, ..Weave
using ..Base64, ..Plots, ..Weave
# Pre-execute hooks to set the plot size for the chunk
function plots_set_size(chunk)
function plots_set_size!(chunk)
w = chunk.options[:fig_width] * chunk.options[:dpi]
h = chunk.options[:fig_height] * chunk.options[:dpi]
Plots.default(size = (w, h))
return chunk
end
Weave.push_preexecute_hook(plots_set_size)
Weave.push_preexecution_hook!(plots_set_size!)
# PNG or SVG is not working, output html
function Base.display(
report::Weave.Report,
m::MIME"image/svg+xml",
data::Plots.Plot{Plots.PlotlyBackend},
)#
)
# Remove extra spaces from start of line for pandoc
s = repr(MIME("text/html"), data)
splitted = split(s, "\n")
@ -40,7 +39,7 @@ function Base.display(
report::Weave.Report,
m::MIME"image/png",
data::Plots.Plot{Plots.PlotlyBackend},
)#
)
display(report, MIME("image/svg+xml"), data)
end

View File

@ -5,7 +5,7 @@ function parse_markdown(document_body; is_pandoc = false)
r"^<<(?<options>.*?)>>=\s*$",
r"^@\s*$"
else
r"^[`~]{3}(?:\{?)julia(?:;?)\s*(?<options>.*?)(\}|\s*)$",
r"^[`~]{3}(\{?)julia\s*([;,\{]?)\s*(?<options>.*?)(\}|\s*)$",
r"^[`~]{3}\s*$"
end
return header, parse_markdown_body(document_body, code_start, code_end, offset)
@ -49,72 +49,47 @@ end
function parse_markdown_body(document_body, code_start, code_end, offset)
lines = split(document_body, '\n')
state = "doc"
docno = 1
codeno = 1
state = :doc
doc_no = 0
code_no = 0
content = ""
start_line = offset
options = Dict()
optionString = ""
chunks = WeaveChunk[]
for (lineno, line) in enumerate(lines)
m = match(code_start, line)
if !isnothing(m) && state == "doc"
state = "code"
if m.captures[1] == nothing
optionString = ""
else
optionString = strip(m.captures[1])
end
options = OptionDict()
option_string = ""
options = Dict{Symbol,Any}()
if length(optionString) > 0
expr = Meta.parse(optionString)
Base.Meta.isexpr(expr, :(=)) && (options[expr.args[1]] = expr.args[2])
Base.Meta.isexpr(expr, :toplevel) &&
map(pushopt, fill(options, length(expr.args)), expr.args)
end
chunks = WeaveChunk[]
for (line_no, line) in enumerate(lines)
m = match(code_start, line)
if !isnothing(m) && state === :doc
state = :code
option_string = isnothing(m[:options]) ? "" : strip(m[:options])
options = parse_options(option_string)
haskey(options, :label) && (options[:name] = options[:label])
haskey(options, :name) || (options[:name] = nothing)
if !isempty(strip(content))
chunk = DocChunk(content, docno, start_line)
docno += 1
push!(chunks, chunk)
end
isempty(strip(content)) || push!(chunks, DocChunk(content, doc_no += 1, start_line))
start_line = line_no + offset
content = ""
start_line = lineno + offset
continue
end
if occursin(code_end, line) && state == "code"
chunk = CodeChunk(content, codeno, start_line, optionString, options)
if occursin(code_end, line) && state === :code
push!(chunks, CodeChunk(content, code_no += 1, start_line, option_string, options))
codeno += 1
start_line = lineno + offset
start_line = line_no + offset
content = ""
state = "doc"
push!(chunks, chunk)
state = :doc
continue
end
if lineno == 1
content *= line
else
content *= "\n" * line
end
content *= isone(line_no) ? line : string('\n', line)
end
# Remember the last chunk
if strip(content) != ""
chunk = DocChunk(content, docno, start_line)
# chunk = Dict{Symbol,Any}(:type => "doc", :content => content,
# :number => docno, :start_line => start_line)
push!(chunks, chunk)
end
isempty(strip(content)) || push!(chunks, DocChunk(content, doc_no += 1, start_line))
return chunks
end

View File

@ -1,22 +1,21 @@
using JSON
function parse_notebook(document_body)
nb = JSON.parse(document_body)
chunks = WeaveChunk[]
code_no = 0
doc_no = 0
# TODO: handle some of options ?
options = Dict{Symbol,Any}()
opt_string = ""
docno = 1
codeno = 1
for cell in nb["cells"]
srctext = "\n" * join(cell["source"], "")
if cell["cell_type"] == "code"
chunk = CodeChunk(rstrip(srctext), codeno, 0, opt_string, options)
push!(chunks, chunk)
codeno += 1
chunks = map(nb["cells"]) do cell
text = string('\n', join(cell["source"]), '\n')
return if cell["cell_type"] == "code"
CodeChunk(text, code_no += 1, 0, opt_string, options)
else
chunk = DocChunk(srctext * "\n", docno, 0; notebook = true)
push!(chunks, chunk)
docno += 1
DocChunk(text, doc_no += 1, 0; notebook = true)
end
end

View File

@ -1,8 +1,9 @@
using JSON, YAML
using YAML
function WeaveDoc(source, informat = nothing)
path, fname = splitdir(abspath(source))
path = abspath(source)
_, fname = splitdir(path)
basename = splitext(fname)[1]
isnothing(informat) && (informat = detect_informat(source))
@ -36,10 +37,6 @@ function WeaveDoc(source, informat = nothing)
"",
"",
header,
"",
"",
Highlights.Themes.DefaultTheme,
"",
chunk_defaults,
)
end
@ -68,12 +65,6 @@ function parse_doc(document, informat)
error("unsupported input format given: $informat")
end
function pushopt(options::Dict, expr::Expr)
if Base.Meta.isexpr(expr, :(=))
options[expr.args[1]] = expr.args[2]
end
end
# inline
# ------
@ -86,34 +77,51 @@ end
const INLINE_REGEX = r"`j\s+(.*?)`"
const INLINE_REGEXES = r"`j\s+(.*?)`|^!\s(.*)$"m
function parse_inlines(text)::Vector{Inline}
occursin(INLINE_REGEXES, text) || return parse_inline(text)
inline_chunks = eachmatch(INLINE_REGEXES, text)
# handle code units correctly !
function parse_inlines(str)
ret = Inline[]
s = 1
e = 1
res = Inline[]
textno = 1
codeno = 1
for ic in inline_chunks
s = ic.offset
doc = InlineText(text[e:(s-1)], e, s - 1, textno)
textno += 1
push!(res, doc)
e = s + lastindex(ic.match)
ic.captures[1] !== nothing && (ctype = :inline)
ic.captures[2] !== nothing && (ctype = :line)
cap = filter(x -> x !== nothing, ic.captures)[1]
push!(res, InlineCode(cap, s, e, codeno, ctype))
codeno += 1
code_no = text_no = 0
for m in eachmatch(INLINE_REGEXES, str)
e = m.offset
push!(ret, InlineText((str[s:prevind(str,e)]), text_no += 1))
i = findfirst(!isnothing, m.captures)
push!(ret, InlineCode(m.captures[i], code_no += 1, isone(i) ? :inline : :line))
s = e + ncodeunits(m.match)
end
push!(res, InlineText(text[e:end], e, length(text), textno))
return res
push!(ret, InlineText(str[s:end], text_no += 1))
return ret
end
parse_inline(text) = Inline[InlineText(text, 1, length(text), 1)]
parse_inline(str) = Inline[InlineText(str, 1)]
# options
# -------
const OptionDict = Dict{Symbol,Any}
function parse_options(str)::OptionDict
str = string('(', str, ')')
ex = Meta.parse(str)
nt = if Meta.isexpr(ex, (
:block, # "(k1 = v1; k2 = v2, ...)"
:tuple, # "(k1 = v1, k2 = v2, ...)"
))
eval(Expr(:tuple, filter(is_valid_kv, ex.args)...))
elseif is_valid_kv(ex) # "(k = v)"
eval(Expr(:tuple, ex))
else
NamedTuple{}()
end
return dict(nt)
end
is_valid_kv(x) = Meta.isexpr(x, :(=))
dict(nt) = Dict((k => v for (k,v) in zip(keys(nt), values(nt)))...)
nt(dict) = NamedTuple{(Symbol.(keys(dict))...,)}((collect(values(dict))...,))
# each input format
# -----------------
include("markdown.jl")
include("script.jl")

View File

@ -1,89 +1,67 @@
function parse_script(document_body)
lines = split(document_body, "\n")
lines = split(document_body, '\n')
doc_line = r"(^#'.*)|(^#%%.*)|(^# %%.*)"
doc_start = r"(^#')|(^#%%)|(^# %%)"
opt_line = r"(^#\+.*$)|(^#%%\+.*$)|(^# %%\+.*$)"
opt_start = r"(^#\+)|(^#%%\+)|(^# %%\+)"
read = ""
docno = 1
codeno = 1
content = ""
state = :code
doc_no = 0
code_no = 0
start_line = 1
options = Dict{Symbol,Any}()
optionString = ""
options = OptionDict()
option_string = ""
chunks = WeaveChunk[]
state = "code"
for lineno = 1:length(lines)
line = lines[lineno]
if (m = match(doc_line, line)) != nothing && (m = match(opt_line, line)) == nothing
for (line_no, line) in enumerate(lines)
if (m = match(doc_line, line)) !== nothing && (m = match(opt_line, line)) === nothing
line = replace(line, doc_start => "", count = 1)
if startswith(line, " ")
line = replace(line, " " => "", count = 1)
startswith(line, ' ') && (line = replace(line, ' ' => "", count = 1))
if state === :code && !isempty(strip(content))
push!(chunks, CodeChunk(string('\n', strip(content)), code_no += 1, start_line, option_string, options))
content = ""
start_line = line_no
end
if state == "code" && strip(read) != ""
chunk =
CodeChunk("\n" * strip(read), codeno, start_line, optionString, options)
push!(chunks, chunk)
codeno += 1
read = ""
start_line = lineno
state = :doc
elseif (m = match(opt_line, line)) !== nothing
start_line = line_no
if state === :code && !isempty(strip(content))
push!(chunks, CodeChunk(string('\n', strip(content)), code_no += 1, start_line, option_string, options))
content = ""
end
state = "doc"
elseif (m = match(opt_line, line)) != nothing
start_line = lineno
if state == "code" && strip(read) != ""
chunk =
CodeChunk("\n" * strip(read), codeno, start_line, optionString, options)
push!(chunks, chunk)
read = ""
codeno += 1
end
if state == "doc" && strip(read) != ""
(docno > 1) && (read = "\n" * read) # Add whitespace to doc chunk. Needed for markdown output
chunk = DocChunk(read, docno, start_line)
push!(chunks, chunk)
read = ""
docno += 1
if state === :doc && !isempty(strip(content))
iszero(doc_no) || (content = string('\n', content)) # Add whitespace to doc chunk. Needed for markdown output
push!(chunks, DocChunk(content, doc_no += 1, start_line))
content = ""
end
optionString = replace(line, opt_start => "", count = 1)
# Get options
options = Dict{Symbol,Any}()
if length(optionString) > 0
expr = Meta.parse(optionString)
Base.Meta.isexpr(expr, :(=)) && (options[expr.args[1]] = expr.args[2])
Base.Meta.isexpr(expr, :toplevel) &&
map(pushopt, fill(options, length(expr.args)), expr.args)
end
option_string = replace(line, opt_start => "", count = 1)
options = parse_options(option_string)
haskey(options, :label) && (options[:name] = options[:label])
haskey(options, :name) || (options[:name] = nothing)
state = "code"
state = :code
continue
elseif state == "doc" # && strip(line) != "" && strip(read) != ""
state = "code"
(docno > 1) && (read = "\n" * read) # Add whitespace to doc chunk. Needed for markdown output
chunk = DocChunk(read, docno, start_line)
push!(chunks, chunk)
elseif state === :doc # && strip(line) != "" && strip(content) != ""
state = :code
iszero(doc_no) || (content = string('\n', content)) # Add whitespace to doc chunk. Needed for markdown output
push!(chunks, DocChunk(content, doc_no += 1, start_line))
content = ""
options = Dict{Symbol,Any}()
start_line = lineno
read = ""
docno += 1
start_line = line_no
end
read *= line * "\n"
content *= string(line, '\n')
end
# Handle the last chunk
if state == "code"
chunk = CodeChunk("\n" * strip(read), codeno, start_line, optionString, options)
push!(chunks, chunk)
else
chunk = DocChunk(read, docno, start_line)
push!(chunks, chunk)
end
chunk = state === :code ?
CodeChunk(string('\n', strip(content)), code_no, start_line, option_string, options) :
DocChunk(content, doc_no, start_line)
push!(chunks, chunk)
return Dict(), chunks
end

162
src/rendering/common.jl Normal file
View File

@ -0,0 +1,162 @@
# fallback methods
# ----------------
set_format_options!(docformat::WeaveFormat; _kwargs...) = return
function restore_header!(doc)
(hasproperty(doc.format, :preserve_header) && doc.format.preserve_header) || return
# only strips Weave headers
delete!(doc.header, WEAVE_OPTION_NAME)
if haskey(doc.header, WEAVE_OPTION_NAME_DEPRECATED)
@warn "Weave: `options` key is deprecated. Use `weave_options` key instead." _id = WEAVE_OPTION_DEPRECATE_ID maxlog = 1
delete!(doc.header, WEAVE_OPTION_NAME_DEPRECATED)
end
isempty(doc.header) && return
# restore remained headers as `DocChunk`
header_text = "---\n$(YAML.write(doc.header))---"
pushfirst!(doc.chunks, DocChunk(header_text, 0, 0))
end
render_chunk(docformat::WeaveFormat, chunk::DocChunk) = join((render_inline(c) for c in chunk.content))
render_inline(inline::InlineText) = inline.content
function render_inline(inline::InlineCode)
isempty(inline.rich_output) || return inline.rich_output
isempty(inline.figures) || return inline.figures[end]
return inline.output
end
function render_chunk(docformat::WeaveFormat, chunk::CodeChunk)
# Fill undefined options with format specific defaults
isnothing(chunk.options[:out_width]) && (chunk.options[:out_width] = docformat.out_width)
isnothing(chunk.options[:fig_pos]) && (chunk.options[:fig_pos] = docformat.fig_pos)
# Only use floats if chunk has caption or sets fig_env
if !isnothing(chunk.options[:fig_cap]) && isnothing(chunk.options[:fig_env])
(chunk.options[:fig_env] = docformat.fig_env)
end
hasproperty(docformat, :indent) && (chunk.content = indent(chunk.content, docformat.indent))
chunk.content = render_code(docformat, chunk.content)
echo = chunk.options[:echo]
chunk.options[:eval] || return echo ? string(docformat.codestart, chunk.content, docformat.codeend) : ""
if chunk.options[:term]
result = render_termchunk(docformat, chunk)
else
result = if echo
# Convert to output format and highlight (html, tex...) if needed
string(docformat.codestart, chunk.content, docformat.codeend, '\n')
else
""
end
if (strip(chunk.output) "" || strip(chunk.rich_output) "") &&
(chunk.options[:results] "hidden")
if chunk.options[:results] "markup" && chunk.options[:results] "hold"
strip(chunk.output) "" && (result *= "$(chunk.output)\n")
strip(chunk.rich_output) "" && (result *= "$(chunk.rich_output)\n")
else
if chunk.options[:wrap]
chunk.output =
'\n' * wraplines(chunk.output, chunk.options[:line_width])
chunk.output = render_output(docformat, chunk.output)
else
chunk.output = '\n' * rstrip(chunk.output)
chunk.output = render_output(docformat, chunk.output)
end
hasproperty(docformat, :indent) && (chunk.output = indent(chunk.output, docformat.indent))
strip(chunk.output) "" && (
result *= "$(docformat.outputstart)$(chunk.output)\n$(docformat.outputend)\n"
)
strip(chunk.rich_output) "" && (result *= chunk.rich_output * '\n')
end
end
end
# Handle figures
if chunk.options[:fig] && length(chunk.figures) > 0
result *= render_figures(docformat, chunk)
end
return result
end
render_code(docformat::WeaveFormat, code) = code
indent(text, nindent) = join(map(x -> string(repeat(' ', nindent), x), split(text, '\n')), '\n')
function wraplines(text, line_width = 75)
result = AbstractString[]
lines = split(text, '\n')
for line in lines
if length(line) > line_width
push!(result, wrapline(line, line_width))
else
push!(result, line)
end
end
return strip(join(result, '\n'))
end
function wrapline(text, line_width = 75)
result = ""
while length(text) > line_width
result *= first(text, line_width) * '\n'
text = chop(text, head = line_width, tail = 0)
end
result *= text
end
render_output(docformat::WeaveFormat, output) = output
function render_termchunk(docformat::WeaveFormat, chunk)
return if should_render(chunk)
string(docformat.termstart, chunk.output, docformat.termend)
else
""
end
end
should_render(chunk) = chunk.options[:echo] && chunk.options[:results] "hidden"
render_doc(docformat, body, doc) = body
# utilities
# ---------
function clear_buffer_and_format!(io::IOBuffer, out::IOBuffer, render_function)
text = take2string!(io)
m = Markdown.parse(text, flavor = WeaveMarkdown.weavemd)
write(out, string(render_function(m)))
end
addlines(op, inline) = inline.ctype === :line ? string('\n', op, '\n') : op
get_mustache_template(path::AbstractString) = Mustache.template_from_file(path)
get_mustache_template(tpl::Mustache.MustacheTokens) = tpl
get_highlight_stylesheet(mime, highlight_theme) =
get_highlight_stylesheet(mime, get_highlight_theme(highlight_theme))
get_highlight_stylesheet(mime, highlight_theme::Type{<:Highlights.AbstractTheme}) =
sprint((io, x) -> Highlights.stylesheet(io, mime, x), highlight_theme)
get_highlight_theme(::Nothing) = Highlights.Themes.DefaultTheme
get_highlight_theme(highlight_theme::Type{<:Highlights.AbstractTheme}) = highlight_theme
highlight_code(mime, code, highlight_theme) =
highlight(mime, strip(code), Highlights.Lexers.JuliaLexer, highlight_theme)
highlight_term(mime, output, highlight_theme) =
highlight(mime, strip(output), Highlights.Lexers.JuliaConsoleLexer, highlight_theme)
highlight(mime, output, lexer, theme = Highlights.Themes.DefaultTheme) =
sprint((io, x) -> Highlights.highlight(io, mime, x, lexer, theme), output)

View File

@ -0,0 +1,24 @@
abstract type ExportFormat <: WeaveFormat end
function Base.getproperty(sf::T, s::Symbol) where {T<:ExportFormat}
hasfield(T, s) && return getfield(sf, s)
return getproperty(sf.primaryformat, s)
end
function Base.setproperty!(sf::T, s::Symbol, v) where {T<:ExportFormat}
if hasfield(T, s)
setfield!(sf, s, v)
else
setproperty!(sf.primaryformat, s, v)
end
end
function Base.hasproperty(sf::T, s::Symbol) where {T<:ExportFormat}
hasfield(T, s) || hasproperty(sf.primaryformat, s)
end
render_doc(df::ExportFormat, body, doc) = render_doc(df.primaryformat, body, doc)
render_chunk(df::ExportFormat, chunk) = render_chunk(df.primaryformat, chunk)
# Need to define these to avoid ambiguities
render_chunk(df::ExportFormat, chunk::DocChunk) = render_chunk(df.primaryformat, chunk)
render_chunk(df::ExportFormat, chunk::CodeChunk) = render_chunk(df.primaryformat, chunk)
render_output(df::ExportFormat, output) = render_output(df.primaryformat, output)

View File

@ -0,0 +1,146 @@
# HTML
# ----
abstract type HTMLFormat <: WeaveFormat end
render_code(docformat::HTMLFormat, code) =
highlight_code(MIME("text/html"), code, docformat.highlight_theme)
render_termchunk(docformat::HTMLFormat, chunk) =
should_render(chunk) ? highlight_term(MIME("text/html"), chunk.output, docformat.highlight_theme) : ""
# Julia markdown
# --------------
Base.@kwdef mutable struct WeaveHTML <: HTMLFormat
description = "Weave-style HTML"
extension = "html"
codestart = '\n'
codeend = '\n'
termstart = codestart
termend = codeend
outputstart = "<pre class=\"output\">"
outputend = "</pre>\n"
mimetypes = ["image/png", "image/jpg", "image/svg+xml",
"text/html", "text/markdown", "text/plain"]
fig_ext = ".png"
out_width = nothing
out_height = nothing
fig_pos = nothing
fig_env = nothing
# specials
template = nothing
stylesheet = nothing
highlight_theme = nothing
end
register_format!("md2html", WeaveHTML())
function set_format_options!(docformat::WeaveHTML; template = nothing, css = nothing, highlight_theme = nothing, _kwargs...)
template_path = isnothing(template) ? normpath(TEMPLATE_DIR, "md2html.tpl") : template
docformat.template = get_mustache_template(template_path)
stylesheet_path = isnothing(css) ? normpath(STYLESHEET_DIR, "skeleton.css") : css
docformat.stylesheet = read(stylesheet_path, String)
docformat.highlight_theme = get_highlight_theme(highlight_theme)
end
# very similar to tex version of function
function render_chunk(docformat::WeaveHTML, chunk::DocChunk)
out = IOBuffer()
io = IOBuffer()
for inline in chunk.content
if isa(inline, InlineText)
write(io, inline.content)
elseif !isempty(inline.rich_output)
clear_buffer_and_format!(io, out, WeaveMarkdown.html)
write(out, addlines(inline.rich_output, inline))
elseif !isempty(inline.figures)
write(io, inline.figures[end])
elseif !isempty(inline.output)
write(io, addlines(inline.output, inline))
end
end
clear_buffer_and_format!(io, out, WeaveMarkdown.html)
return take2string!(out)
end
render_output(docformat::WeaveHTML, output) = Markdown.htmlesc(output)
function render_figures(docformat::WeaveHTML, chunk)
fignames = chunk.figures
caption = chunk.options[:fig_cap]
width = chunk.options[:out_width]
height = chunk.options[:out_height]
f_pos = chunk.options[:fig_pos]
f_env = chunk.options[:fig_env]
result = ""
figstring = ""
# Set size
attribs = ""
isnothing(width) || (attribs = "width=\"$width\"")
(!isempty(attribs) && !isnothing(height)) && (attribs *= ",")
isnothing(height) || (attribs *= " height=\"$height\" ")
if !isnothing(caption)
result *= """<figure>\n"""
end
for fig in fignames
figstring *= """<img src="$fig" $attribs />\n"""
end
result *= figstring
if !isnothing(caption)
result *= """
<figcaption>$caption</figcaption>
"""
end
if !isnothing(caption)
result *= "</figure>\n"
end
return result
end
function render_doc(docformat::WeaveHTML, body, doc; css = nothing)
_, weave_source = splitdir(abspath(doc.source))
weave_version, weave_date = weave_info()
return Mustache.render(
docformat.template;
body = body,
stylesheet = docformat.stylesheet,
highlight_stylesheet = get_highlight_stylesheet(MIME("text/html"), docformat.highlight_theme),
header_script = doc.header_script,
weave_source = weave_source,
weave_version = weave_version,
weave_date = weave_date,
[Pair(Symbol(k), v) for (k, v) in doc.header]...,
)
end
# Pandoc
# ------
Base.@kwdef mutable struct Pandoc2HTML <: ExportFormat
description = "HTML via intermediate Pandoc Markdown (requires Pandoc 2)"
primaryformat = Pandoc()
template_path = nothing
stylesheet_path = nothing
highlight_theme = nothing
pandoc_options = String[]
end
register_format!("pandoc2html", Pandoc2HTML())
function set_format_options!(docformat::Pandoc2HTML; template = nothing, css = nothing, highlight_theme = nothing, pandoc_options = String[], _kwargs...)
docformat.template_path =
isnothing(template) ? normpath(TEMPLATE_DIR, "pandoc2html.html") : template
docformat.stylesheet_path =
isnothing(css) ? normpath(STYLESHEET_DIR, "pandoc2html_skeleton.css") : css
docformat.highlight_theme = get_highlight_theme(highlight_theme)
docformat.pandoc_options = pandoc_options
end
render_figures(docformat::Pandoc2HTML, chunk) = render_figures(Pandoc(), chunk)

View File

@ -0,0 +1,224 @@
# GitHub markdown
# ---------------
Base.@kwdef mutable struct GitHubMarkdown <: WeaveFormat
description = "GitHub Markdown"
extension = "md"
codestart = "```julia"
codeend = "```\n"
termstart = codestart
termend = codeend
outputstart = "```"
outputend = "```\n\n"
fig_ext = ".png"
mimetypes = ["image/png", "image/svg+xml", "image/jpg",
"text/markdown", "text/plain"]
out_width = nothing
out_height = nothing
fig_pos = nothing
fig_env = nothing
# specials
preserve_header = true
end
register_format!("github", GitHubMarkdown())
function render_figures(docformat::GitHubMarkdown, chunk)
fignames = chunk.figures
caption = chunk.options[:fig_cap]
result = ""
figstring = ""
length(fignames) > 0 || (return "")
if !isnothing(caption)
result *= "![$caption]($(fignames[1]))\n"
for fig in fignames[2:end]
result *= "![]($fig)\n"
println("Warning, only the first figure gets a caption\n")
end
else
for fig in fignames
result *= "![]($fig)\n"
end
end
return result
end
# Hugo markdown
# -------------
Base.@kwdef mutable struct Hugo <: WeaveFormat
description = "Hugo Markdown (using shortcodes)"
extension = "md"
codestart = "```julia"
codeend = "```\n"
termstart = codestart
termend = codeend
outputstart = "```"
outputend = "```\n\n"
mimetypes = default_mime_types
fig_ext = ".png"
out_width = nothing
out_height = nothing
fig_pos = nothing
fig_env = nothing
# specials
preserve_header = true
uglyURLs = false # if `false`, prepend figure path by `..`
end
register_format!("hugo", Hugo())
function render_figures(docformat::Hugo, chunk)
relpath = docformat.uglyURLs ? "" : ".."
mapreduce(*, enumerate(chunk.figures), init = "") do (index, fig)
if index > 1
@warn("Only the first figure gets a caption.")
title_spec = ""
else
caption = chunk.options[:fig_cap]
title_spec = isnothing(caption) ? "" : "title=\"$(caption)\" "
end
"{{< figure src=\"$(joinpath(relpath, fig))\" $(title_spec) >}}"
end
end
# multi language markdown
# -----------------------
Base.@kwdef mutable struct MultiMarkdown <: WeaveFormat
description = "MultiMarkdown"
extension = "md"
codestart = "```julia"
codeend = "```\n"
termstart = codestart
termend = codeend
outputstart = "```"
outputend = "```\n\n"
mimetypes = default_mime_types
fig_ext = ".png"
out_width = nothing
out_height = nothing
fig_pos = nothing
fig_env = nothing
# specials
preserve_header = true
end
register_format!("multimarkdown", MultiMarkdown())
function render_figures(docformat::MultiMarkdown, chunk)
fignames = chunk.figures
caption = chunk.options[:fig_cap]
result = ""
figstring = ""
if chunk.options[:out_width] == nothing
width = ""
else
width = "width=$(chunk.options[:out_width])"
end
length(fignames) > 0 || (return "")
if !isnothing(caption)
result *= "![$caption][$(fignames[1])]\n\n"
result *= "[$(fignames[1])]: $(fignames[1]) $width\n"
for fig in fignames[2:end]
result *= "![][$fig]\n\n"
result *= "[$fig]: $fig $width\n"
println("Warning, only the first figure gets a caption\n")
end
else
for fig in fignames
result *= "![][$fig]\n\n"
result *= "[$fig]: $fig $width\n"
end
end
return result
end
# Rest
# ----
Base.@kwdef mutable struct Rest <: WeaveFormat
description = "reStructuredText and Sphinx"
extension = "rst"
codestart = ".. code-block:: julia\n"
codeend = "\n"
termstart = codestart
termend = codeend
outputstart = "::\n"
outputend = "\n\n"
mimetypes = default_mime_types
fig_ext = ".png"
out_width = "15 cm"
out_height = nothing
fig_pos = nothing
fig_env = nothing
# specials
indent = 4
end
register_format!("rst", Rest())
function render_figures(docformat::Rest, chunk)
fignames = chunk.figures
caption = chunk.options[:fig_cap]
width = chunk.options[:out_width]
result = ""
figstring = ""
for fig in fignames
figstring *= @sprintf(".. image:: %s\n :width: %s\n\n", fig, width)
end
if !isnothing(caption)
result *= string(
".. figure:: $(fignames[1])\n",
" :width: $width\n\n",
" $caption\n\n",
)
else
result *= figstring
return result
end
end
# Ansii
# -----
# asciidoc -b html5 -a source-highlighter=pygments ...
Base.@kwdef mutable struct AsciiDoc <: WeaveFormat
description = "AsciiDoc"
extension = "txt"
codestart = "[source,julia]\n--------------------------------------"
codeend = "--------------------------------------\n"
termstart = codestart
termend = codeend
outputstart = "--------------------------------------"
outputend = "--------------------------------------\n\n"
mimetypes = default_mime_types
fig_ext = ".png"
out_width = "600"
out_height = nothing
fig_pos = nothing
fig_env = nothing
end
register_format!("asciidoc", AsciiDoc())
function render_figures(docformat::AsciiDoc, chunk)
fignames = chunk.figures
caption = chunk.options[:fig_cap]
width = chunk.options[:out_width]
result = ""
figstring = ""
for fig in fignames
figstring *= @sprintf("image::%s[width=%s]\n", fig, width)
end
if !isnothing(caption)
result *= string("image::$(fignames[1])", "[width=$width,", "title=\"$caption\"]")
else
result *= figstring
return result
end
end

View File

@ -0,0 +1,70 @@
abstract type PandocFormat <: WeaveFormat end
function render_figures(docformat::PandocFormat, chunk)
fignames = chunk.figures
length(fignames) > 0 || (return "")
caption = chunk.options[:fig_cap]
label = get(chunk.options, :label, nothing)
result = ""
figstring = ""
attribs = ""
width = chunk.options[:out_width]
height = chunk.options[:out_height]
# Build figure attibutes
attribs = String[]
isnothing(width) || push!(attribs, "width=$width")
isnothing(height) || push!(attribs, "height=$height")
isnothing(label) || push!(attribs, "#fig:$label")
attribs = isempty(attribs) ? "" : "{" * join(attribs, " ") * "}"
if !isnothing(caption)
result *= "![$caption]($(fignames[1]))$attribs\n"
for fig in fignames[2:end]
result *= "![]($fig)$attribs\n"
println("Warning, only the first figure gets a caption\n")
end
else
for fig in fignames
result *= "![]($fig)$attribs\\ \n\n"
end
end
return result
end
Base.@kwdef mutable struct Pandoc <: PandocFormat
description = "Pandoc Markdown"
extension = "md"
codestart = "~~~~{.julia}"
codeend = "~~~~~~~~~~~~~\n"
termstart = codestart
termend = codeend
outputstart = "~~~~"
outputend = "~~~~\n\n"
# Prefer png figures for markdown conversion, svg doesn't work with latex
mimetypes = ["image/png", "image/jpg", "image/svg+xml", "text/markdown", "text/plain"]
fig_ext = ".png"
out_width = nothing
out_height = nothing
fig_pos = nothing
fig_env = nothing
# specials
preserve_header = true
end
register_format!("pandoc", Pandoc())
const DEFAULT_PANDOC_OPTIONS = String[]
Base.@kwdef mutable struct Pandoc2PDF <: ExportFormat
description = "PDF via intermediate Pandoc Markdown"
primaryformat = Pandoc()
pandoc_options = DEFAULT_PANDOC_OPTIONS
header_template = normpath(TEMPLATE_DIR, "pandoc2pdf_header.txt")
end
register_format!("pandoc2pdf", Pandoc2PDF())
function set_format_options!(docformat::Pandoc2PDF; pandoc_options = DEFAULT_PANDOC_OPTIONS, _kwargs...)
docformat.pandoc_options = pandoc_options
end

View File

@ -0,0 +1,31 @@
# TODO:
# - 1. Improve argument handling
# - 2. Update code to use UnPack.jl to make it more readable
# - 3. Export new interface
# - 4. Document Interface
using Mustache, Highlights, .WeaveMarkdown, Markdown, Dates, Printf
const FORMATS = Dict{String,WeaveFormat}()
# TODO: do some assertion for necessary fields of `format`
register_format!(format_name::AbstractString, format::WeaveFormat) = push!(FORMATS, format_name => format)
register_format!(_, format) = error("Format needs to be a subtype of WeaveFormat.")
set_format_options!(doc; kwargs...) = set_format_options!(doc.format; kwargs...)
function render_doc(doc::WeaveDoc)
restore_header!(doc)
docformat = doc.format
body = joinlines(render_chunk.(Ref(docformat), copy(doc.chunks)))
return render_doc(docformat, body, doc)
end
include("exportformat.jl")
include("common.jl")
include("pandocformats.jl")
include("htmlformats.jl")
include("texformats.jl")
include("miscformats.jl")

264
src/rendering/texformats.jl Normal file
View File

@ -0,0 +1,264 @@
# Tex
# ---
abstract type LaTeXFormat <: WeaveFormat end
function set_format_options!(docformat::LaTeXFormat; keep_unicode = false, template = nothing, _kwargs...)
docformat.keep_unicode |= keep_unicode
docformat.template =
get_mustache_template(isnothing(template) ? normpath(TEMPLATE_DIR, "md2pdf.tpl") : template)
end
# very similar to export to html
function render_chunk(docformat::LaTeXFormat, chunk::DocChunk)
out = IOBuffer()
io = IOBuffer()
for inline in chunk.content
if isa(inline, InlineText)
write(io, inline.content)
elseif !isempty(inline.rich_output)
clear_buffer_and_format!(io, out, WeaveMarkdown.latex)
write(out, addlines(inline.rich_output, inline))
elseif !isempty(inline.figures)
write(io, inline.figures[end], inline)
elseif !isempty(inline.output)
write(io, addlines(inline.output, inline))
end
end
clear_buffer_and_format!(io, out, WeaveMarkdown.latex)
out = take2string!(out)
return unicode2latex(docformat, out)
end
render_output(docformat::LaTeXFormat, output) = unicode2latex(docformat, output, true)
render_code(docformat::LaTeXFormat, code) = unicode2latex(docformat, code, true)
render_termchunk(docformat::LaTeXFormat, chunk) =
string(docformat.termstart,
unicode2latex(docformat, chunk.output, true),
docformat.termend, "\n")
# from julia symbols (e.g. "\bfhoge") to valid latex
const UNICODE2LATEX = let
function texify(s)
return if occursin(r"^\\bf[A-Z]$", s)
replace(s, "\\bf" => "\\bm{\\mathrm{") * "}}"
elseif startswith(s, "\\bfrak")
replace(s, "\\bfrak" => "\\bm{\\mathfrak{") * "}}"
elseif startswith(s, "\\bf")
replace(s, "\\bf" => "\\bm{\\") * "}"
elseif startswith(s, "\\frak")
replace(s, "\\frak" => "\\mathfrak{") * "}"
else
s
end
end
Dict(unicode => texify(sym) for (sym, unicode) in REPL.REPLCompletions.latex_symbols)
end
function unicode2latex(docformat::LaTeXFormat, s, escape = false)
# Check whether to convert at all and return input if not
docformat.keep_unicode && return s
for (unicode, latex) in UNICODE2LATEX
body = "\\ensuremath{$(latex)}"
target = escape ? string(docformat.escape_starter, body, docformat.escape_closer) : body
s = replace(s, unicode => target)
end
return s
end
function render_figures(docformat::LaTeXFormat, chunk)
fignames = chunk.figures
caption = chunk.options[:fig_cap]
width = chunk.options[:out_width]
height = chunk.options[:out_height]
f_pos = chunk.options[:fig_pos]
f_env = chunk.options[:fig_env]
result = ""
figstring = ""
if isnothing(f_env) && !isnothing(caption)
f_env = "figure"
end
(isnothing(f_pos)) && (f_pos = "!h")
# Set size
attribs = ""
isnothing(width) || (attribs = "width=$(md_length_to_latex(width,"\\linewidth"))")
(!isempty(attribs) && !isnothing(height)) && (attribs *= ",")
isnothing(height) || (attribs *= "height=$(md_length_to_latex(height,"\\paperheight"))")
if !isnothing(f_env)
result *= "\\begin{$f_env}"
(!isempty(f_pos)) && (result *= "[$f_pos]")
result *= "\n"
end
for fig in fignames
if splitext(fig)[2] == ".tex" # Tikz figures
figstring *= "\\resizebox{$width}{!}{\\input{$fig}}\n"
else
if isempty(attribs)
figstring *= "\\includegraphics{$fig}\n"
else
figstring *= "\\includegraphics[$attribs]{$fig}\n"
end
end
end
# Figure environment
if !isnothing(caption)
result *= string("\\center\n", "$figstring", "\\caption{$caption}\n")
else
result *= figstring
end
if !isnothing(chunk.options[:label]) && !isnothing(f_env)
label = chunk.options[:label]
result *= "\\label{fig:$label}\n"
end
if !isnothing(f_env)
result *= "\\end{$f_env}\n"
end
return result
end
function md_length_to_latex(def, reference)
if occursin("%", def)
_def = tryparse(Float64, replace(def, "%" => ""))
isnothing(_def) && return def
perc = round(_def / 100, digits = 2)
return "$perc$reference"
end
return def
end
function render_doc(docformat::LaTeXFormat, body, doc)
return Mustache.render(
docformat.template;
body = body,
highlight = "",
tex_deps = docformat.tex_deps,
[Pair(Symbol(k), v) for (k, v) in doc.header]...,
)
end
# minted Tex
# ----------
Base.@kwdef mutable struct LaTeXMinted <: LaTeXFormat
description = "LaTeX using minted package for code highlighting"
extension = "tex"
codestart = "\\begin{minted}[texcomments = true, mathescape, fontsize=\\small, xleftmargin=0.5em]{julia}"
codeend = "\\end{minted}"
termstart = "\\begin{minted}[texcomments = true, mathescape, fontsize=\\footnotesize, xleftmargin=0.5em]{jlcon}"
termend = "\\end{minted}"
outputstart = "\\begin{minted}[texcomments = true, mathescape, fontsize=\\small, xleftmargin=0.5em, frame = leftline]{text}"
outputend = "\\end{minted}"
mimetypes = ["application/pdf", "image/png", "text/latex", "text/plain"]
fig_ext = ".pdf"
out_width = "\\linewidth"
out_height = nothing
fig_pos = "htpb"
fig_env = "figure"
# specials
keep_unicode = false
template = nothing
tex_deps = "\\usepackage{minted}"
# how to escape latex in verbatim/code environment
escape_starter = "|\$"
escape_closer = reverse(escape_starter)
end
register_format!("texminted", LaTeXMinted())
# Tex (directly to PDF)
# ---------------------
abstract type WeaveLaTeXFormat <: LaTeXFormat end
function set_format_options!(docformat::WeaveLaTeXFormat; template = nothing, highlight_theme = nothing, keep_unicode = false, _kwargs...)
docformat.template =
get_mustache_template(isnothing(template) ? normpath(TEMPLATE_DIR, "md2pdf.tpl") : template)
docformat.highlight_theme = get_highlight_theme(highlight_theme)
docformat.keep_unicode |= keep_unicode
end
function render_output(docformat::WeaveLaTeXFormat, output)
# Highligts has some extra escaping defined, eg of $, ", ...
output_escaped = sprint(
(io, x) ->
Highlights.Format.escape(io, MIME("text/latex"), x, charescape = true),
output,
)
return unicode2latex(docformat, output_escaped, true)
end
function render_code(docformat::WeaveLaTeXFormat, code)
ret = highlight_code(MIME("text/latex"), code, docformat.highlight_theme)
unicode2latex(docformat, ret, false)
end
function render_termchunk(docformat::WeaveLaTeXFormat, chunk)
if should_render(chunk)
ret = highlight_term(MIME("text/latex"), chunk.output, docformat.highlight_theme)
unicode2latex(docformat, ret, true)
else
""
end
end
function render_doc(docformat::WeaveLaTeXFormat, body, doc)
return Mustache.render(
docformat.template;
body = body,
highlight = get_highlight_stylesheet(MIME("text/latex"), docformat.highlight_theme),
tex_deps = docformat.tex_deps,
[Pair(Symbol(k), v) for (k, v) in doc.header]...,
)
end
Base.@kwdef mutable struct WeaveLaTeX <: WeaveLaTeXFormat
description = "Weave-styled LaTeX"
extension = "tex"
codestart = ""
codeend = ""
termstart = codestart
termend = codeend
outputstart = "\\begin{lstlisting}"
outputend = "\\end{lstlisting}\n"
mimetypes = ["application/pdf", "image/png", "image/jpg", "text/latex", "text/markdown", "text/plain"]
fig_ext = ".pdf"
out_width = "\\linewidth"
out_height = nothing
fig_pos = nothing
fig_env = nothing
# specials
highlight_theme = nothing
template = nothing
keep_unicode = false
tex_deps = ""
# how to escape latex in verbatim/code environment
escape_starter = "(*@"
escape_closer = "@*)"
end
register_format!("md2tex", WeaveLaTeX())
# will be used by `write_doc`
const DEFAULT_LATEX_CMD = ["xelatex", "-shell-escape", "-halt-on-error"]
Base.@kwdef mutable struct LaTeX2PDF <: ExportFormat
primaryformat = WeaveLaTeX()
description = "PDF via LaTeX"
latex_cmd = DEFAULT_LATEX_CMD
end
register_format!("md2pdf", LaTeX2PDF())
register_format!("minted2pdf", LaTeX2PDF(primaryformat=LaTeXMinted()))
function set_format_options!(docformat::LaTeX2PDF; latex_cmd = DEFAULT_LATEX_CMD, _kwargs...)
docformat.latex_cmd = latex_cmd
set_format_options!(docformat.primaryformat; _kwargs...)
end

View File

@ -3,71 +3,49 @@ using Base64
const PROGRESS_ID = "weave_progress"
"""
run_doc(doc::WeaveDoc; kwargs...)
Run code chunks and capture output from the parsed document.
## Keyword options
- `doctype::Union{Nothing,AbstractString} = nothing`: Output document format. By default (i.e. given `nothing`), Weave will set it automatically based on file extension. You can also manually specify it; see [`list_out_formats()`](@ref) for the supported formats
- `out_path::Union{Symbol,AbstractString} = :doc`: Path where the output is generated can be either of:
* `:doc`: Path of the source document (default)
* `:pwd`: Julia working directory
* `"somepath"`: `String` of output directory e.g. `"~/outdir"`, or of filename e.g. `"~/outdir/outfile.tex"`
- `args::Dict = Dict()`: Arguments to be passed to the weaved document; will be available as `WEAVE_ARGS` in the document
- `mod::Union{Module,Nothing} = nothing`: Module where Weave `eval`s code. You can pass a `Module` object, otherwise create an new sandbox module.
- `fig_path::AbstractString = "figures"`: Where figures will be generated, relative to `out_path`
- `fig_ext::Union{Nothing,AbstractString} = nothing`: Extension for saved figures e.g. `".pdf"`, `".png"`. Default setting depends on `doctype`
- `cache_path::AbstractString = "cache"`: Where of cached output will be saved
- `cache::Symbol = :off`: Controls caching of code:
* `:off` means no caching (default)
* `:all` caches everything
* `:user` caches based on chunk options
* `:refresh` runs all code chunks and save new cache
- `throw_errors::Bool = false`: If `false` errors are included in output document and the whole document is executed. If `true` errors are thrown when they occur
!!! note
Run Weave from terminal and try to avoid weaving from IJulia or ESS; they tend to mess with capturing output.
"""
function run_doc(
doc::WeaveDoc;
doctype::Union{Nothing,AbstractString} = nothing,
out_path::Union{Symbol,AbstractString} = :doc,
args::Dict = Dict(),
args::Any = Dict(),
mod::Union{Module,Nothing} = nothing,
fig_path::AbstractString = "figures",
fig_path::Union{Nothing,AbstractString} = nothing,
fig_ext::Union{Nothing,AbstractString} = nothing,
cache_path::AbstractString = "cache",
cache::Symbol = :off,
throw_errors::Bool = false,
)
# cache :all, :user, :off, :refresh
doc.doctype = isnothing(doctype) ? (doctype = detect_doctype(doc.source)) : doctype
doc.format = deepcopy(formats[doctype])
doc.format = deepcopy(get_format(doctype))
doc.cwd = get_cwd(doc, out_path)
isdir(doc.cwd) || mkpath(doc.cwd)
if (occursin("2pdf", doctype) && cache == :off) || occursin("2html", doctype)
fig_path = mktempdir(abspath(doc.cwd))
cwd = doc.cwd = get_cwd(doc, out_path)
mkpath(cwd)
# TODO: provide a way not to create `fig_path` ?
if isnothing(fig_path)
fig_path = if (endswith(doctype, "2pdf") && cache === :off) || endswith(doctype, "2html")
basename(mktempdir(abspath(cwd)))
else
DEFAULT_FIG_PATH
end
end
mkpath(normpath(cwd, fig_path))
# This is needed for latex and should work on all output formats
@static Sys.iswindows() && (fig_path = replace(fig_path, "\\" => "/"))
set_rc_params(doc, fig_path, fig_ext)
cache === :off || @eval import Serialization # XXX: evaluate in a more sensible module
# This is needed for latex and should work on all output formats
@static Sys.iswindows() && (fig_path = replace(fig_path, "\\" => "/"))
doc.fig_path = fig_path
set_rc_params(doc, fig_path, fig_ext)
# New sandbox for each document with args exposed
isnothing(mod) && (mod = sandbox = Core.eval(Main, :(module $(gensym(:WeaveSandBox)) end))::Module)
@eval mod WEAVE_ARGS = $args
Core.eval(mod, :(WEAVE_ARGS = $(args)))
mimetypes = get(doc.format.formatdict, :mimetypes, default_mime_types)
mimetypes = doc.format.mimetypes
report = Report(doc.cwd, doc.basename, doc.format.formatdict, mimetypes, throw_errors)
report = Report(cwd, doc.basename, doc.format, mimetypes)
cd_back = let d = pwd(); () -> cd(d); end
cd(cwd)
pushdisplay(report)
try
if cache !== :off && cache !== :refresh
@ -110,7 +88,10 @@ function run_doc(
rethrow(err)
finally
@info "Weaved all chunks" progress=1 _id=PROGRESS_ID
cd_back()
popdisplay(report) # ensure display pops out even if internal error occurs
# Temporary fig_path is not automatically removed because it contains files so...
!isnothing(fig_path) && startswith(fig_path, "jl_") && rm(normpath(cwd, fig_path), force=true, recursive=true)
end
return doc
@ -135,9 +116,24 @@ function detect_doctype(path)
return "pandoc"
end
function get_cwd(doc, out_path)
return if out_path === :doc
dirname(doc.path)
elseif out_path === :pwd
pwd()
else
path, ext = splitext(out_path)
if isempty(ext) # directory given
path
else # file given
dirname(path)
end
end |> abspath
end
function run_chunk(chunk::CodeChunk, doc, report, mod)
result = eval_chunk(chunk, report, mod)
occursin("2html", report.formatdict[:doctype]) && (embed_figures!(result, report.cwd))
result = eval_chunk(doc, chunk, report, mod)
occursin("2html", doc.doctype) && (embed_figures!(result, report.cwd))
return result
end
@ -146,27 +142,17 @@ function embed_figures!(chunk::CodeChunk, cwd)
chunk.figures[i] = img2base64(fig, cwd)
end
end
function embed_figures!(chunks::Vector{CodeChunk}, cwd)
for chunk in chunks
embed_figures!(chunk, cwd)
end
end
embed_figures!(chunks, cwd) = embed_figures!.(chunks, Ref(cwd))
function img2base64(fig, cwd)
ext = splitext(fig)[2]
f = open(joinpath(cwd, fig), "r")
raw = read(f)
close(f)
if ext == ".png"
return "data:image/png;base64," * stringmime(MIME("image/png"), raw)
elseif ext == ".svg"
return "data:image/svg+xml;base64," * stringmime(MIME("image/svg"), raw)
elseif ext == ".gif"
return "data:image/gif;base64," * stringmime(MIME("image/gif"), raw)
else
return (fig)
end
return ext == ".png" ? "data:image/png;base64," * stringmime(MIME("image/png"), raw) :
ext == ".svg" ? "data:image/svg+xml;base64," * stringmime(MIME("image/svg"), raw) :
ext == ".gif" ? "data:image/gif;base64," * stringmime(MIME("image/gif"), raw) :
fig
end
function run_chunk(chunk::DocChunk, doc, report, mod)
@ -174,7 +160,7 @@ function run_chunk(chunk::DocChunk, doc, report, mod)
return chunk
end
run_inline(inline::InlineText, doc::WeaveDoc, report::Report, SandBox::Module) = inline
run_inline(inline::InlineText, ::WeaveDoc, ::Report, ::Module) = inline
const INLINE_OPTIONS = Dict(
:term => false,
@ -182,14 +168,14 @@ const INLINE_OPTIONS = Dict(
:wrap => false
)
function run_inline(inline::InlineCode, doc::WeaveDoc, report::Report, SandBox::Module)
function run_inline(inline::InlineCode, doc::WeaveDoc, report::Report, mod::Module)
# Make a temporary CodeChunk for running code. Collect results and don't wrap
chunk = CodeChunk(inline.content, 0, 0, "", INLINE_OPTIONS)
options = merge(doc.chunk_defaults, chunk.options)
merge!(chunk.options, options)
chunks = eval_chunk(chunk, report, SandBox)
occursin("2html", report.formatdict[:doctype]) && (embed_figures!(chunks, report.cwd))
chunks = eval_chunk(doc, chunk, report, mod)
occursin("2html", doc.doctype) && (embed_figures!(chunks, report.cwd))
output = chunks[1].output
endswith(output, "\n") && (output = output[1:end-1])
@ -199,115 +185,117 @@ function run_inline(inline::InlineCode, doc::WeaveDoc, report::Report, SandBox::
return inline
end
function reset_report(report::Report)
report.cur_result = ""
report.figures = AbstractString[]
report.term_state = :text
function run_code(doc::WeaveDoc, chunk::CodeChunk, report::Report, mod::Module)
code = chunk.content
path = doc.path
error = chunk.options[:error]
codes = chunk.options[:term] ? split_code(code) : [code]
capture = code -> capture_output(code, mod, path, error, report)
return capture.(codes)
end
function run_code(chunk::CodeChunk, report::Report, SandBox::Module)
expressions = parse_input(chunk.content)
N = length(expressions)
# @show expressions
result_no = 1
results = ChunkOutput[]
for (str_expr, expr) in expressions
reset_report(report)
lastline = (result_no == N)
(obj, out) = capture_output(
expr,
SandBox,
chunk.options[:term],
chunk.options[:display],
lastline,
report.throw_errors,
)
figures = report.figures # Captured figures
result = ChunkOutput(str_expr, out, report.cur_result, report.rich_output, figures)
report.rich_output = ""
push!(results, result)
result_no += 1
end
return results
end
# TODO: run in document source path
function capture_output(expr, SandBox::Module, term, disp, lastline, throw_errors = false)
out = nothing
obj = nothing
old = stdout
rw, wr = redirect_stdout()
reader = @async read(rw, String)
try
obj = Core.eval(SandBox, expr)
!isnothing(obj) && ((term || disp) || lastline) && display(obj)
catch err
throw_errors && throw(err)
display(err)
@warn "ERROR: $(typeof(err)) occurred, including output in Weaved document"
finally
redirect_stdout(old)
close(wr)
out = fetch(reader)
close(rw)
end
out = replace(out, r"\u001b\[.*?m" => "") # remove ANSI color codes
return (obj, out)
end
# Parse chunk input to array of expressions
function parse_input(s)
res = []
s = lstrip(s)
n = sizeof(s)
pos = 1 # The first character is extra line end
while (oldpos = pos) n
ex, pos = Meta.parse(s, pos)
push!(res, (s[oldpos:pos-1], ex))
function split_code(code)
res = String[]
e = 1
ex = :init
while true
s = e
ex, e = Meta.parse(code, s)
isnothing(ex) && break
push!(res, strip(code[s:e-1]))
end
return res
end
function eval_chunk(chunk::CodeChunk, report::Report, SandBox::Module)
function capture_output(code, mod, path, error, report)
reset_report!(report)
old = stdout
rw, wr = redirect_stdout()
reader = @async read(rw, String)
local out = nothing
task_local_storage(:SOURCE_PATH, path) do
try
obj = include_string(mod, code, path) # TODO: fix line number
!isnothing(obj) && !REPL.ends_with_semicolon(code) && display(obj)
catch _err
err = unwrap_load_err(_err)
error || throw(err)
display(err)
@warn "ERROR: $(typeof(err)) occurred, including output in Weaved document"
finally
redirect_stdout(old)
close(wr)
out = fetch(reader)
close(rw)
end
end
return ChunkOutput(code, remove_ansi_control_chars(out), report.rich_output, report.figures)
end
function reset_report!(report)
report.rich_output = ""
report.figures = String[]
end
unwrap_load_err(err) = return err
unwrap_load_err(err::LoadError) = return err.error
# https://stackoverflow.com/a/33925425/12113178
remove_ansi_control_chars(s) = replace(s, r"(\x9B|\x1B\[)[0-?]*[ -\/]*[@-~]" => "")
function eval_chunk(doc::WeaveDoc, chunk::CodeChunk, report::Report, mod::Module)
if !chunk.options[:eval]
chunk.output = ""
chunk.options[:fig] = false
return chunk
end
# Run preexecute_hooks
for hook in preexecute_hooks
chunk = Base.invokelatest(hook, chunk)
end
execute_prehooks!(chunk)
report.fignum = 1
report.cur_chunk = chunk
if haskey(report.formatdict, :out_width) && isnothing(chunk.options[:out_width])
chunk.options[:out_width] = report.formatdict[:out_width]
if hasproperty(report.format, :out_width) && isnothing(chunk.options[:out_width])
chunk.options[:out_width] = report.format.out_width
end
chunk.result = run_code(chunk, report, SandBox)
chunk.result = run_code(doc, chunk, report, mod)
# Run post_execute chunks
for hook in postexecute_hooks
chunk = Base.invokelatest(hook, chunk)
execute_posthooks!(chunk)
return chunk.options[:term] ? collect_term_results(chunk) :
chunk.options[:hold] ? collect_hold_results(chunk) :
collect_results(chunk)
end
# Hooks to run before and after chunks, this is form IJulia,
const preexecution_hooks = Function[]
push_preexecution_hook!(f::Function) = push!(preexecution_hooks, f)
function pop_preexecution_hook!(f::Function)
i = findfirst(x -> x == f, preexecution_hooks)
isnothing(i) && error("this function has not been registered in the pre-execution hook yet")
return splice!(preexecution_hooks, i)
end
function execute_prehooks!(chunk::CodeChunk)
for prehook in preexecution_hooks
Base.invokelatest(prehook, chunk)
end
end
if chunk.options[:term]
chunks = collect_results(chunk, TermResult())
elseif chunk.options[:hold]
chunks = collect_results(chunk, CollectResult())
else
chunks = collect_results(chunk, ScriptResult())
const postexecution_hooks = Function[]
push_postexecution_hook!(f::Function) = push!(postexecution_hooks, f)
function pop_postexecution_hook!(f::Function)
i = findfirst(x -> x == f, postexecution_hooks)
isnothing(i) && error("this function has not been registered in the post-execution hook yet")
return splice!(postexecution_hooks, i)
end
function execute_posthooks!(chunk::CodeChunk)
for posthook in postexecution_hooks
Base.invokelatest(posthook, chunk)
end
# else
# chunk.options[:fig] && (chunk.figures = copy(report.figures))
# end
return chunks
end
"""
@ -336,77 +324,28 @@ function clear_module!(mod::Module)
end
function get_figname(report::Report, chunk; fignum = nothing, ext = nothing)
figpath = joinpath(report.cwd, chunk.options[:fig_path])
isdir(figpath) || mkpath(figpath)
isnothing(ext) && (ext = chunk.options[:fig_ext])
isnothing(fignum) && (fignum = report.fignum)
chunkid = isnothing(chunk.options[:label]) ? chunk.number : chunk.options[:label]
full_name = joinpath(
report.cwd,
chunk.options[:fig_path],
"$(report.basename)_$(chunkid)_$(fignum)$ext",
)
rel_name = "$(chunk.options[:fig_path])/$(report.basename)_$(chunkid)_$(fignum)$ext" # Relative path is used in output
basename = string(report.basename, '_', chunkid, '_', fignum, ext)
full_name = normpath(report.cwd, chunk.options[:fig_path], basename)
rel_name = string(chunk.options[:fig_path], '/', basename) # Relative path is used in output
return full_name, rel_name
end
function get_cwd(doc::WeaveDoc, out_path)
# Set the output directory
if out_path == :doc
cwd = doc.path
elseif out_path == :pwd
cwd = pwd()
else
# If there is no extension, use as path
splitted = splitext(out_path)
if splitted[2] == ""
cwd = expanduser(out_path)
else
cwd = splitdir(expanduser(out_path))[1]
end
end
return cwd
end
"""Get output file name based on out_path"""
function get_outname(out_path::Symbol, doc::WeaveDoc; ext = nothing)
isnothing(ext) && (ext = doc.format.formatdict[:extension])
outname = "$(doc.cwd)/$(doc.basename).$ext"
end
"""Get output file name based on out_path"""
function get_outname(out_path::AbstractString, doc::WeaveDoc; ext = nothing)
isnothing(ext) && (ext = doc.format.formatdict[:extension])
splitted = splitext(out_path)
if (splitted[2]) == ""
outname = "$(doc.cwd)/$(doc.basename).$ext"
else
outname = expanduser(out_path)
end
end
function set_rc_params(doc::WeaveDoc, fig_path, fig_ext)
formatdict = doc.format.formatdict
if isnothing(fig_ext)
doc.chunk_defaults[:fig_ext] = formatdict[:fig_ext]
else
doc.chunk_defaults[:fig_ext] = fig_ext
end
doc.chunk_defaults[:fig_ext] = isnothing(fig_ext) ? doc.format.fig_ext : fig_ext
doc.chunk_defaults[:fig_path] = fig_path
return nothing
end
function collect_results(chunk::CodeChunk, fmt::ScriptResult)
function collect_results(chunk::CodeChunk)
content = ""
result_no = 1
result_chunks = CodeChunk[]
for r in chunk.result
content *= r.code
# Check if there is any output from chunk
if strip(r.stdout) == "" && isempty(r.figures) && strip(r.rich_output) == ""
content *= r.code
else
content = "\n" * content * r.code
if any(!isempty strip, (r.stdout, r.rich_output)) || !isempty(r.figures)
rchunk = CodeChunk(
content,
chunk.number,
@ -414,17 +353,14 @@ function collect_results(chunk::CodeChunk, fmt::ScriptResult)
chunk.optionstring,
copy(chunk.options),
)
content = ""
rchunk.result_no = result_no
result_no *= 1
rchunk.figures = r.figures
rchunk.output = r.stdout * r.displayed
rchunk.output = r.stdout
rchunk.rich_output = r.rich_output
rchunk.figures = r.figures
push!(result_chunks, rchunk)
content = ""
end
end
if content != ""
startswith(content, "\n") || (content = "\n" * content)
if !isempty(content)
rchunk = CodeChunk(
content,
chunk.number,
@ -438,14 +374,12 @@ function collect_results(chunk::CodeChunk, fmt::ScriptResult)
return result_chunks
end
function collect_results(chunk::CodeChunk, fmt::TermResult)
function collect_term_results(chunk::CodeChunk)
output = ""
prompt = chunk.options[:prompt]
result_no = 1
result_chunks = CodeChunk[]
for r in chunk.result
output *= prompt * r.code
output *= r.displayed * r.stdout
output *= string('\n', indent_term_code(prompt, r.code), '\n', r.stdout)
if !isempty(r.figures)
rchunk = CodeChunk(
"",
@ -460,7 +394,7 @@ function collect_results(chunk::CodeChunk, fmt::TermResult)
push!(result_chunks, rchunk)
end
end
if output != ""
if !isempty(output)
rchunk = CodeChunk(
"",
chunk.number,
@ -475,8 +409,16 @@ function collect_results(chunk::CodeChunk, fmt::TermResult)
return result_chunks
end
function collect_results(chunk::CodeChunk, fmt::CollectResult)
result_no = 1
function indent_term_code(prompt, code)
prompt_with_space = string(prompt, ' ')
n = length(prompt_with_space)
pads = ' ' ^ n
return map(enumerate(split(code, '\n'))) do (i,line)
isone(i) ? string(prompt_with_space, line) : string(pads, line)
end |> joinlines
end
function collect_hold_results(chunk::CodeChunk)
for r in chunk.result
chunk.output *= r.stdout
chunk.rich_output *= r.rich_output
@ -503,7 +445,7 @@ function _replace_header_inline!(doc, header, report, mod)
end
function run_inline_code(code, doc, report, mod)
inline = InlineCode(code, 1, 1, 1, :inline)
inline = InlineCode(code, 1, :inline)
inline = run_inline(inline, doc, report, mod)
return strip(inline.output, '"')
end

View File

@ -1,6 +1,8 @@
# TODO: concreate typing
abstract type WeaveChunk end
abstract type Inline end
abstract type WeaveFormat end
mutable struct WeaveDoc
source::AbstractString
@ -12,49 +14,41 @@ mutable struct WeaveDoc
doctype::String
header_script::String
header::Dict
template::Union{AbstractString,Mustache.MustacheTokens}
css::AbstractString
highlight_theme::Type{<:Highlights.AbstractTheme}
fig_path::AbstractString
chunk_defaults::Dict{Symbol,Any}
end
struct ChunkOutput
code::AbstractString
stdout::AbstractString
displayed::AbstractString
rich_output::AbstractString
figures::Vector{AbstractString}
code::String
stdout::String
rich_output::String
figures::Vector{String}
end
mutable struct CodeChunk <: WeaveChunk
content::AbstractString
content::String
number::Int
result_no::Int
start_line::Int
optionstring::AbstractString
optionstring::String
options::Dict{Symbol,Any}
output::AbstractString
rich_output::AbstractString
figures::Vector{AbstractString}
figures::Vector{String}
result::Vector{ChunkOutput}
function CodeChunk(content, number, start_line, optionstring, options)
new(
rstrip(content) * "\n",
number,
0,
start_line,
optionstring,
options,
"",
"",
AbstractString[],
ChunkOutput[],
)
end
end
abstract type Inline end
function CodeChunk(content, number, start_line, optionstring, options)
return CodeChunk(
string(rstrip(content), '\n'), # normalize end of chunk)
number,
start_line,
optionstring,
options,
"",
"",
AbstractString[],
ChunkOutput[]
)
end
mutable struct DocChunk <: WeaveChunk
content::Vector{Inline}
@ -62,27 +56,17 @@ mutable struct DocChunk <: WeaveChunk
start_line::Int
end
mutable struct InlineText <: Inline
content::AbstractString
si::Int
ei::Int
struct InlineText <: Inline
content::String
number::Int
end
mutable struct InlineCode <: Inline
content::AbstractString
si::Int
ei::Int
content::String
number::Int
ctype::Symbol
output::AbstractString
rich_output::AbstractString
figures::Vector{AbstractString}
function InlineCode(content, si, ei, number, ctype)
new(content, si, ei, number, ctype, "", "", AbstractString[])
end
output::String
rich_output::String
figures::Vector{String}
end
struct TermResult end
struct ScriptResult end
struct CollectResult end
InlineCode(content, number, ctype) = InlineCode(content, number, ctype, "", "", String[])

19
src/writer/latex.jl Normal file
View File

@ -0,0 +1,19 @@
function write_doc(docformat::LaTeX2PDF, doc, rendered, out_path)
cd_back = let d = pwd(); () -> cd(d); end
cd(doc.cwd)
try
tex_path = basename(out_path)
write(tex_path, rendered)
cmds = copy(docformat.latex_cmd)
push!(cmds, tex_path)
cmd = Cmd(cmds)
run(cmd); run(cmd) # XXX: is twice enough for every case ?
catch
@warn "Error converting document to pdf. Try running latex manually"
rethrow()
finally
cd_back()
end
return get_out_path(doc, out_path, "pdf")
end

76
src/writer/pandoc.jl Normal file
View File

@ -0,0 +1,76 @@
function write_doc(docformat::Pandoc2HTML, doc, rendered, out_path)
_, weave_source = splitdir(abspath(doc.source))
weave_version, weave_date = weave_info()
# Header is inserted from displayed plots
header_script = doc.header_script
self_contained = (header_script "") ? [] : "--self-contained"
if haskey(doc.header, "bibliography")
filt = "--filter"
citeproc = "pandoc-citeproc"
else
filt = []
citeproc = []
end
out_path = get_out_path(doc, out_path, "html")
cd_back = let d = pwd(); () -> cd(d); end
cd(dirname(out_path))
try
out = basename(out_path)
highlight_stylesheet = get_highlight_stylesheet(MIME("text/html"), docformat.highlight_theme)
cmd = `pandoc -f markdown+raw_html -s --mathjax=""
$filt $citeproc $(docformat.pandoc_options)
--template $(docformat.template_path)
-H $(docformat.stylesheet_path)
$(self_contained)
-V highlight_stylesheet=$(highlight_stylesheet)
-V weave_version=$(weave_version)
-V weave_date=$(weave_date)
-V weave_source=$(weave_source)
-V headerscript=$(header_script)
-o $(out)`
proc = open(cmd, "r+")
println(proc.in, rendered)
close(proc.in)
proc_output = read(proc.out, String)
catch
rethrow() # TODO: just show error content instead of rethrow the err
finally
cd_back()
end
return out_path
end
function write_doc(docformat::Pandoc2PDF, doc, rendered, out_path)
if haskey(doc.header, "bibliography")
filt = "--filter"
citeproc = "pandoc-citeproc"
else
filt = []
citeproc = []
end
out_path = get_out_path(doc, out_path, "pdf")
cd_back = let d = pwd(); () -> cd(d); end
cd(dirname(out_path))
try
out = basename(out_path)
cmd = `pandoc -f markdown+raw_tex -s --pdf-engine=xelatex --highlight-style=tango
$filt $citeproc $(docformat.pandoc_options)
--include-in-header=$(docformat.header_template)
-o $(out)`
proc = open(cmd, "r+")
println(proc.in, rendered)
close(proc.in)
proc_output = read(proc.out, String)
catch
rethrow()
finally
cd_back()
end
return out_path
end

11
src/writer/writer.jl Normal file
View File

@ -0,0 +1,11 @@
function write_doc(doc, rendered, out_path)
return write_doc(doc.format, doc, rendered, out_path)
end
function write_doc(::WeaveFormat, doc, rendered, out_path)
write(out_path, rendered)
return out_path
end
include("pandoc.jl")
include("latex.jl")

View File

@ -16,10 +16,10 @@
<script type="text/javascript" async src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML">
</script>
{{{ :highlightcss }}}
{{{ :highlight_stylesheet }}}
<style type="text/css">
{{{ :themecss }}}
{{{ :stylesheet }}}
</style>
</HEAD>
@ -38,8 +38,8 @@
<HR/>
<div class="footer">
<p>
Published from <a href="{{{:source}}}">{{{:source}}}</a>
using <a href="http://github.com/JunoLab/Weave.jl">Weave.jl</a> {{:wversion}} on {{:wdate}}.
Published from <a href="{{{:weave_source}}}">{{{:weave_source}}}</a>
using <a href="http://github.com/JunoLab/Weave.jl">Weave.jl</a> {{:weave_version}} on {{:weave_date}}.
</p>
</div>
</div>

View File

@ -7,6 +7,9 @@
\usepackage{graphicx}
\usepackage{microtype}
\usepackage{hyperref}
{{#:tex_deps}}
{{{ :tex_deps }}}
{{/:tex_deps}}
\setlength{\parindent}{0pt}
\setlength{\parskip}{1.2ex}

View File

@ -32,7 +32,7 @@ $for(header-includes)$
$header-includes$
$endfor$
$highlightcss$
$highlight_stylesheet$
$if(highlighting-css)$
<style type="text/css">
@ -85,8 +85,8 @@ $endfor$
<HR/>
<div class="footer"><p>
Published from <a href="$wsource$">$wsource$</a> using
<a href="http://github.com/mpastell/Weave.jl">Weave.jl</a> $wversion$ on $wdate$.
Published from <a href="$source$">$source$</a> using
<a href="http://github.com/mpastell/Weave.jl">Weave.jl</a> $weave_version$ on $weave_date$.
<p></div>
</div>

View File

@ -1,7 +1,4 @@
using Weave
using Test
#Test if running document with and without cache works
# Test if running document with and without cache works
isdir("documents/cache") && rm("documents/cache", recursive = true)
weave("documents/chunk_options.noweb", cache=:all)
result = read("documents/chunk_options.md", String)

View File

@ -1,20 +0,0 @@
using Weave
using Test
cleanup = true
VER = "$(VERSION.major).$(VERSION.minor)"
Weave.push_preexecute_hook(identity)
weave("documents/chunk_options.noweb")
Weave.pop_preexecute_hook(identity)
result = read("documents/chunk_options.md", String)
ref = read("documents/chunk_options_ref.md", String)
@test result == ref
cleanup && rm("documents/chunk_options.md")
tangle("documents/chunk_options.noweb", out_path = "documents/tangle")
result = read("documents/tangle/chunk_options.jl", String)
ref = read("documents/tangle/chunk_options.jl.ref", String)
@test ref == result
cleanup && rm("documents/tangle/chunk_options.jl")

View File

@ -1,6 +0,0 @@
Functions:
<<>>=
f(x)=x^2
println(f(2))
@

View File

@ -1,13 +0,0 @@
Functions:
~~~~{.julia}
f(x)=x^2
println(f(2))
~~~~~~~~~~~~~
~~~~
4
~~~~

View File

@ -1,18 +0,0 @@
~~~~{.julia}
using Gadfly
x = range(0, stop =2π, step=0.05)
plot(x=x, y = sin.(x), Geom.line)
~~~~~~~~~~~~~
![sin(x) function.](figures/gadfly_formats_test_sin_fun_1.js.svg){#fig:sin_fun}
![cos(x) function.](figures/gadfly_formats_test_2_1.js.svg)
~~~~{.julia}
plot(x=x, y = cos.(2x), Geom.line)
~~~~~~~~~~~~~
![](figures/gadfly_formats_test_cos2_fun_1.js.svg){width=15cm #fig:cos2_fun}\

View File

@ -1,17 +0,0 @@
````julia
using Gadfly
x = range(0, stop =2π, step=0.05)
plot(x=x, y = sin.(x), Geom.line)
````
![sin(x) function.](figures/gadfly_formats_test_sin_fun_1.pdf)
![cos(x) function.](figures/gadfly_formats_test_2_1.pdf)
````julia
plot(x=x, y = cos.(2x), Geom.line)
````
![](figures/gadfly_formats_test_cos2_fun_1.pdf)

View File

@ -1,17 +0,0 @@
````julia
using Gadfly
x = range(0, stop =2π, step=0.05)
plot(x=x, y = sin.(x), Geom.line)
````
![sin(x) function.](figures/gadfly_formats_test_sin_fun_1.png)
![cos(x) function.](figures/gadfly_formats_test_2_1.png)
````julia
plot(x=x, y = cos.(2x), Geom.line)
````
![](figures/gadfly_formats_test_cos2_fun_1.png)

View File

@ -1,18 +0,0 @@
~~~~{.julia}
using Gadfly
x = range(0, stop =2π, step=0.05)
plot(x=x, y = sin.(x), Geom.line)
~~~~~~~~~~~~~
![sin(x) function.](figures/gadfly_formats_test_sin_fun_1.png){#fig:sin_fun}
![cos(x) function.](figures/gadfly_formats_test_2_1.png)
~~~~{.julia}
plot(x=x, y = cos.(2x), Geom.line)
~~~~~~~~~~~~~
![](figures/gadfly_formats_test_cos2_fun_1.png){width=15cm #fig:cos2_fun}\

View File

@ -1,17 +0,0 @@
````julia
using Gadfly
x = range(0, stop =2π, step=0.05)
plot(x=x, y = sin.(x), Geom.line)
````
![sin(x) function.](figures/gadfly_formats_test_sin_fun_1.svg)
![cos(x) function.](figures/gadfly_formats_test_2_1.svg)
````julia
plot(x=x, y = cos.(2x), Geom.line)
````
![](figures/gadfly_formats_test_cos2_fun_1.svg)

View File

@ -1,22 +0,0 @@
\begin{juliacode}
using Gadfly
x = range(0, stop =2π, step=0.05)
plot(x=x, y = sin.(x), Geom.line)
\end{juliacode}
\begin{figure}[ht]
\center
\includegraphics[width=\linewidth]{figures/gadfly_formats_test_sin_fun_1.pdf}
\caption{sin(x) function.}
\label{fig:sin_fun}
\end{figure}
\begin{figure}[htpb]
\center
\includegraphics[width=\linewidth]{figures/gadfly_formats_test_2_1.pdf}
\caption{cos(x) function.}
\end{figure}
\begin{juliacode}
plot(x=x, y = cos.(2x), Geom.line)
\end{juliacode}
\includegraphics[width=15cm]{figures/gadfly_formats_test_cos2_fun_1.pdf}

View File

@ -1,22 +0,0 @@
\begin{juliacode}
using Gadfly
x = range(0, stop =2π, step=0.05)
plot(x=x, y = sin.(x), Geom.line)
\end{juliacode}
\begin{figure}[ht]
\center
\includegraphics[width=\linewidth]{figures/gadfly_formats_test_sin_fun_1.png}
\caption{sin(x) function.}
\label{fig:sin_fun}
\end{figure}
\begin{figure}[htpb]
\center
\includegraphics[width=\linewidth]{figures/gadfly_formats_test_2_1.png}
\caption{cos(x) function.}
\end{figure}
\begin{juliacode}
plot(x=x, y = cos.(2x), Geom.line)
\end{juliacode}
\includegraphics[width=15cm]{figures/gadfly_formats_test_cos2_fun_1.png}

View File

@ -1,22 +0,0 @@
\begin{juliacode}
using Gadfly
x = range(0, stop =2π, step=0.05)
plot(x=x, y = sin.(x), Geom.line)
\end{juliacode}
\begin{figure}[ht]
\center
\includegraphics[width=\linewidth]{figures/gadfly_formats_test_sin_fun_1.ps}
\caption{sin(x) function.}
\label{fig:sin_fun}
\end{figure}
\begin{figure}[htpb]
\center
\includegraphics[width=\linewidth]{figures/gadfly_formats_test_2_1.ps}
\caption{cos(x) function.}
\end{figure}
\begin{juliacode}
plot(x=x, y = cos.(2x), Geom.line)
\end{juliacode}
\includegraphics[width=15cm]{figures/gadfly_formats_test_cos2_fun_1.ps}

View File

@ -1,22 +0,0 @@
\begin{juliacode}
using Gadfly
x = range(0, stop =2π, step=0.05)
plot(x=x, y = sin.(x), Geom.line)
\end{juliacode}
\begin{figure}[ht]
\center
\resizebox{\linewidth}{!}{\input{figures/gadfly_formats_test_sin_fun_1.tex}}
\caption{sin(x) function.}
\label{fig:sin_fun}
\end{figure}
\begin{figure}[htpb]
\center
\resizebox{\linewidth}{!}{\input{figures/gadfly_formats_test_2_1.tex}}
\caption{cos(x) function.}
\end{figure}
\begin{juliacode}
plot(x=x, y = cos.(2x), Geom.line)
\end{juliacode}
\resizebox{15cm}{!}{\input{figures/gadfly_formats_test_cos2_fun_1.tex}}

View File

@ -1,19 +0,0 @@
---
weave_options:
out_path: gadfly
---
<<fig_cap="sin(x) function."; label="sin_fun"; fig_pos="ht">>=
using Gadfly
x = range(0, stop =2π, step=0.05)
plot(x=x, y = sin.(x), Geom.line)
@
<<echo=false; fig_cap="cos(x) function."; dpi=200>>=
plot(x=x, y = cos.(x), Geom.line)
@
<<label="cos2_fun"; out_width="15cm">>=
plot(x=x, y = cos.(2x), Geom.line)
@

View File

@ -1,12 +0,0 @@
# Gadfly
```{julia;fig_ext=".svg";dpi=300}
using Gadfly
x = collect(range(0, stop=2π, length=200))
plot(
layer(x=x, y = sin.(x), Geom.line),
layer(x=x, y = cos.(x), Geom.line, Theme(default_color=colorant"red")),
Guide.manual_color_key("Legend", ["sin", "cos"], ["deepskyblue", "red"])
)
```

View File

@ -1,22 +0,0 @@
<div class="Random plot">
<p>Some inline output</p>
<pre class='hljl'>
<span class='hljl-nf'>println</span><span class='hljl-p'>(</span><span class='hljl-s'>&quot;Testing output&quot;</span><span class='hljl-p'>)</span>
</pre>
<pre class="output">
Testing output
</pre>
</div>

View File

@ -1,22 +0,0 @@
\begin{frame}[fragile]
\frametitle{Random plot}
Some inline output
\begin{lstlisting}
(*@\HLJLnf{println}@*)(*@\HLJLp{(}@*)(*@\HLJLs{"{}Testing}@*) (*@\HLJLs{output"{}}@*)(*@\HLJLp{)}@*)
\end{lstlisting}
\begin{lstlisting}
Testing output
\end{lstlisting}
\end{frame}

View File

@ -1,17 +0,0 @@
Here's some text
And here's some code
```julia
x = 1
y = 2
@show x + y
```
Here's some more complicated code
```julia
@code_native +(1.0, π)
using Test
@test 1 == 1
```

View File

@ -1,31 +0,0 @@
---
title: A minimal beamer example using Weave markdown
author: Matti Pastell
weave_options:
out_path: inline
---
```julia; echo=false
struct Begin
text
title
end
struct End
text
end
Base.show(io::IO, m::MIME"text/latex", b::Begin) = write(io, "\\begin{$(b.text)}[fragile]\n\\frametitle{$(b.title)}\n")
Base.show(io::IO, m::MIME"text/latex", e::End) = write(io, "\\end{$(e.text)}")
Base.show(io::IO, m::MIME"text/html", b::Begin) = write(io, "<div class=\"$(b.title)\">\n")
Base.show(io::IO, m::MIME"text/html", e::End) = write(io, "</div>")
```
! Begin("frame", "Random plot")
Some inline `j print("output")`
```julia
println("Testing output")
```
! End("frame")

View File

@ -1,31 +0,0 @@
```julia
display("text/markdown",
"""
### Small markdown sample
**Hello** from `code` block.
""")
```
```julia
struct Dummy
s::String
end
function Base.show(io::IO, m::MIME"text/markdown", d::Dummy)
print(io, d.s)
end
Dummy("""
* one
* two
* three
""")
```

View File

@ -1,96 +0,0 @@
````julia
import Base
function Base.show(io::IO, m::MIME"text/html", x::Array)
print(io, "<table>")
for i in 1:size(x,1)
print(io, "<tr>")
[print(io, "<td>$r</td>") for r in x[i,:]]
print(io, "</tr>")
end
print(io, "</table>")
end
#This isn't valid latex, doesn't matter for the test
function Base.show(io::IO, m::MIME"text/latex", x::Array)
println(io, "\\begin{tabular}")
for i in 1:size(x,1)
[print(io, "$r & ") for r in x[i,:]]
print(io, "\\\\")
println(io, " \\hline")
end
print(io, "\\end{tabular")
end
#This isn't valid markdown, doesn't matter for the test
function Base.show(io::IO, m::MIME"text/markdown", x::Array)
println(io, "-----")
for i in 1:size(x,1)
print(io, "| ")
[print(io, "$r | ") for r in x[i,:]]
println(io, "")
end
print(io, "-----")
end
x = [collect(1:3) collect(1:3)]
ca = collect('a':'d')
ca
````
-----
| a |
| b |
| c |
| d |
-----
````julia
display(ca)
display(x)
````
-----
| a |
| b |
| c |
| d |
-----
-----
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
-----
````julia
julia> x
3×2 Array{Int64,2}:
1 1
2 2
3 3
julia> ca
4-element Array{Char,1}:
'a'
'b'
'c'
'd'
````
````julia
using Markdown
m = Markdown.parse("**Some Markdown**")
m
````
**Some Markdown**

View File

@ -1,84 +0,0 @@
<pre class='hljl'>
<span class='hljl-k'>import</span><span class='hljl-t'> </span><span class='hljl-n'>Base</span><span class='hljl-t'>
</span><span class='hljl-k'>function</span><span class='hljl-t'> </span><span class='hljl-n'>Base</span><span class='hljl-oB'>.</span><span class='hljl-nf'>show</span><span class='hljl-p'>(</span><span class='hljl-n'>io</span><span class='hljl-oB'>::</span><span class='hljl-n'>IO</span><span class='hljl-p'>,</span><span class='hljl-t'> </span><span class='hljl-n'>m</span><span class='hljl-oB'>::</span><span class='hljl-so'>MIME&quot;text/html&quot;</span><span class='hljl-p'>,</span><span class='hljl-t'> </span><span class='hljl-n'>x</span><span class='hljl-oB'>::</span><span class='hljl-n'>Array</span><span class='hljl-p'>)</span><span class='hljl-t'>
</span><span class='hljl-nf'>print</span><span class='hljl-p'>(</span><span class='hljl-n'>io</span><span class='hljl-p'>,</span><span class='hljl-t'> </span><span class='hljl-s'>&quot;&lt;table&gt;&quot;</span><span class='hljl-p'>)</span><span class='hljl-t'>
</span><span class='hljl-k'>for</span><span class='hljl-t'> </span><span class='hljl-n'>i</span><span class='hljl-t'> </span><span class='hljl-kp'>in</span><span class='hljl-t'> </span><span class='hljl-ni'>1</span><span class='hljl-oB'>:</span><span class='hljl-nf'>size</span><span class='hljl-p'>(</span><span class='hljl-n'>x</span><span class='hljl-p'>,</span><span class='hljl-ni'>1</span><span class='hljl-p'>)</span><span class='hljl-t'>
</span><span class='hljl-nf'>print</span><span class='hljl-p'>(</span><span class='hljl-n'>io</span><span class='hljl-p'>,</span><span class='hljl-t'> </span><span class='hljl-s'>&quot;&lt;tr&gt;&quot;</span><span class='hljl-p'>)</span><span class='hljl-t'>
</span><span class='hljl-p'>[</span><span class='hljl-nf'>print</span><span class='hljl-p'>(</span><span class='hljl-n'>io</span><span class='hljl-p'>,</span><span class='hljl-t'> </span><span class='hljl-s'>&quot;&lt;td&gt;</span><span class='hljl-si'>$r</span><span class='hljl-s'>&lt;/td&gt;&quot;</span><span class='hljl-p'>)</span><span class='hljl-t'> </span><span class='hljl-k'>for</span><span class='hljl-t'> </span><span class='hljl-n'>r</span><span class='hljl-t'> </span><span class='hljl-kp'>in</span><span class='hljl-t'> </span><span class='hljl-n'>x</span><span class='hljl-p'>[</span><span class='hljl-n'>i</span><span class='hljl-p'>,</span><span class='hljl-oB'>:</span><span class='hljl-p'>]]</span><span class='hljl-t'>
</span><span class='hljl-nf'>print</span><span class='hljl-p'>(</span><span class='hljl-n'>io</span><span class='hljl-p'>,</span><span class='hljl-t'> </span><span class='hljl-s'>&quot;&lt;/tr&gt;&quot;</span><span class='hljl-p'>)</span><span class='hljl-t'>
</span><span class='hljl-k'>end</span><span class='hljl-t'>
</span><span class='hljl-nf'>print</span><span class='hljl-p'>(</span><span class='hljl-n'>io</span><span class='hljl-p'>,</span><span class='hljl-t'> </span><span class='hljl-s'>&quot;&lt;/table&gt;&quot;</span><span class='hljl-p'>)</span><span class='hljl-t'>
</span><span class='hljl-k'>end</span><span class='hljl-t'>
</span><span class='hljl-cs'>#This isn&#39;t valid latex, doesn&#39;t matter for the test</span><span class='hljl-t'>
</span><span class='hljl-k'>function</span><span class='hljl-t'> </span><span class='hljl-n'>Base</span><span class='hljl-oB'>.</span><span class='hljl-nf'>show</span><span class='hljl-p'>(</span><span class='hljl-n'>io</span><span class='hljl-oB'>::</span><span class='hljl-n'>IO</span><span class='hljl-p'>,</span><span class='hljl-t'> </span><span class='hljl-n'>m</span><span class='hljl-oB'>::</span><span class='hljl-so'>MIME&quot;text/latex&quot;</span><span class='hljl-p'>,</span><span class='hljl-t'> </span><span class='hljl-n'>x</span><span class='hljl-oB'>::</span><span class='hljl-n'>Array</span><span class='hljl-p'>)</span><span class='hljl-t'>
</span><span class='hljl-nf'>println</span><span class='hljl-p'>(</span><span class='hljl-n'>io</span><span class='hljl-p'>,</span><span class='hljl-t'> </span><span class='hljl-s'>&quot;</span><span class='hljl-se'>\\</span><span class='hljl-s'>begin{tabular}&quot;</span><span class='hljl-p'>)</span><span class='hljl-t'>
</span><span class='hljl-k'>for</span><span class='hljl-t'> </span><span class='hljl-n'>i</span><span class='hljl-t'> </span><span class='hljl-kp'>in</span><span class='hljl-t'> </span><span class='hljl-ni'>1</span><span class='hljl-oB'>:</span><span class='hljl-nf'>size</span><span class='hljl-p'>(</span><span class='hljl-n'>x</span><span class='hljl-p'>,</span><span class='hljl-ni'>1</span><span class='hljl-p'>)</span><span class='hljl-t'>
</span><span class='hljl-p'>[</span><span class='hljl-nf'>print</span><span class='hljl-p'>(</span><span class='hljl-n'>io</span><span class='hljl-p'>,</span><span class='hljl-t'> </span><span class='hljl-s'>&quot;</span><span class='hljl-si'>$r</span><span class='hljl-s'> &amp; &quot;</span><span class='hljl-p'>)</span><span class='hljl-t'> </span><span class='hljl-k'>for</span><span class='hljl-t'> </span><span class='hljl-n'>r</span><span class='hljl-t'> </span><span class='hljl-kp'>in</span><span class='hljl-t'> </span><span class='hljl-n'>x</span><span class='hljl-p'>[</span><span class='hljl-n'>i</span><span class='hljl-p'>,</span><span class='hljl-oB'>:</span><span class='hljl-p'>]]</span><span class='hljl-t'>
</span><span class='hljl-nf'>print</span><span class='hljl-p'>(</span><span class='hljl-n'>io</span><span class='hljl-p'>,</span><span class='hljl-t'> </span><span class='hljl-s'>&quot;</span><span class='hljl-se'>\\\\</span><span class='hljl-s'>&quot;</span><span class='hljl-p'>)</span><span class='hljl-t'>
</span><span class='hljl-nf'>println</span><span class='hljl-p'>(</span><span class='hljl-n'>io</span><span class='hljl-p'>,</span><span class='hljl-t'> </span><span class='hljl-s'>&quot; </span><span class='hljl-se'>\\</span><span class='hljl-s'>hline&quot;</span><span class='hljl-p'>)</span><span class='hljl-t'>
</span><span class='hljl-k'>end</span><span class='hljl-t'>
</span><span class='hljl-nf'>print</span><span class='hljl-p'>(</span><span class='hljl-n'>io</span><span class='hljl-p'>,</span><span class='hljl-t'> </span><span class='hljl-s'>&quot;</span><span class='hljl-se'>\\</span><span class='hljl-s'>end{tabular&quot;</span><span class='hljl-p'>)</span><span class='hljl-t'>
</span><span class='hljl-k'>end</span><span class='hljl-t'>
</span><span class='hljl-cs'>#This isn&#39;t valid markdown, doesn&#39;t matter for the test</span><span class='hljl-t'>
</span><span class='hljl-k'>function</span><span class='hljl-t'> </span><span class='hljl-n'>Base</span><span class='hljl-oB'>.</span><span class='hljl-nf'>show</span><span class='hljl-p'>(</span><span class='hljl-n'>io</span><span class='hljl-oB'>::</span><span class='hljl-n'>IO</span><span class='hljl-p'>,</span><span class='hljl-t'> </span><span class='hljl-n'>m</span><span class='hljl-oB'>::</span><span class='hljl-so'>MIME&quot;text/markdown&quot;</span><span class='hljl-p'>,</span><span class='hljl-t'> </span><span class='hljl-n'>x</span><span class='hljl-oB'>::</span><span class='hljl-n'>Array</span><span class='hljl-p'>)</span><span class='hljl-t'>
</span><span class='hljl-nf'>println</span><span class='hljl-p'>(</span><span class='hljl-n'>io</span><span class='hljl-p'>,</span><span class='hljl-t'> </span><span class='hljl-s'>&quot;-----&quot;</span><span class='hljl-p'>)</span><span class='hljl-t'>
</span><span class='hljl-k'>for</span><span class='hljl-t'> </span><span class='hljl-n'>i</span><span class='hljl-t'> </span><span class='hljl-kp'>in</span><span class='hljl-t'> </span><span class='hljl-ni'>1</span><span class='hljl-oB'>:</span><span class='hljl-nf'>size</span><span class='hljl-p'>(</span><span class='hljl-n'>x</span><span class='hljl-p'>,</span><span class='hljl-ni'>1</span><span class='hljl-p'>)</span><span class='hljl-t'>
</span><span class='hljl-nf'>print</span><span class='hljl-p'>(</span><span class='hljl-n'>io</span><span class='hljl-p'>,</span><span class='hljl-t'> </span><span class='hljl-s'>&quot;| &quot;</span><span class='hljl-p'>)</span><span class='hljl-t'>
</span><span class='hljl-p'>[</span><span class='hljl-nf'>print</span><span class='hljl-p'>(</span><span class='hljl-n'>io</span><span class='hljl-p'>,</span><span class='hljl-t'> </span><span class='hljl-s'>&quot;</span><span class='hljl-si'>$r</span><span class='hljl-s'> | &quot;</span><span class='hljl-p'>)</span><span class='hljl-t'> </span><span class='hljl-k'>for</span><span class='hljl-t'> </span><span class='hljl-n'>r</span><span class='hljl-t'> </span><span class='hljl-kp'>in</span><span class='hljl-t'> </span><span class='hljl-n'>x</span><span class='hljl-p'>[</span><span class='hljl-n'>i</span><span class='hljl-p'>,</span><span class='hljl-oB'>:</span><span class='hljl-p'>]]</span><span class='hljl-t'>
</span><span class='hljl-nf'>println</span><span class='hljl-p'>(</span><span class='hljl-n'>io</span><span class='hljl-p'>,</span><span class='hljl-t'> </span><span class='hljl-s'>&quot;&quot;</span><span class='hljl-p'>)</span><span class='hljl-t'>
</span><span class='hljl-k'>end</span><span class='hljl-t'>
</span><span class='hljl-nf'>print</span><span class='hljl-p'>(</span><span class='hljl-n'>io</span><span class='hljl-p'>,</span><span class='hljl-t'> </span><span class='hljl-s'>&quot;-----&quot;</span><span class='hljl-p'>)</span><span class='hljl-t'>
</span><span class='hljl-k'>end</span><span class='hljl-t'>
</span><span class='hljl-n'>x</span><span class='hljl-t'> </span><span class='hljl-oB'>=</span><span class='hljl-t'> </span><span class='hljl-p'>[</span><span class='hljl-nf'>collect</span><span class='hljl-p'>(</span><span class='hljl-ni'>1</span><span class='hljl-oB'>:</span><span class='hljl-ni'>3</span><span class='hljl-p'>)</span><span class='hljl-t'> </span><span class='hljl-nf'>collect</span><span class='hljl-p'>(</span><span class='hljl-ni'>1</span><span class='hljl-oB'>:</span><span class='hljl-ni'>3</span><span class='hljl-p'>)]</span><span class='hljl-t'>
</span><span class='hljl-n'>ca</span><span class='hljl-t'> </span><span class='hljl-oB'>=</span><span class='hljl-t'> </span><span class='hljl-nf'>collect</span><span class='hljl-p'>(</span><span class='hljl-sc'>&#39;a&#39;</span><span class='hljl-oB'>:</span><span class='hljl-sc'>&#39;d&#39;</span><span class='hljl-p'>)</span><span class='hljl-t'>
</span><span class='hljl-n'>ca</span>
</pre>
<table><tr><td>a</td></tr><tr><td>b</td></tr><tr><td>c</td></tr><tr><td>d</td></tr></table>
<pre class='hljl'>
<span class='hljl-nf'>display</span><span class='hljl-p'>(</span><span class='hljl-n'>ca</span><span class='hljl-p'>)</span><span class='hljl-t'>
</span><span class='hljl-nf'>display</span><span class='hljl-p'>(</span><span class='hljl-n'>x</span><span class='hljl-p'>)</span>
</pre>
<table><tr><td>a</td></tr><tr><td>b</td></tr><tr><td>c</td></tr><tr><td>d</td></tr></table>
<table><tr><td>1</td><td>1</td></tr><tr><td>2</td><td>2</td></tr><tr><td>3</td><td>3</td></tr></table>
<pre class='hljl'>
<span class='hljl-nB'>julia&gt; </span><span class='hljl-n'>x</span><span class='hljl-t'>
3×2 Array{Int64,2}:
1 1
2 2
3 3
</span><span class='hljl-nB'>julia&gt; </span><span class='hljl-n'>ca</span><span class='hljl-t'>
4-element Array{Char,1}:
&#39;a&#39;
&#39;b&#39;
&#39;c&#39;
&#39;d&#39;</span>
</pre>
<pre class='hljl'>
<span class='hljl-k'>using</span><span class='hljl-t'> </span><span class='hljl-n'>Markdown</span><span class='hljl-t'>
</span><span class='hljl-n'>m</span><span class='hljl-t'> </span><span class='hljl-oB'>=</span><span class='hljl-t'> </span><span class='hljl-n'>Markdown</span><span class='hljl-oB'>.</span><span class='hljl-nf'>parse</span><span class='hljl-p'>(</span><span class='hljl-s'>&quot;**Some Markdown**&quot;</span><span class='hljl-p'>)</span><span class='hljl-t'>
</span><span class='hljl-n'>m</span>
</pre>
<div class="markdown"><p><strong>Some Markdown</strong></p>
</div>

View File

@ -1,96 +0,0 @@
~~~~{.julia}
import Base
function Base.show(io::IO, m::MIME"text/html", x::Array)
print(io, "<table>")
for i in 1:size(x,1)
print(io, "<tr>")
[print(io, "<td>$r</td>") for r in x[i,:]]
print(io, "</tr>")
end
print(io, "</table>")
end
#This isn't valid latex, doesn't matter for the test
function Base.show(io::IO, m::MIME"text/latex", x::Array)
println(io, "\\begin{tabular}")
for i in 1:size(x,1)
[print(io, "$r & ") for r in x[i,:]]
print(io, "\\\\")
println(io, " \\hline")
end
print(io, "\\end{tabular")
end
#This isn't valid markdown, doesn't matter for the test
function Base.show(io::IO, m::MIME"text/markdown", x::Array)
println(io, "-----")
for i in 1:size(x,1)
print(io, "| ")
[print(io, "$r | ") for r in x[i,:]]
println(io, "")
end
print(io, "-----")
end
x = [collect(1:3) collect(1:3)]
ca = collect('a':'d')
ca
~~~~~~~~~~~~~
-----
| a |
| b |
| c |
| d |
-----
~~~~{.julia}
display(ca)
display(x)
~~~~~~~~~~~~~
-----
| a |
| b |
| c |
| d |
-----
-----
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
-----
~~~~{.julia}
julia> x
3×2 Array{Int64,2}:
1 1
2 2
3 3
julia> ca
4-element Array{Char,1}:
'a'
'b'
'c'
'd'
~~~~~~~~~~~~~
~~~~{.julia}
using Markdown
m = Markdown.parse("**Some Markdown**")
m
~~~~~~~~~~~~~
**Some Markdown**

View File

@ -1,89 +0,0 @@
\begin{juliacode}
import Base
function Base.show(io::IO, m::MIME"text/html", x::Array)
print(io, "<table>")
for i in 1:size(x,1)
print(io, "<tr>")
[print(io, "<td>$r</td>") for r in x[i,:]]
print(io, "</tr>")
end
print(io, "</table>")
end
#This isn't valid latex, doesn't matter for the test
function Base.show(io::IO, m::MIME"text/latex", x::Array)
println(io, "\\begin{tabular}")
for i in 1:size(x,1)
[print(io, "$r & ") for r in x[i,:]]
print(io, "\\\\")
println(io, " \\hline")
end
print(io, "\\end{tabular")
end
#This isn't valid markdown, doesn't matter for the test
function Base.show(io::IO, m::MIME"text/markdown", x::Array)
println(io, "-----")
for i in 1:size(x,1)
print(io, "| ")
[print(io, "$r | ") for r in x[i,:]]
println(io, "")
end
print(io, "-----")
end
x = [collect(1:3) collect(1:3)]
ca = collect('a':'d')
ca
\end{juliacode}
\begin{tabular}
a & \\ \hline
b & \\ \hline
c & \\ \hline
d & \\ \hline
\end{tabular
\begin{juliacode}
display(ca)
display(x)
\end{juliacode}
\begin{tabular}
a & \\ \hline
b & \\ \hline
c & \\ \hline
d & \\ \hline
\end{tabular
\begin{tabular}
1 & 1 & \\ \hline
2 & 2 & \\ \hline
3 & 3 & \\ \hline
\end{tabular
\begin{juliaterm}
julia> x
3×2 Array{Int64,2}:
1 1
2 2
3 3
julia> ca
4-element Array{Char,1}:
'a'
'b'
'c'
'd'
\end{juliaterm}
\begin{juliacode}
using Markdown
m = Markdown.parse("**Some Markdown**")
m
\end{juliacode}
\textbf{Some Markdown}

View File

@ -1,16 +0,0 @@
using Plots
pyplot()
x = range(0, stop=2*pi, length=50)
println(x)
p = plot(x = x, y = sin(x), size =(900,300))
plot(x = x, y = sin(x))
plot(rand(100) / 3,reg=true,fill=(0,:green))
scatter!(rand(100),markersize=6,c=:orange)
plot(rand(100) / 3,reg=true,fill=(0,:green))
scatter!(rand(100),markersize=6,c=:orange)
plot(y = cumsum(randn(1000, 1)))

View File

@ -1,60 +0,0 @@
~~~~{.julia}
using Plots
pyplot()
x = linspace(0, 2*pi)
println(x)
~~~~~~~~~~~~~
~~~~
linspace(0.0,6.283185307179586,50)
~~~~
~~~~{.julia}
p = plot(x, sin(x), size =(900,300))
~~~~~~~~~~~~~
~~~~{.julia}
julia> plot(x, sin(x))
~~~~~~~~~~~~~
![](figures/plotsjl_test_2_1.png)\
~~~~{.julia}
plot(rand(100) / 3,reg=true,fill=(0,:green))
scatter!(rand(100),markersize=6,c=:orange)
~~~~~~~~~~~~~
![](figures/plotsjl_test_3_1.png)\
~~~~{.julia}
julia> plot(rand(100) / 3,reg=true,fill=(0,:green))
~~~~~~~~~~~~~
![](figures/plotsjl_test_4_1.png)\
~~~~{.julia}
julia> scatter!(rand(100),markersize=6,c=:orange)
~~~~~~~~~~~~~
![](figures/plotsjl_test_4_2.png)\
![A random walk.](figures/plotsjl_test_random_1.png)

View File

@ -1,47 +0,0 @@
\begin{juliacode}
using Plots
pyplot()
x = linspace(0, 2*pi)
println(x)
\end{juliacode}
\begin{juliaout}
linspace(0.0,6.283185307179586,50)
\end{juliaout}
\begin{juliacode}
p = plot(x, sin(x), size =(900,300))
\end{juliacode}
\begin{juliaterm}
julia> plot(x, sin(x))
\end{juliaterm}
\includegraphics[width=\linewidth]{figures/plotsjl_test_2_1.pdf}
\begin{juliacode}
plot(rand(100) / 3,reg=true,fill=(0,:green))
scatter!(rand(100),markersize=6,c=:orange)
\end{juliacode}
\includegraphics[width=\linewidth]{figures/plotsjl_test_3_1.pdf}
\begin{juliaterm}
julia> plot(rand(100) / 3,reg=true,fill=(0,:green))
\end{juliaterm}
\includegraphics[width=\linewidth]{figures/plotsjl_test_4_1.pdf}
\begin{juliaterm}
julia> scatter!(rand(100),markersize=6,c=:orange)
\end{juliaterm}
\includegraphics[width=\linewidth]{figures/plotsjl_test_4_2.pdf}
\begin{figure}[htpb]
\center
\includegraphics[width=\linewidth]{figures/plotsjl_test_random_1.pdf}
\caption{A random walk.}
\label{fig:random}
\end{figure}

View File

@ -1,41 +0,0 @@
~~~~{.julia}
using Plots
gr()
x = range(0, stop=2π, length=50)
println(x)
~~~~~~~~~~~~~
~~~~
0.0:0.1282282715750936:6.283185307179586
~~~~
~~~~{.julia}
p = plot(x, sin.(x), size =(900,300))
p
~~~~~~~~~~~~~
![](figures/plotsjl_test_gr_1_1.png)\
~~~~{.julia}
plot(x, sin.(x))
~~~~~~~~~~~~~
![](figures/plotsjl_test_gr_2_1.png)\
~~~~{.julia}
plot(rand(100) / 3,reg=true,fill=(0,:green))
scatter!(rand(100),markersize=6,c=:orange)
~~~~~~~~~~~~~
![](figures/plotsjl_test_gr_3_1.png)\
![A random walk.](figures/plotsjl_test_gr_random_1.png){#fig:random}

View File

@ -1,33 +0,0 @@
\begin{juliacode}
using Plots
gr()
x = range(0, stop=2π, length=50)
println(x)
\end{juliacode}
\begin{juliaout}
0.0:0.1282282715750936:6.283185307179586
\end{juliaout}
\begin{juliacode}
p = plot(x, sin.(x), size =(900,300))
p
\end{juliacode}
\includegraphics[width=\linewidth]{figures/plotsjl_test_gr_1_1.pdf}
\begin{juliacode}
plot(x, sin.(x))
\end{juliacode}
\includegraphics[width=\linewidth]{figures/plotsjl_test_gr_2_1.pdf}
\begin{juliacode}
plot(rand(100) / 3,reg=true,fill=(0,:green))
scatter!(rand(100),markersize=6,c=:orange)
\end{juliacode}
\includegraphics[width=\linewidth]{figures/plotsjl_test_gr_3_1.pdf}
\begin{figure}[htpb]
\center
\includegraphics[width=\linewidth]{figures/plotsjl_test_gr_random_1.pdf}
\caption{A random walk.}
\label{fig:random}
\end{figure}

View File

@ -1,29 +0,0 @@
```julia
using Plots
pyplot()
x = linspace(0, 2*pi)
println(x)
p = plot(x, sin(x), size =(900,300))
```
```julia; term=true
plot(x, sin(x))
```
```julia
plot(rand(100) / 3,reg=true,fill=(0,:green))
scatter!(rand(100),markersize=6,c=:orange)
```
```julia; term=true
plot(rand(100) / 3,reg=true,fill=(0,:green))
scatter!(rand(100),markersize=6,c=:orange)
```
```{julia;echo=false; fig_cap="A random walk."; label="random"}
plot(cumsum(randn(1000, 1)))
```

View File

@ -1,25 +0,0 @@
```julia
using Plots
gr()
x = range(0, stop=2π, length=50)
println(x)
p = plot(x, sin.(x), size =(900,300))
p
```
```julia
plot(x, sin.(x))
```
```julia
plot(rand(100) / 3,reg=true,fill=(0,:green))
scatter!(rand(100),markersize=6,c=:orange)
```
```{julia;echo=false; fig_cap="A random walk."; label="random"}
plot(cumsum(randn(1000, 1), dims=1))
```

View File

@ -1,58 +0,0 @@
```julia
import Base
function Base.show(io::IO, m::MIME"text/html", x::Array)
print(io, "<table>")
for i in 1:size(x,1)
print(io, "<tr>")
[print(io, "<td>$r</td>") for r in x[i,:]]
print(io, "</tr>")
end
print(io, "</table>")
end
#This isn't valid latex, doesn't matter for the test
function Base.show(io::IO, m::MIME"text/latex", x::Array)
println(io, "\\begin{tabular}")
for i in 1:size(x,1)
[print(io, "$r & ") for r in x[i,:]]
print(io, "\\\\")
println(io, " \\hline")
end
print(io, "\\end{tabular")
end
#This isn't valid markdown, doesn't matter for the test
function Base.show(io::IO, m::MIME"text/markdown", x::Array)
println(io, "-----")
for i in 1:size(x,1)
print(io, "| ")
[print(io, "$r | ") for r in x[i,:]]
println(io, "")
end
print(io, "-----")
end
x = [collect(1:3) collect(1:3)]
ca = collect('a':'d')
ca
```
```julia; hold=true
display(ca)
display(x)
```
```julia; term=true
x
ca
```
```julia
using Markdown
m = Markdown.parse("**Some Markdown**")
m
```

View File

@ -1,37 +0,0 @@
y= [2, 5, 12]
x = 1:10
d = Dict("Weave" => "testing")
y = [2, 4 ,8]
x = [12, 10]
println(y)
println(x)
println("Results without code")
println(x)
y = 1:5
println(y)
a = "Don't print me"
println(a)
println("No markup for results.")
println(collect(0:10:1000))
println(collect(0:10:1000))
println(collect(0:10:1000))

View File

@ -1,12 +0,0 @@
```julia
p = Array(linspace(0, 2π))
```
```julia;term=true
p = Array(linspace(0, 2π))
```
```julia;term=true
p = Array(linspace(0, 2π));
```

View File

@ -1,73 +0,0 @@
~~~~{.julia}
p = Array(linspace(0, 2π))
~~~~~~~~~~~~~
~~~~{.julia}
julia> p = Array(linspace(0, 2π))
50-element Array{Float64,1}:
0.0
0.128228
0.256457
0.384685
0.512913
0.641141
0.76937
0.897598
1.02583
1.15405
1.28228
1.41051
1.53874
1.66697
1.7952
1.92342
2.05165
2.17988
2.30811
2.43634
2.56457
2.69279
2.82102
2.94925
3.07748
3.20571
3.33394
3.46216
3.59039
3.71862
3.84685
3.97508
4.1033
4.23153
4.35976
4.48799
4.61622
4.74445
4.87267
5.0009
5.12913
5.25736
5.38559
5.51382
5.64204
5.77027
5.8985
6.02673
6.15496
6.28319
~~~~~~~~~~~~~
~~~~{.julia}
julia> p = Array(linspace(0, 2π));
~~~~~~~~~~~~~

View File

@ -0,0 +1,11 @@
# NOTE:
# This test file does end to end tests, while we don't want to check the details in the generated documents.
# Rather, we just assert we can `weave` all the supported formats without errors here.
# TODO:
# - more complex example
# - integration with other libraries, like Plots
@testset "end2end simple" begin
include("test_simple.jl")
end # @testset "end2end"

View File

@ -0,0 +1,47 @@
using Weave.Dates
test_doctypes = filter(first.(Weave.list_out_formats())) do doctype
# don't test doctypes which need external programs
doctype ("pandoc2html", "pandoc2pdf", "md2pdf", "minted2pdf")
end
function test_func(body)
@test !isempty(body)
date_str = string(Date(now()))
@test occursin(date_str, body)
end
# julia markdown
julia_markdown_body = """
# doc chunk
this is text with `j :inline` code
code chunk:
```julia
using Dates
Date(now())
```
"""
for doctype in test_doctypes
test_mock_weave(test_func, julia_markdown_body; informat = "markdown", doctype = doctype)
end
# TODO: test noweb format
# julia script
julia_script_body = """
#' # doc chunk
#'
#' this is text with `j :inline` code
#'
#' code chunk:
#+
using Dates
Date(now())
"""
for doctype in test_doctypes
test_mock_weave(test_func, julia_script_body; informat = "script", doctype = doctype)
end

View File

@ -1,49 +0,0 @@
using Weave
using Test
# Make a dummy codehunk with figure
chunk = Weave.CodeChunk("plot(x)", 1, 1, "", Dict())
options = merge(Weave.get_chunk_defaults(), chunk.options)
merge!(chunk.options, options)
chunk.figures = ["figs/figures_plot1.png"]
@test Weave.formatfigures(chunk, Weave.md2tex) == "\\includegraphics{figs/figures_plot1.png}\n"
@test Weave.formatfigures(chunk, Weave.tex) == "\\includegraphics{figs/figures_plot1.png}\n"
@test Weave.formatfigures(chunk, Weave.texminted) == "\\includegraphics{figs/figures_plot1.png}\n"
@test Weave.formatfigures(chunk, Weave.pandoc) == "![](figs/figures_plot1.png)\\ \n\n"
@test Weave.formatfigures(chunk, Weave.github) == "![](figs/figures_plot1.png)\n"
@test Weave.formatfigures(chunk, Weave.hugo) == "{{< figure src=\"../figs/figures_plot1.png\" >}}"
@test Weave.formatfigures(chunk, Weave.multimarkdown) == "![][figs/figures_plot1.png]\n\n[figs/figures_plot1.png]: figs/figures_plot1.png \n"
@test Weave.formatfigures(chunk, Weave.md2html) == "<img src=\"figs/figures_plot1.png\" />\n"
chunk.options[:out_width] = "100%"
@test Weave.formatfigures(chunk, Weave.adoc) == "image::figs/figures_plot1.png[width=100%]\n"
@test Weave.formatfigures(chunk, Weave.rst) == ".. image:: figs/figures_plot1.png\n :width: 100%\n\n"
chunk.options[:fig_cap] = "Nice plot"
@test Weave.formatfigures(chunk, Weave.tex) == "\\begin{figure}[!h]\n\\center\n\\includegraphics[width=1.0\\linewidth]{figs/figures_plot1.png}\n\\caption{Nice plot}\n\\end{figure}\n"
@test Weave.formatfigures(chunk, Weave.pandoc) == "![Nice plot](figs/figures_plot1.png){width=100%}\n"
@test Weave.formatfigures(chunk, Weave.md2tex) == "\\begin{figure}[!h]\n\\center\n\\includegraphics[width=1.0\\linewidth]{figs/figures_plot1.png}\n\\caption{Nice plot}\n\\end{figure}\n"
@test Weave.formatfigures(chunk, Weave.md2html) == "<figure>\n<img src=\"figs/figures_plot1.png\" width=\"100%\" />\n<figcaption>Nice plot</figcaption>\n</figure>\n"
@test Weave.formatfigures(chunk, Weave.rst) == ".. figure:: figs/figures_plot1.png\n :width: 100%\n\n Nice plot\n\n"
@test Weave.formatfigures(chunk, Weave.multimarkdown) == "![Nice plot][figs/figures_plot1.png]\n\n[figs/figures_plot1.png]: figs/figures_plot1.png width=100%\n"
@test Weave.formatfigures(chunk, Weave.adoc) == "image::figs/figures_plot1.png[width=100%,title=\"Nice plot\"]"
chunk.options[:label] = "somefig"
@test Weave.formatfigures(chunk, Weave.pandoc) == "![Nice plot](figs/figures_plot1.png){width=100% #fig:somefig}\n"
@test Weave.formatfigures(chunk, Weave.tex) == "\\begin{figure}[!h]\n\\center\n\\includegraphics[width=1.0\\linewidth]{figs/figures_plot1.png}\n\\caption{Nice plot}\n\\label{fig:somefig}\n\\end{figure}\n"
@test Weave.formatfigures(chunk, Weave.tex) == Weave.formatfigures(chunk, Weave.md2tex)
chunk.options[:label] = nothing
chunk.options[:fig_cap] = nothing
chunk.options[:fig_env] = "center"
chunk.options[:fig_pos] = ""
@test Weave.formatfigures(chunk, Weave.tex) == "\\begin{center}\n\\includegraphics[width=1.0\\linewidth]{figs/figures_plot1.png}\n\\end{center}\n"
chunk.options[:out_width] = "50%"
chunk.options[:out_height] = "75 %"
@test Weave.formatfigures(chunk, Weave.tex) == "\\begin{center}\n\\includegraphics[width=0.5\\linewidth,height=0.75\\paperheight]{figs/figures_plot1.png}\n\\end{center}\n"
chunk.options[:out_width] = "A%"
chunk.options[:out_height] = "0.5\\textwidth"
@test Weave.formatfigures(chunk, Weave.tex) == "\\begin{center}\n\\includegraphics[width=A%,height=0.5\\textwidth]{figs/figures_plot1.png}\n\\end{center}\n"

View File

@ -1,122 +0,0 @@
# Test rendering of doc chunks
content = """
# Test chunk
Test rendering \$\alpha\$
"""
dchunk = Weave.DocChunk(content, 1, 1)
pformat = Weave.formats["github"]
f = Weave.format_chunk(dchunk, pformat.formatdict, pformat)
@test f == content
docformat = Weave.formats["md2html"]
f_check = "<h1>Test chunk</h1>\n<p>Test rendering <span class=\"math\">\$\alpha\$</span></p>\n"
f = Weave.format_chunk(dchunk, docformat.formatdict, docformat)
@test f_check == f
# Test with actual doc
parsed = Weave.WeaveDoc("documents/chunk_options.noweb")
doc = run_doc(parsed, doctype = "md2html")
c_check = "<pre class='hljl'>\n<span class='hljl-n'>x</span><span class='hljl-t'> </span><span class='hljl-oB'>=</span><span class='hljl-t'> </span><span class='hljl-p'>[</span><span class='hljl-ni'>12</span><span class='hljl-p'>,</span><span class='hljl-t'> </span><span class='hljl-ni'>10</span><span class='hljl-p'>]</span><span class='hljl-t'>\n</span><span class='hljl-nf'>println</span><span class='hljl-p'>(</span><span class='hljl-n'>y</span><span class='hljl-p'>)</span>\n</pre>\n"
doc.format.formatdict[:theme] = doc.highlight_theme
c = Weave.format_code(doc.chunks[3].content, doc.format)
@test c_check == c
o_check = "\nprintln&#40;x&#41;\n"
o = Weave.format_output(doc.chunks[4].content, doc.format)
@test o_check == o
doc.template = "templates/mini.tpl"
rendered = Weave.render_doc("Hello", doc)
@test rendered == "\nHello\n"
# Tex format
parsed = Weave.WeaveDoc("documents/chunk_options.noweb")
doc = run_doc(parsed, doctype = "md2tex")
c_check = "\\begin{lstlisting}\n(*@\\HLJLnf{println}@*)(*@\\HLJLp{(}@*)(*@\\HLJLn{x}@*)(*@\\HLJLp{)}@*)\n\\end{lstlisting}\n"
doc.format.formatdict[:theme] = doc.highlight_theme
c = Weave.format_code(doc.chunks[4].content, doc.format)
@test c_check == c
o_check = "\nx = [12, 10]\nprintln(y)\n"
o = Weave.format_output(doc.chunks[3].content, doc.format)
@test o_check == o
doc.template = "templates/mini.tpl"
rendered = Weave.render_doc("Hello", doc)
@test rendered == "\nHello\n"
# Test wrapping
cows = repeat("🐄", 100)
testcows = """
🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄
🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄🐄"""
wcows = Weave.wrapline(cows)
@test wcows == testcows
@test length(split(wcows, "\n")[1]) == 75
@test length(split(wcows, "\n")[2]) == 25
tfied = "\\ensuremath{\\bm{\\mathrm{L}}} \\ensuremath{\\bm{\\mathfrak{F}}} \\ensuremath{\\bm{\\iota}} \\ensuremath{\\mathfrak{A}} \\ensuremath{\\bm{\\varTheta}}"
@test Weave.uc2tex("𝐋 𝕱 𝛊 𝔄 𝚹") == tfied
# Test markdown output from chunks
parsed = Weave.WeaveDoc("documents/markdown_output.jmd")
doc = run_doc(parsed, doctype = "md2html")
@test doc.chunks[1].rich_output == "\n<div class=\"markdown\"><h3>Small markdown sample</h3>\n<p><strong>Hello</strong> from <code>code</code> block.</p>\n</div>"
@test doc.chunks[2].rich_output == "\n<div class=\"markdown\"><ul>\n<li><p>one</p>\n</li>\n<li><p>two</p>\n</li>\n<li><p>three</p>\n</li>\n</ul>\n</div>"
ldoc = run_doc(parsed, doctype = "md2tex")
@test ldoc.chunks[1].rich_output == "\n\\subsubsection{Small markdown sample}\n\\textbf{Hello} from \\texttt{code} block.\n\n"
@test ldoc.chunks[2].rich_output == "\n\\begin{itemize}\n\\item one\n\n\n\\item two\n\n\n\\item three\n\n\\end{itemize}\n"
mdoc = run_doc(parsed, doctype = "github")
@test mdoc.chunks[1].rich_output == "\n\n### Small markdown sample\n\n**Hello** from `code` block.\n\n"
@test mdoc.chunks[2].rich_output == "\n\n* one\n* two\n* three\n\n"
# Test disable escaping of unicode
@testset "escape/unescape unicode characters" begin
content = """
# Test chunk
α
"""
chunk = Weave.DocChunk(content, 1, 1)
fmt = deepcopy(Weave.formats["md2tex"])
fmtdict = fmt.formatdict
f = Weave.format_chunk(chunk, fmtdict, fmt)
@test f == "\\section{Test chunk}\n\\ensuremath{\\alpha}\n\n"
fmtdict[:keep_unicode] = true
f = Weave.format_chunk(chunk, fmtdict, fmt)
@test f == "\\section{Test chunk}\nα\n\n"
str = """
```julia
α = 10
```
"""
doc = mock_doc(str; doctype = "md2tex")
doc = Weave.format(doc)
@test occursin(Weave.uc2tex("α"), doc)
@test !occursin("α", doc)
doc = mock_doc(str; doctype = "md2tex")
doc.format.formatdict[:keep_unicode] = true
doc = Weave.format(doc)
@test occursin("α", doc)
@test !occursin(Weave.uc2tex("α"), doc)
end

View File

@ -1,31 +0,0 @@
# Test for Gadfly with different chunk options and figure formatsusing Weave
using Gadfly, Cairo
function test_gadfly(doctype, fig_ext)
out = weave(
joinpath(@__DIR__ , "documents/gadfly_formats_test.jnw"),
doctype = doctype,
fig_ext = fig_ext
)
result = read(out, String)
# cp(out, out*fig_ext*"."*doctype, force=true) # Used when adding new tests
ref = read(out*fig_ext*"."*doctype, String)
@test result == ref
rm(out)
end
test_gadfly("github", ".png")
test_gadfly("github", ".pdf")
test_gadfly("github", ".svg")
test_gadfly("pandoc", ".png")
test_gadfly("pandoc", ".js.svg")
test_gadfly("tex", ".pdf")
test_gadfly("tex", ".png")
test_gadfly("tex", ".ps")
test_gadfly("tex", ".tex")
p = Gadfly.plot(x=1:10, y=1:10)
@test showable(MIME"application/pdf"(), p) == true
@test showable(MIME"application/png"(), p) == true

View File

@ -1,47 +0,0 @@
using Mustache
# Test parsing
doc = """
! println("Something")
Some markdown with inline stuff and `j code`
! Not julia code but `j show("is")`
"""
ms = collect(eachmatch(Weave.INLINE_REGEXES, doc))
@test ms[1][2] == "println(\"Something\")"
@test ms[2][1] == "code"
@test ms[3][1] == "show(\"is\")"
let
_, chunks = Weave.parse_markdown(doc)
chunk = first(chunks)
@test length(chunk.content) == 7
@test chunk.content[2].content == ms[1][2]
@test chunk.content[4].content == ms[2][1]
@test chunk.content[6].content == ms[3][1]
end
let
_, chunks = Weave.parse_markdown(doc)
chunk = first(chunks)
@test all([chunk.content[i].content == chunk.content[i].content for i in 1:7])
end
# Test with document
tpl = mt"""
{{{ :body }}}
"""
out = weave(joinpath(@__DIR__, "documents", "markdown_beamer.jmd"), doctype="md2html", template=tpl)
@test read(out, String) == read(out*".ref", String)
rm(out)
out = weave(joinpath(@__DIR__, "documents", "markdown_beamer.jmd"), doctype="md2tex", template=tpl)
@test read(out, String) == read(out*".ref", String)
rm(out)

View File

@ -1,6 +1,9 @@
using Test
import Weave: WeaveMarkdown
import Markdown
# TODO: make this more sensible:
# - separate tests for
# 1. features that are "copy-and-pasted" from `Markdown` module
# 2. features that are extended by Weave
using Weave: WeaveMarkdown, Markdown
# Test markdown2html writer

2
test/mocks/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
*
!.gitignore

View File

@ -1,7 +0,0 @@
file = joinpath(@__DIR__, "documents", "jupyter_test.jmd")
using IJulia, Conda
Conda.add("nbconvert") # should be the same as IJulia.JUPYTER, i.e. the miniconda Python
Weave.notebook(file, jupyter_path = IJulia.JUPYTER)
@test "jupyter_test.ipynb" readdir(@__DIR__) # test if the result was weaved

View File

@ -1,22 +0,0 @@
using Plots
function pljtest(source, resfile, doctype)
weave("documents/$source", out_path = "documents/plotsjl/$resfile", doctype=doctype)
result = read("documents/plotsjl/$resfile", String)
ref = read("documents/plotsjl/$resfile.ref", String)
@test result == ref
rm("documents/plotsjl/$resfile")
end
pljtest("plotsjl_test_gr.jmd", "plotsjl_test_gr.md", "pandoc")
pljtest("plotsjl_test_gr.jmd", "plotsjl_test_gr.tex", "tex")
# test cache with plots
isdir("documents/cache") && rm("documents/cache", recursive = true)
weave("documents/plotsjl_test_gr.jmd", cache=:all)
result = read("documents/plotsjl_test_gr.html", String)
rm("documents/plotsjl_test_gr.html")
weave("documents/plotsjl_test_gr.jmd", cache=:all)
cached_result = read("documents/plotsjl_test_gr.html", String)
@test result == cached_result

View File

@ -0,0 +1,102 @@
using Weave: parse_options, parse_markdown
@testset "`parse_options`" begin
# general
@test isempty(parse_options(""))
@test (:opt => nothing) in parse_options("opt = nothing")
# Weave style -- semicolon separated
let opts = parse_options("opt1 = 1; opt2 = \"2\"")
@test (:opt1 => 1) in opts
@test (:opt2 => "2") in opts
end
# robust parsing
@test let opts = parse_options("invalid; valid = nothing")
@test (:valid => nothing) in opts
true
end
# RMarkdown style -- comma separated
let opts = parse_options("opt1 = 1, opt2 = \"2\"")
@test (:opt1 => 1) in opts
@test (:opt2 => "2") in opts
end
# robust parsing
@test let opts = parse_options("invalid, valid = nothing")
@test (:valid => nothing) in opts
true
end
end
@testset "`parse_markdown` Julia markdown format" begin
get_options(str) =
(chunk = first(last(parse_markdown(str))); @test hasproperty(chunk, :options); chunk.options)
# Julia markdown
@test get_options("```julia\n```") |> length === 1
@test get_options("```julia \n```") |> length === 1
@test get_options("```{julia}\n```") |> length === 1
@test get_options("```{julia }\n```") |> length === 1
# Weave style -- semicolon separated
@test get_options("```julia;\n```") |> length === 1
@test get_options("```julia ;\n```") |> length === 1
@test get_options("```julia; \n```") |> length === 1
@test (:opt => nothing) in get_options("```julia; opt = nothing\n```")
@test (:opt => nothing) in get_options("```{julia; opt = nothing}\n```")
let opts = get_options("```julia; opt1 = 1; opt2 = \"2\"\n```")
@test (:opt1 => 1) in opts
@test (:opt2 => "2") in opts
end
let opts = get_options("```{julia; opt1 = 1; opt2 = \"2\"}\n```")
@test (:opt1 => 1) in opts
@test (:opt2 => "2") in opts
end
# RMarkdown style -- comma separated
@test get_options("```julia,\n```") |> length === 1
@test get_options("```julia ,\n```") |> length === 1
@test get_options("```julia, \n```") |> length === 1
@test (:opt => nothing) in get_options("```julia, opt = nothing\n```")
@test (:opt => nothing) in get_options("```{julia, opt = nothing}\n```")
let opts = get_options("```{julia, opt1 = 1, opt2 = \"2\"}\n```")
@test (:opt1 => 1) in opts
@test (:opt2 => "2") in opts
end
let opts = get_options("```julia, opt1 = 1, opt2 = \"2\"\n```")
@test (:opt1 => 1) in opts
@test (:opt2 => "2") in opts
end
let opts = get_options("```julia{opt1 = 1, opt2 = \"2\"}\n```")
@test (:opt1 => 1) in opts
@test (:opt2 => "2") in opts
end
end
@testset "`parse_markdown` pandoc format" begin
get_options(str) =
(chunk = first(last(parse_markdown(str; is_pandoc = true))); @test hasproperty(chunk, :options); chunk.options)
@test get_options("<<>>=\n@") |> length === 1
@test (:opt => nothing) in get_options("<<opt = nothing>>=\n@")
let opts = get_options("<<opt1 = 1; opt2 = \"2\">>=\n@")
@test (:opt1 => 1) in opts
@test (:opt2 => "2") in opts
end
let opts = get_options("<<opt1 = 1, opt2 = \"2\">>=\n@")
@test (:opt1 => 1) in opts
@test (:opt2 => "2") in opts
end
end
# TODO: tests for `"script"` format ?

View File

@ -0,0 +1,99 @@
# TODO: test evaluation
using Weave.Mustache
using Weave: parse_inlines, InlineText, InlineCode
@testset "`parse_inlines` basic" begin
@test filter(parse_inlines("text")) do chunk
chunk isa InlineCode
end |> isempty
@test filter(parse_inlines("text")) do chunk
chunk isa InlineText &&
chunk.content == "text"
end |> length === 1
@test filter(parse_inlines("`j code`")) do chunk
chunk isa InlineCode &&
chunk.ctype === :inline &&
chunk.content == "code"
end |> length == 1
@test filter(parse_inlines("! code")) do chunk
chunk isa InlineCode &&
chunk.ctype === :line &&
chunk.content == "code"
end |> length == 1
@test filter(parse_inlines("text ! maybe_intended_to_be_code")) do chunk # invalid inline chunk
chunk isa InlineText &&
chunk.content == "maybe_intended_to_be_code"
end |> isempty
end
@testset "`parse_inlines` multiple lines" begin
str = """
- item1
- `j code`
- item2
"""
chunks = parse_inlines(str)
let chunk = chunks[1]
@test chunk isa InlineText
@test occursin("- item1", chunk.content)
end
let chunk = chunks[2]
@test chunk isa InlineCode
@test occursin("code", chunk.content)
end
let chunk = chunks[3]
@test chunk isa InlineText
@test occursin("- item2", chunk.content)
end
end
@testset "`parse_inlines` unicode handling" begin
str = """
- eng1 `j :eng1`
- eng2`j :eng2`
- 日本語1 `j :日本語1`
- 日本語2`j :日本語2`
"""
chunks = parse_inlines(str)
@test filter(chunks) do chunk
chunk isa InlineCode &&
chunk.number === 1 &&
chunk.content == ":eng1"
end |> length === 1
@test filter(chunks) do chunk
chunk isa InlineCode &&
chunk.number === 2 &&
chunk.content == ":eng2"
end |> length === 1
@test filter(chunks) do chunk
chunk isa InlineCode &&
chunk.number === 3 &&
chunk.content == ":日本語1"
end |> length === 1
@test filter(chunks) do chunk
chunk isa InlineCode &&
chunk.number === 4 &&
chunk.content == ":日本語2"
end |> length === 1
end

30
test/render/texformats.jl Normal file
View File

@ -0,0 +1,30 @@
@testset "unicode to latex conversion" begin
unicode2latex(args...) = Weave.unicode2latex(get_format("md2tex"), args...)
# unit test
let
s = unicode2latex("α = 10")
@test !occursin("α", s)
@test occursin("alpha", s)
end
# end2end
let
str = """
```julia
α = 10
```
"""
doc = mock_run(str; doctype = "md2tex")
Weave.set_format_options!(doc.format)
rendered = Weave.render_doc(doc)
@test occursin("alpha", rendered)
@test !occursin("α", rendered)
doc = mock_run(str; doctype = "md2tex")
Weave.set_format_options!(doc.format; keep_unicode = true)
rendered = Weave.render_doc(doc)
@test !occursin("alpha", rendered)
@test occursin("α", rendered)
end
end # @testset "rendering tex formats"

Some files were not shown because too many files have changed in this diff Show More