Compare commits

...

394 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 c24920870d version 0.10.2 2020-05-23 22:51:33 +09:00
Shuhei Kadowaki f4caba1561 maxlog for deprecation warning 2020-05-23 22:51:17 +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
Shuhei Kadowaki af45cc01ab even more clean up 2020-05-23 22:03:40 +09:00
Shuhei Kadowaki 31f670b74c
Merge pull request #339 from JunoLab/avi/pandoc
refactor pandoc code:
2020-05-23 21:59:42 +09:00
Shuhei Kadowaki 0cdcc72bfb version 0.10.1 2020-05-23 21:57:05 +09:00
Shuhei Kadowaki 3ee7dec864
Merge pull request #340 from JunoLab/avi/emptyheader
fix case when `weave_options` are empty
2020-05-23 21:55:38 +09:00
Shuhei Kadowaki 0f94c7b49c fix case when `weave_options` are empty 2020-05-23 21:18:16 +09:00
Shuhei Kadowaki 54ccd9b1ed refactor pandoc code:
- more sensible err handling
- annotate TODO comments
2020-05-23 21:15:05 +09:00
Shuhei Kadowaki 3f4ba672b3 Revert "rm unused dict push!"
This reverts commit ef295e9a24.
2020-05-23 20:07:59 +09:00
Shuhei Kadowaki 745abe176c Revert "rm unused field from WeaveDoc"
This reverts commit 301f9b2f27.
2020-05-23 20:07:41 +09:00
Shuhei Kadowaki 301f9b2f27 rm unused field from WeaveDoc 2020-05-23 20:03:38 +09:00
Shuhei Kadowaki ef295e9a24 rm unused dict push! 2020-05-23 19:52:00 +09:00
Shuhei Kadowaki a03a1d4c34 EXAMPLE_FOLDER 2020-05-23 19:42:19 +09:00
Shuhei Kadowaki daec0e618f version 0.10 2020-05-18 23:45:47 +09:00
Shuhei Kadowaki 129a654b1d
Merge pull request #334 from JunoLab/avi/deprecate
deprecate `options`, change to `weave_options`:
2020-05-18 23:44:15 +09:00
Shuhei Kadowaki 500d77c9ca
Merge pull request #335 from JunoLab/avi/doc
doc improvements
2020-05-18 23:15:35 +09:00
Shuhei Kadowaki 8aa8f0c4df easy doc access 2020-05-18 22:59:18 +09:00
Shuhei Kadowaki ec0c0a327f format NEWS.md 2020-05-18 22:14:41 +09:00
Shuhei Kadowaki b4c2bbea45 deprecate `options`, change to `weave_options`:
- avoid unexpected header stripping (`options` sounds too general)
- deprecated `options` support will be remove within ≥v0.11
2020-05-18 22:10:26 +09:00
Shuhei Kadowaki 5e5cb875cf fix doc generation, add issue template 2020-05-17 13:03:19 +09:00
Shuhei Kadowaki 576ca2b6c9 some doc fix:
- update functions
- only make examples in CI
2020-05-17 12:23:41 +09:00
Shuhei Kadowaki 4113402908 rename `latex_keep_unicode` to `keep_unicode`, handle this in `format` 2020-05-17 12:17:24 +09:00
Shuhei Kadowaki 249c94a5c1 avoid manipulation of global struct 2020-05-17 12:14:30 +09:00
Shuhei Kadowaki 101b170ea6 some support for dynamic YAML `weave` configuration 2020-05-17 11:45:39 +09:00
Shuhei Kadowaki 6d1732247a a bit refactor 2020-05-17 11:10:25 +09:00
Shuhei Kadowaki b7233b468e no `term` option for inline code chunk 2020-05-17 11:05:30 +09:00
Shuhei Kadowaki 405deb3681 reorder things 2020-05-17 10:30:33 +09:00
Shuhei Kadowaki 87ba87d2d1 resolve CSS theme path relative to a target document when given in YAML 2020-05-17 10:29:01 +09:00
Shuhei Kadowaki cec388e94f add Weave version 2020-05-17 01:16:59 +09:00
Shuhei Kadowaki 0831144393
Merge pull request #311 from JunoLab/avi/limitdisplay
limit display:
2020-05-17 00:18:12 +09:00
Shuhei Kadowaki e60f066d31 fix when a header value is not `String` 2020-05-16 23:45:41 +09:00
Shuhei Kadowaki f86f5a7bd0 preserve header when weaving to Hugo markdown 2020-05-16 23:31:27 +09:00
Shuhei Kadowaki f9daa3a289 add test for HTML display limit 2020-05-16 23:25:44 +09:00
Shuhei Kadowaki 91403b4ec0 fix typo 2020-05-16 23:11:05 +09:00
Shuhei Kadowaki 5fb3fae741 no ANSI chars 2020-05-16 23:11:05 +09:00
Shuhei Kadowaki 7b53eb8e9e limit display:
- for now if we try to render a "big object" like a table with many 
rows, Weave tries to render all of the result and it can lead to that a 
document can't even be opened
2020-05-16 23:11:05 +09:00
Shuhei Kadowaki 58bc741b7f detect doctype when running a doc 2020-05-16 23:10:44 +09:00
Shuhei Kadowaki a740ba3556
Merge pull request #331 from JunoLab/avi/progres
integrate with Juno progress bar
2020-05-16 21:29:33 +09:00
Shuhei Kadowaki bca3ee7dd1 LTS compat ... 2020-05-16 21:04:58 +09:00
Shuhei Kadowaki ba8e9f4724 fix header handling in noweb doc 2020-05-16 20:33:48 +09:00
Shuhei Kadowaki 6121d21bfb fix doc syntax highlight 2020-05-16 19:53:09 +09:00
Shuhei Kadowaki 99a50ad86f integrate with Juno progress bar 2020-05-16 19:52:56 +09:00
Shuhei Kadowaki 2a6ee38850 fix code chunk line numbers 2020-05-16 19:52:24 +09:00
Shuhei Kadowaki 11c720ad7f
Merge pull request #329 from JunoLab/avi/dynamic
dynamic YAML parsing
2020-05-16 18:57:07 +09:00
Shuhei Kadowaki c1cf566c53 refactor format.jl 2020-05-16 17:59:17 +09:00
Shuhei Kadowaki 0d3d3a8c19 rm code ... 2020-05-16 17:59:04 +09:00
Shuhei Kadowaki 6d91ab6512 no explicit header support in `convert_doc` 2020-05-16 17:53:46 +09:00
Shuhei Kadowaki 98abd5e92e write documentation for dynamic header 2020-05-16 17:52:17 +09:00
Shuhei Kadowaki 6100083c9e update test 2020-05-16 16:05:02 +09:00
Shuhei Kadowaki 6955ca6be2 add test for header processing 2020-05-16 01:49:55 +09:00
Shuhei Kadowaki 17c2151d86 a bit refactor:
- don't match slide `---` separator as header start/end
- recognize `doctype` in construction
2020-05-16 01:49:30 +09:00
Shuhei Kadowaki 492d1f330b dynamic YAML option specification 2020-05-16 01:47:52 +09:00
Shuhei Kadowaki 95c3dac962
Merge pull request #330 from JunoLab/avi/refactor
refactor
2020-05-16 01:25:25 +09:00
Shuhei Kadowaki 42115e7d52 rename writer.jl -> converter.jl 2020-05-16 00:43:33 +09:00
Shuhei Kadowaki 094ebea6cf simplify converter functions 2020-05-16 00:32:28 +09:00
Shuhei Kadowaki 7c2eb23bcd small refactors (mostly about code styles) 2020-05-16 00:32:09 +09:00
Shuhei Kadowaki 589e1ce3d1
Merge pull request #327 from JunoLab/avi/clean
more test clean up
2020-05-11 14:33:53 +09:00
Shuhei Kadowaki 1ddff9a1b7 more test clean up 2020-05-11 09:40:10 +09:00
Shuhei Kadowaki 636e3540c7
Merge pull request #325 from JunoLab/avi/header
rm header_args
2020-05-10 16:25:34 +09:00
Shuhei Kadowaki bc0f687352 rm header_args 2020-05-10 15:55:37 +09:00
Shuhei Kadowaki 2c7f3da7cc
Merge pull request #324 from JunoLab/avi/cleanup
rm unused tests
2020-05-10 15:54:46 +09:00
Shuhei Kadowaki 423146f981 rm unused tests 2020-05-10 15:27:14 +09:00
Shuhei Kadowaki 2e19930565
Merge pull request #323 from JunoLab/avi/bang
use bangs for destructive functions
2020-05-10 14:28:40 +09:00
Shuhei Kadowaki de2a6657ea rm appveyor 2020-05-10 14:11:10 +09:00
Shuhei Kadowaki 867ad7c954 update LICENSE 2020-05-10 14:10:46 +09:00
Shuhei Kadowaki 54e50a54cb users should load Cairo 2020-05-10 14:07:55 +09:00
Shuhei Kadowaki d809ddf703
Merge pull request #322 from JunoLab/avi/require
don't load Weave Plots submodules into user's module
2020-05-10 14:06:09 +09:00
Shuhei Kadowaki e459bfb87d use bangs for destructive functions 2020-05-10 13:56:09 +09:00
Shuhei Kadowaki 98e44db659
Merge pull request #321 from JunoLab/avi/noauto
internal API improvements
2020-05-10 13:49:33 +09:00
Shuhei Kadowaki ede31bcf74 don't load Weave Plots submodules into user's module 2020-05-10 13:35:54 +09:00
Shuhei Kadowaki e89d5da250 rm unncessary `Symbol` spec:
- change `informat` and `doctype` options to 
`Union{NothingAbstractString}`
2020-05-10 13:20:44 +09:00
Shuhei Kadowaki 4b6fc2d913 fix typings 2020-05-10 00:01:49 +09:00
Shuhei Kadowaki c825076e36 simplify imports 2020-05-10 00:01:41 +09:00
Shuhei Kadowaki 68f72bdfb3 small updates 2020-05-09 23:55:11 +09:00
Shuhei Kadowaki ca42e09f8d
Merge pull request #313 from JunoLab/avi/sandbox
internal refactor step 1
2020-05-09 23:53:49 +09:00
Shuhei Kadowaki a526cb8f15
Merge pull request #319 from JunoLab/avi/weavedoc
remove weird default constructor for `WeaveDoc`
2020-05-09 23:39:03 +09:00
Shuhei Kadowaki f1df02c2b7
Merge pull request #320 from JunoLab/avi/robusttest
more robust error rendering test
2020-05-09 23:17:24 +09:00
Shuhei Kadowaki 4dae2a0816 `WEAVE_OPTION_NAME` 2020-05-09 22:42:05 +09:00
Shuhei Kadowaki 8303311d59 more robust error rendering test 2020-05-09 22:35:45 +09:00
Shuhei Kadowaki 36bdd4f82b remove weird default constructor for `WeaveDoc` 2020-05-09 22:33:58 +09:00
Shuhei Kadowaki 5f7cf529b9 chunks.jl -> types.jl 2020-05-09 21:03:00 +09:00
Shuhei Kadowaki 66d32fabe8
Merge pull request #318 from JunoLab/avi/refactorreader
refactor readers.jl
2020-05-09 21:00:35 +09:00
Shuhei Kadowaki 750b7624e0 refactor readers.jl:
- avoid unnecessary overloading on `parse_doc`
- split readers.jl into multiple scripts
2020-05-09 20:17:53 +09:00
Shuhei Kadowaki 8b910c0d70
Merge pull request #317 from JunoLab/avi/clearsandbox
clear sandbox module correctly
2020-05-09 18:56:44 +09:00
Shuhei Kadowaki 3b8201df04 add test for `clear_module!` 2020-05-09 18:22:24 +09:00
Shuhei Kadowaki 79579053f1 refactor tests:
- simpler module evaluation test
- remove useless include_weave test
2020-05-09 17:27:51 +09:00
Shuhei Kadowaki d4413a1d78 clear sandbox module correctly 2020-05-09 16:09:11 +09:00
Shuhei Kadowaki 5dbe54316b isnothing utility 2020-05-09 11:26:32 +09:00
Shuhei Kadowaki e41202d3ff no weird Base.run overload 2020-05-09 11:25:19 +09:00
Shuhei Kadowaki 14e7635458 getvalue -> get 2020-05-09 11:25:19 +09:00
Shuhei Kadowaki ac486c5e1d
Merge pull request #316 from JunoLab/avi/dev
ensure Weave display pops out even if an internal err occurs
2020-05-09 11:16:03 +09:00
Shuhei Kadowaki 9a1b81a026
Merge pull request #315 from JunoLab/avi/bumpplot
bump Plots.jl version
2020-05-09 03:25:18 +09:00
Shuhei Kadowaki 4e7fda212d ensure Weave display pops out even if an internal err occurs 2020-05-09 02:48:56 +09:00
Shuhei Kadowaki b25300b269 bump Plots.jl version 2020-05-09 02:48:09 +09:00
Shuhei Kadowaki 0c59e92fd7
Merge pull request #312 from JunoLab/avi/format
format things
2020-05-09 01:10:44 +09:00
Shuhei Kadowaki 2376a9dae9 format things 2020-05-08 23:39:17 +09:00
Shuhei Kadowaki 020b4353a4 fix indents, Github -> GitHub 2020-05-06 23:37:04 +09:00
Shuhei Kadowaki 36bce9cf1f
Merge pull request #305 from JunoLab/avi/headers
more graceful header handling
2020-04-23 00:44:51 +09:00
Shuhei Kadowaki db13be44e3 fix no header case 2020-04-18 19:18:03 +09:00
Shuhei Kadowaki 95e32c4908 more graceful header handling 2020-04-18 19:10:07 +09:00
Shuhei Kadowaki 8bbe31324f
Merge pull request #302 from baggepinnen/keepfigures
Keep latex figures [replaces #274]
2020-04-17 18:59:16 +09:00
Fredrik Bagge Carlson f126e1c7a9 fix formatting 2020-04-17 12:16:56 +08:00
Fredrik Bagge Carlson 7e88052db3 keep latex figures 2020-04-17 12:16:56 +08:00
Shuhei Kadowaki 67126a515a update README 2020-04-01 19:04:55 +09:00
Shuhei Kadowaki 3a3385471b
Merge pull request #297 from JunoLab/avi/buildpdf
upload (locally) prebuilt PDF example outputs
2020-04-01 18:28:08 +09:00
Shuhei Kadowaki 20fd22ec75 upload prebuilt PDF examples 2020-04-01 18:26:59 +09:00
Shuhei Kadowaki f1e87123f4
Merge pull request #296 from JunoLab/avi/notebook
Specify HTML as a default output format for weaving notebooks
2020-03-28 01:14:17 +09:00
Shuhei Kadowaki d40e21ea35 improve documentations around notebooks 2020-03-27 20:43:33 +09:00
Shuhei Kadowaki a759dc10bd specify default output format (HMTL) for notebooks 2020-03-27 20:34:06 +09:00
Shuhei Kadowaki b6b4082977
Merge pull request #295 from JunoLab/avi/moretypes
more type annotate APIs
2020-03-27 19:12:51 +09:00
Shuhei Kadowaki 840f1b3b8f simpler doc APIs 2020-03-27 18:45:04 +09:00
Shuhei Kadowaki efccb5c7f1 more documentation improve 2020-03-27 10:16:57 +09:00
Shuhei Kadowaki dfb9e63d0e update travis 2020-03-26 21:42:31 +09:00
Shuhei Kadowaki 9e9fe45231 improve documentations 2020-03-26 21:41:54 +09:00
Shuhei Kadowaki 7a7d8f3dde update documentation source accordingly 2020-03-26 17:35:43 +09:00
Shuhei Kadowaki f8c32c865b more type annotate APIs 2020-03-26 17:35:05 +09:00
Shuhei Kadowaki 529edaf94e version 0.9.4 2020-03-18 18:19:23 +09:00
Shuhei Kadowaki e1365ba9b5
Merge pull request #294 from JunoLab/avi/rmcompat
rm Compat
2020-03-18 18:05:32 +09:00
Shuhei Kadowaki 16bc2d7be9 immutable structs for result trait 2020-03-18 10:50:01 +09:00
Shuhei Kadowaki 545baecdaa bump YAML (closes #291) 2020-03-18 10:23:27 +09:00
Shuhei Kadowaki 6339303569 rm Compat 2020-03-18 08:53:25 +09:00
Shuhei Kadowaki 62ae84d32d
Merge pull request #292 from JunoLab/avi/plotfix
fixes on plotting
2020-03-17 12:15:31 +09:00
Shuhei Kadowaki 1f8514a737 fixes: #105, #288
closes: #289
2020-03-17 10:57:36 +09:00
Shuhei Kadowaki 5fd0bcb9ee re: update image 2020-03-06 20:52:09 +09:00
Shuhei Kadowaki 47323b37f7 update Juno integration image 2020-03-06 20:23:44 +09:00
Shuhei Kadowaki d8595e266f more doc fixes 2020-03-06 10:14:21 +09:00
Shuhei Kadowaki 230a8c5454 more fix doc syntax 2020-03-06 09:59:32 +09:00
Shuhei Kadowaki db0aa06f38 fix doc syntax 2020-03-06 09:20:32 +09:00
Shuhei Kadowaki 32bddc543f add version compat for Compat 2020-03-06 09:19:00 +09:00
Shuhei Kadowaki 0f5e3df9aa
Merge pull request #285 from JunoLab/avi/docbuild
fix doc url and reenable doc build
2020-03-06 02:41:07 +09:00
Shuhei Kadowaki deeb54dc7c fix doc url and reenable doc build 2020-03-06 01:08:07 +09:00
Shuhei Kadowaki 372974e1ad
Merge pull request #281 from kleinschmidt/dfk/code-size
use 0.9em for code size instead of hard coding 13px
2020-03-05 20:25:40 +09:00
Sebastian Pfitzner 7c58a284ee
Merge pull request #283 from JunoLab/compathelper/new_version/2020-03-05-00-07-25-058-3363680067
CompatHelper: add new compat entry for "Requires" at version "1.0"
2020-03-05 10:49:53 +01:00
Sebastian Pfitzner 04ed58102d
Merge pull request #282 from JunoLab/compathelper/new_version/2020-03-05-00-07-19-291-3538927573
CompatHelper: add new compat entry for "JSON" at version "0.21"
2020-03-05 10:49:44 +01:00
github-actions[bot] a250a48499 CompatHelper: add new compat entry for "Requires" at version "1.0" 2020-03-05 00:07:25 +00:00
github-actions[bot] ae8812de51 CompatHelper: add new compat entry for "JSON" at version "0.21" 2020-03-05 00:07:19 +00:00
Dave Kleinschmidt 9ae54c80d6 bump patch version 2020-03-04 16:32:24 -05:00
Dave Kleinschmidt 048603ffe6 use 0.9em for code size instead of hard coding 13px 2020-03-04 16:29:32 -05:00
Sebastian Pfitzner ab5db9aa24
Merge pull request #279 from aviatesk/release
Release 0.9.2
2020-03-04 12:09:05 +01:00
Shuhei Kadowaki c020fea642 fix matrix&jobs 2020-03-04 19:37:36 +09:00
Shuhei Kadowaki 2aa7cb7ca5 several documentation updates 2020-03-04 19:23:48 +09:00
Shuhei Kadowaki 4dfa7da71f update doc deps 2020-03-04 19:20:03 +09:00
Shuhei Kadowaki 4cfcc61fb6 introduce compat helper 2020-03-04 18:01:36 +09:00
Shuhei Kadowaki d9b37f8244 fix compats 2020-03-04 18:01:26 +09:00
Sebastian Pfitzner 79a3d73882
Merge pull request #268 from aviatesk/update
updates
2020-03-04 09:25:52 +01:00
Shuhei Kadowaki d4ce8cdb6b update travis 2020-03-04 02:05:04 +09:00
Sebastian Pfitzner d108e4a1dc
Merge pull request #272 from JuliaTagBot/master
Install TagBot as a GitHub Action
2020-02-18 13:10:23 +01:00
Julia TagBot fd216ca1f5 Install TagBot as a GitHub Action 2020-02-08 20:51:08 +07:00
aviatesk e18c5f35e3 update comment 2020-01-07 23:51:55 +09:00
aviatesk d0ecc30f52 bump version 2020-01-05 16:11:19 +09:00
aviatesk 6ca6c51ea6 rm REQUIRE 2020-01-05 15:21:02 +09:00
aviatesk 652b19cd0f fixes #232 2020-01-05 15:18:41 +09:00
Sebastian Pfitzner 72e7ccfe8a
Merge pull request #257 from aminya/patch-1
Update old markdown link
2019-11-04 09:23:39 +01:00
Amin Yahyaabadi a64fccbf2c
Update old markdown link 2019-11-03 07:00:37 -06:00
Sebastian Pfitzner 585c4111b6
Merge pull request #255 from sebastianpech/fix-test
Fix inline tests after Highlights update
2019-10-23 09:04:01 +02:00
Sebastian Pech 05c93b8607 Fix inline tests after Highlights update 2019-10-22 20:10:27 +02:00
Sebastian Pfitzner 3d673d0338
Merge pull request #244 from sebastianpech/disable-unicode-escape
Add argument to weave function to disable unicode escape
2019-10-21 19:48:29 +02:00
Sebastian Pech c9e26d5638 Rename escape_unicode and move to tex based formatdicts 2019-10-15 21:48:05 +02:00
Sebastian Pech 0018f0e24c Fix new expected output in ref for new escape char 2019-10-15 17:18:50 +02:00
Sebastian Pech da66a8f272 Add escape_unicode to docstring 2019-10-15 14:20:11 +02:00
Sebastian Pfitzner d31d16581b
Merge pull request #247 from xiaodaigh/patch-1
Update usage.md
2019-09-29 10:57:02 +02:00
evalparse 31d3c2da56
Update usage.md 2019-09-28 17:41:54 +10:00
Sebastian Pfitzner b01b18ea2f
Merge pull request #241 from sebastianpech/figures
Improve usage of different figure environments in latex
2019-09-05 12:34:45 +02:00
Sebastian Pech bd5ff7031c Add argument for disabling unicode escaping 2019-09-05 10:13:49 +02:00
Sebastian Pfitzner 9fa28726ed
Merge pull request #243 from MatFi/patch-1
Fixed missing comma in example
2019-09-03 10:35:39 +02:00
MatFi 4fcee4d0e2
Update getting_started.md 2019-09-03 10:07:35 +02:00
Sebastian Pfitzner 3be6245820
Merge pull request #225 from devmotion/patch-1
Update badges
2019-08-29 12:39:48 +02:00
Sebastian Pech fa4a1a629d Add function to convert percentages to matching latex widths 2019-08-25 19:19:31 +02:00
Sebastian Pech 1b450b9e3d Fix docs \linewidth and fig_pos defaulting to !h 2019-08-25 17:16:59 +02:00
Sebastian Pech eeb723981d Fix printing [] if fig_env is empty string 2019-08-25 10:25:57 +02:00
Sebastian Pech 474cb6e4b2 Combine formatfigures for Tex and JMarkdown2tex 2019-08-25 09:39:03 +02:00
Tamas Nagy 51903c3df3
Merge pull request #239 from sebastianpech/Fixcaptureoutput
Fix displayed output produced by capture_output
2019-08-22 10:59:02 -07:00
Sebastian Pech 4d7a444246 Fix displayed output produced by capture_output 2019-08-21 15:03:22 +02:00
Tamas Nagy e7e5bd7c7f
explicitly add julia to compat section
see https://github.com/JuliaRegistries/General/pull/1616#issuecomment-506636070
2019-07-01 13:26:12 -07:00
David Widmann 18cce8472b
Update badges
The section "Documentation" in the README still contained the old broken links. Appveyor and Coveralls badges should be added again once the services are enabled for the moved repository.
2019-06-29 00:54:38 +02:00
Kevin Bonham 36464be927 Fix docs links in README (#224)
These links are giving 404 errors, so I thought I'd fix them :-)
2019-06-28 21:01:03 +03:00
ilia-kats 02134d29d5 use the minted jlcon lexer for terminal mode (#205) 2019-06-27 09:00:43 +03:00
Viral B. Shah 59edca786d
Create FUNDING.yml 2019-06-26 17:44:20 -04:00
Sebastian Pfitzner ed41be610a
Merge pull request #221 from thofma/master
Add html rendering of Markdown tables
2019-06-26 12:10:46 +02:00
Tommy Hofmann 1c0506342e Add html rendering of Markdown tables 2019-06-26 11:19:11 +02:00
Sebastian Pfitzner 9f664ba5a6
Merge pull request #202 from tshort/hook-fix
Fix hooks and add a push/pop hook to the test
2019-06-25 18:10:38 +02:00
Tamas Nagy 9e462a480b
bump version number for patch release
[ci skip]
2019-06-19 10:40:25 -07:00
Tamas Nagy df7f0d1f3c
Merge pull request #215 from Oblynx/patch-1
Fix mpastell/Weave.jl#214
2019-06-19 10:39:37 -07:00
Arnav Sood 5d3e05511e allow configuration of jupyter command while weaving notebooks, fixes #194
* notebook refactor and tests

* update PR

* add jupyter test jmd

* add back full warnings and remove debugging output

* Update test filename [ci skip]

* Conda for CI

* update for CI?

* remove Conda, IJulia, and tests for now

* Project.toml changes suggested by tinagly

* revive travis tests

* comment out nb tests
2019-06-19 10:26:13 -07:00
Tamas Nagy 6621920bec
Merge pull request #218 from davidanthoff/vscode
Mention VS Code extension in README
2019-06-12 11:48:05 -07:00
David Anthoff 975a67ad44 Mention VS Code extension in README 2019-06-10 11:23:01 -07:00
Konstantinos Samaras-Tsakiris ea1de0fb9e
Fix mpastell/Weave.jl#214
Fixes incorrect UTF-8 string handling as described in https://github.com/mpastell/Weave.jl/issues/214.
2019-06-04 21:02:40 +03:00
tshort bd69ef1f59 Fix hooks and add a push/pop hook to the test 2019-04-27 13:17:29 -04:00
Matti Pastell c9a814759d Release 0.9.0 2019-03-11 16:09:15 +02:00
Matti Pastell 95e860816c Restore .ps and .js.svg to Gadfly 2019-03-11 15:13:30 +02:00
Matti Pastell 99db6a9406 Actually fix include_weave 2019-03-11 14:25:17 +02:00
Matti Pastell 8194c8a1b8 Fix `include_weave`. Closes #152. 2019-03-11 14:05:06 +02:00
Matti Pastell 83e2e0ae20 Add tests for inline code 2019-03-11 13:39:21 +02:00
Matti Pastell 35addd2b50 Fixes to option parsing, gadfly pdf, stripping header, add tests 2019-03-11 10:23:31 +02:00
Matti Pastell c33309abf6 Tweak docs 2019-03-10 23:09:27 +02:00
Matti Pastell 4338fc4b07 Make out_path and template path relative to document 2019-03-10 22:53:00 +02:00
Matti Pastell 6f83f1abf5 Add example beamer document 2019-03-10 20:10:30 +02:00
Matti Pastell 3488af5534 Add docs for inline output, make figure output inline 2019-03-10 19:23:18 +02:00
Matti Pastell 4ab1c09b8c Allow using MustacheTokens as template directly 2019-03-10 17:51:19 +02:00
Matti Pastell e7a10eacdc Don't use isnothing 2019-03-10 17:20:43 +02:00
Matti Pastell 37aa0237a8 Add new syntax for inline code and fix output in md2* formats 2019-03-06 22:27:47 +02:00
151 changed files with 4137 additions and 5917 deletions

1
.github/FUNDING.yml vendored Normal file
View File

@ -0,0 +1 @@
custom: https://numfocus.salsalabs.org/donate-to-julia/index.html

31
.github/ISSUE_TEMPLATE/bug.md vendored Normal file
View File

@ -0,0 +1,31 @@
---
name: bug report
about: create a bug report
title: "[BUG]"
labels: bug
assignees: ''
---
<!-- Please search existing issues to avoid duplicates. -->
## description
## versions
> `using InteractiveUtils; versioninfo()`:
<!-- please paste the the output of `using InteractiveUtils; versioninfo()` in the backticks below -->
```julia
```
> `using Pkg; Pkg.status()`:
<!-- please paste the the output of `using Pkg; Pkg.status()` in the backticks below -->
```julia
```
## minimum reproducible steps
<!-- if possible, paste here a minimum reproducible example document and steps -->

11
.github/ISSUE_TEMPLATE/enhancement.md vendored Normal file
View File

@ -0,0 +1,11 @@
---
name: enhancement
about: suggest an enhancement idea
title: "[FR]"
labels: enhancement
assignees: ''
---
<!-- Please search existing issues to avoid duplicates. -->
## description

19
.github/workflows/CompatHelper.yml vendored Normal file
View File

@ -0,0 +1,19 @@
name: CompatHelper
on:
schedule:
- cron: '00 00 * * *'
jobs:
CompatHelper:
runs-on: ubuntu-latest
steps:
- uses: julia-actions/setup-julia@latest
with:
version: 1.3
- name: Pkg.add("CompatHelper")
run: julia -e 'using Pkg; Pkg.add("CompatHelper")'
- name: CompatHelper.main()
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: julia -e 'using CompatHelper; CompatHelper.main()'

11
.github/workflows/TagBot.yml vendored Normal file
View File

@ -0,0 +1,11 @@
name: TagBot
on:
schedule:
- cron: 0 * * * *
jobs:
TagBot:
runs-on: ubuntu-latest
steps:
- uses: JuliaRegistries/TagBot@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}

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 }}

10
.gitignore vendored
View File

@ -1,6 +1,5 @@
Manifest.toml
src/*.cov
test.jl
examples/figures/
examples/*.md
examples/*.pdf
@ -17,19 +16,14 @@ test/**/*.html
test/**/*.pdf
test/**/*.png
test/**/chunk_options.jl
test/**/*.ipynb
!test/**/*ref.*
doc/build
doc/site
stable/
doc/Manifest.toml
Manifest.toml
tmp/
.idea
*.*~
*.aux
*.log
*.out
\#*\#
.juliahistory

View File

@ -1,26 +1,14 @@
language: julia
julia:
- 1.0
- 1.1
matrix:
allow_failures:
- julia: 1.1
notifications:
email: false
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:
include:
- stage: "Documentation"
julia: 1.0
julia: 1.5
os: linux
script:
- julia --project=doc/ -e 'using Pkg; Pkg.develop(PackageSpec(path=pwd()));
Pkg.instantiate()'
- julia --project=doc/ -e 'using Pkg; Pkg.develop(PackageSpec(path=pwd())); Pkg.instantiate()'
- julia --project=doc/ doc/make.jl
after_success: skip
notifications:
email: false

View File

@ -1,22 +1,20 @@
The Weave.jl package is licensed under the MIT "Expat" License:
Copyright (c) 2020: Contributors
> Copyright (c) 2014-2017: Matti Pastell.
>
> Permission is hereby granted, free of charge, to any person obtaining
> a copy of this software and associated documentation files (the
> "Software"), to deal in the Software without restriction, including
> without limitation the rights to use, copy, modify, merge, publish,
> distribute, sublicense, and/or sell copies of the Software, and to
> permit persons to whom the Software is furnished to do so, subject to
> the following conditions:
>
> The above copyright notice and this permission notice shall be
> included in all copies or substantial portions of the Software.
>
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
> EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
> IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
> CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
> TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
> SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

68
NEWS.md
View File

@ -1,20 +1,66 @@
## Release notes for Weave.jl
### 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)
- document metadata in YAML header can be given dynamically (#329)
- headers are now striped more gracefully; only Weave.jl related header is stripped when weaving to `github` or `hugo` document (#329, #305)
- `WeavePlots`/`GadflyPlots` won't be loaded into `Main` module (#322)
- un`const` bindings in a sandbox module are correctly cleared, helping GC free as much memory usage as possible (#317)
- keep latex figures even if weaving failed (#302)
- bunch of documentation improvements (#297, #295)
- code size in HTML header is now not hardcoded, leading to more readable font size (#281)
bug fixes:
- display of "big" object is fixed and limited (#311)
- fix dependencies issues
internal:
- bunch of internal refactors, code clean up (#330, #327, #325, #321, #320, #319, #318, #313)
- internal error now doesn't mess up display system (#316)
- format code base (#312)
breaking change:
- `options` YAML key is deprecated, use `weave_options` key instead (#334)
- `set_chunk_defaults` is now renamed to `set_chunk_defaults!` (#323)
- `restore_chunk_defaults` is now renamed to `restore_chunk_defaults!` (#323)
---
# Release notes for Weave.jl
### v0.4.1
* Disable precompilation due to warnings from depencies
* Disable precompilation due to warnings from dependencies
* Fix deprecation warnings for Julia 0.6
* Fix PyPlot for Julia 0.6
* Support citations in `pandoc2html` and `pandoc2pdf` output
* Fix extra whitespace when `term=true`
* Fix mime type priority for `md2html`
### V0.4.0
* Support passing arguments to document using `args` option
* Add `include_weave` for including code from Weave documents
* Add support for inline code chunks
* Remove generated figure files when publishing to html and pdf
### v0.3.0
* Add support for YAML title block
@ -25,11 +71,13 @@
* Fix extra whitespace from code chunk output
* Improved GR and GLVisualize support with Plots
### v0.2.2
* Add IJulia notebook as input format
* Add `convert_doc` method to convert between input formats
### v0.2.1
* Fix critical hanging on Windows using proper handling of redirect_stdout
@ -37,6 +85,7 @@
output in published HTML documents.
* Fix semicolons for `term=true`
### v0.2
* Move to Julia 0.5 only
@ -57,6 +106,7 @@
- Fix parsing of lone variables from chunks
- Fix error with md2html formatter and dates #38
### v0.1.2
27th April 2016
@ -66,6 +116,7 @@
* Improve doctype autodetection
* Improved regex for parsing markdown input format
### v0.1.1
* Change pandoc output to use inline images if there is no caption.
@ -81,6 +132,7 @@
* Autodetect input and output formats based on filename
* Allow `out_path` be a file or directory.
### v0.1.0
19th April 2016
@ -97,6 +149,7 @@
- Chunks are now represented with their own type. Allows multiple dispatch
and easier implementation of new chunks.
### 0.0.4
4th January 2015
@ -106,6 +159,7 @@
* New option: `out_path` for controlling where weaved documents and figures are saved
* Command line script `bin/weave.jl` for calling weave from command line
### 0.0.3
9th December 2014
@ -121,8 +175,8 @@
7th December 2014
* First release
* Noweb and markdown input formats
* Support for Gadfly, Winston and PyPlot figures
* Term and script chunks
* Support for markdown, tex and rst output
First release:
- Noweb and markdown input formats
- Support for Gadfly, Winston and PyPlot figures
- Term and script chunks
- Support for markdown, tex and rst output

View File

@ -1,30 +1,37 @@
name = "Weave"
uuid = "44d3d7a6-8a23-5bf8-98c5-b353f8df5ec9"
version="0.8.1"
version = "0.10.12"
[deps]
Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7"
Markdown = "d6f4376e-aef5-505a-96c1-9c027394607a"
Dates = "ade2ca70-3891-5945-98fb-dc099432e06a"
Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"
REPL = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb"
Compat = "34da2185-b29b-5c13-b0c7-acf172513d20"
Serialization = "9e88b42a-f829-5b0c-bbe9-9e923198166b"
JSON = "682c06a0-de6a-54ab-a142-c8b1cf79cde6"
Dates = "ade2ca70-3891-5945-98fb-dc099432e06a"
Highlights = "eafb193a-b7ab-5a9e-9068-77385905fa72"
JSON = "682c06a0-de6a-54ab-a142-c8b1cf79cde6"
Markdown = "d6f4376e-aef5-505a-96c1-9c027394607a"
Mustache = "ffc61752-8dc7-55ee-8c37-f3e9cdd09e70"
YAML = "ddb6d928-2868-570f-bddf-ab3f9cf99eb6"
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"
Plots = ">=0.19.0"
YAML = ">=0.3.0"
Mustache = ">=0.4.1"
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.2"
[extras]
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
Gadfly = "c91e804a-d5a3-530f-b6f0-dfbca275c004"
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
[targets]
test = ["Test", "Plots"]
test = ["DataFrames", "Test"]

View File

@ -1,33 +1,35 @@
# Weave
[![Build Status](https://travis-ci.org/mpastell/Weave.jl.svg?branch=master)](https://travis-ci.org/mpastell/Weave.jl)
[![Build status](https://ci.appveyor.com/api/projects/status/r97pwi9x8ard6xk6/branch/master?svg=true)](https://ci.appveyor.com/project/mpastell/weave-jl/branch/master)
[![Coverage Status](https://img.shields.io/coveralls/mpastell/Weave.jl.svg)](https://coveralls.io/r/mpastell/Weave.jl?branch=master)
[![](https://img.shields.io/badge/docs-stable-blue.svg)](https://mpastell.github.io/Weave.jl/dev)
[![](https://img.shields.io/badge/docs-dev-blue.svg)](https://mpastell.github.io/Weave.jl/dev)
![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. It resembles [Pweave](http://mpastell.com/pweave), Knitr, rmarkdown
and Sweave.
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/),
[R Markdown](https://rmarkdown.rstudio.com/),
and [Sweave](https://stat.ethz.ch/R-manual/R-patched/library/utils/doc/Sweave.pdf).
You can write your documentation and code in input document using Noweb,
Markdown, Script syntax and use `weave` function to execute to document to capture results
and figures.
You can write your documentation and code in input document using Markdown, Noweb or ordinal Julia script syntax,
and then use `weave` function to execute code and generate an output document while capturing results and figures.
**Current features**
* Publish markdown directly to html and pdf using Julia or Pandoc markdown.
* Markdown, script of Noweb syntax for input documents.
* Execute code as terminal or "script" chunks.
* Capture Plots.jl or Gadfly.jl figures
* Supports LaTex, Pandoc, Github markdown, MultiMarkdown, Asciidoc and reStructuredText output
* Simple caching of results
* Convert to and from IJulia notebooks
- Publish markdown directly to HTML and PDF using Julia or [Pandoc](https://pandoc.org/MANUAL.html)
- Execute code as in terminal or in a unit of code chunk
- Capture [Plots.jl](https://github.com/JuliaPlots/Plots.jl) or [Gadfly.jl](https://github.com/GiovineItalia/Gadfly.jl) figures
- Supports various input format: Markdown, [Noweb](https://www.cs.tufts.edu/~nr/noweb/), [Jupyter Notebook](https://jupyter.org/), and ordinal Julia script
- Conversions between those input formats
- Supports various output document formats: HTML, PDF, GitHub markdown, Jupyter Notebook, MultiMarkdown, Asciidoc and reStructuredText
- Simple caching of results
**Citing Weave:** *Pastell, Matti. 2017. Weave.jl: Scientific Reports Using Julia. The Journal of Open Source Software. http://dx.doi.org/10.21105/joss.00204*
![Weave code and output](http://mpastell.com/images/weave_demo.png)
![Weave in Juno demo](https://user-images.githubusercontent.com/40514306/76081328-32f41900-5fec-11ea-958a-375f77f642a2.png)
## Installation
@ -38,31 +40,36 @@ using Pkg
Pkg.add("Weave")
```
## Usage
Run from julia using Plots.jl for plots:
```julia
#First add depencies for the example
using Pkg; Pkg.add.(["Plots", "DSP"])
#Use Weave
using Weave
weave(joinpath(dirname(pathof(Weave)), "../examples", "FIR_design.jmd"), out_path=:pwd)
# add depencies for the example
using Pkg; Pkg.add(["Plots", "DSP"])
filename = normpath(Weave.EXAMPLE_FOLDER, "FIR_design.jmd")
weave(filename, out_path = :pwd)
```
If you have LaTeX installed you can also weave directly to pdf.
```julia
weave(joinpath(dirname(pathof(Weave)), "../examples", "FIR_design.jmd"),
out_path=:pwd, doctype="md2pdf")
filename = normpath(Weave.EXAMPLE_FOLDER, "FIR_design.jmd")
weave(filename, out_path = :pwd, doctype = "md2pdf")
```
NOTE: `Weave.EXAMPLE_FOLDER` just points to [`examples` directory](./examples).
## Documentation
Documenter.jl with MKDocs generated documentation:
[![](https://img.shields.io/badge/docs-stable-blue.svg)](https://mpastell.github.io/Weave.jl/stable)
[![](https://img.shields.io/badge/docs-latest-blue.svg)](https://mpastell.github.io/Weave.jl/latest)
[![](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/)
## Editor support
@ -70,15 +77,28 @@ Install [language-weave](https://atom.io/packages/language-weave) to add Weave s
It allows running code from Weave documents with usual keybindings and allows preview of
html and pdf output.
The [Julia extension for Visual Studio Code](https://www.julia-vscode.org/)
adds Weave support to [Visual Studio Code](https://code.visualstudio.com/).
## Contributing
I will probably add new features to Weave when I need them myself or if they are requested and not too difficult to implement. You can contribute by opening issues on Github or implementing things yourself and making a pull request. I'd also appreciate example documents written using Weave to add to examples.
You can contribute to this package by opening issues on GitHub or implementing things yourself and making a pull request.
We'd also appreciate more example documents written using Weave.
## Contributors
You can see the list of contributors on Github: https://github.com/mpastell/Weave.jl/graphs/contributors. Thanks for the important additions, fixes and comments.
You can see the list of contributors on GitHub: https://github.com/JunoLab/Weave.jl/graphs/contributors .
Thanks for the important additions, fixes and comments.
## Example projects using Weave
- [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

@ -1,7 +0,0 @@
julia 1.0
JSON
Highlights 0.3.0
Mustache
YAML
Compat 0.25.0
Requires

View File

@ -1,32 +0,0 @@
environment:
matrix:
- JULIA_URL: "https://julialang-s3.julialang.org/bin/winnt/x64/1.0/julia-1.0-latest-win64.exe"
branches:
only:
- master
- /release-.*/
notifications:
- provider: Email
on_build_success: false
on_build_failure: false
on_build_status_changed: false
install:
- ps: "[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12"
# Download most recent Julia Windows binary
- ps: (new-object net.webclient).DownloadFile(
$env:JULIA_URL,
"C:\projects\julia-binary.exe")
# Run installer silently, output to C:\projects\julia
- C:\projects\julia-binary.exe /S /D=C:\projects\julia
build_script:
# Need to convert from shallow to complete for Pkg.clone to work
- IF EXIST .git\shallow (git fetch --unshallow)
#- C:\projects\julia\bin\julia -e "ENV[\"PYTHON\"]=\"\"; Pkg.add(\"PyPlot\")"
- C:\projects\julia\bin\julia -e "using Pkg; Pkg.clone(pwd(), \"Weave\"); Pkg.build(\"Weave\")"
test_script:
- C:\projects\julia\bin\julia --check-bounds=yes -e "using Pkg; Pkg.test(\"Weave\")"

View File

@ -14,14 +14,14 @@ ap = ArgParseSettings("Weave Julia documents using Weave.jl",
help = "source document(s)"
required = true
"--doctype"
default = :auto
default = nothing
help = "output format"
"--plotlib"
arg_type = String
default = "Gadfly"
help = "output format"
"--informat"
default = :auto
default = nothing
help = "output format"
"--out_path"
arg_type = String
@ -43,9 +43,6 @@ args_col = []
#Check for special values of out_path
#args["informat"] == ":auto" && (args["informat"] = :auto)
#args["doctype"] == ":auto" && (args["informat"] = :auto)
if args["out_path"] == ":doc"
args["out_path"] = :doc
elseif args["out_path"] == ":pwd"

View File

@ -2,6 +2,3 @@
DSP = "717857b8-e6f2-59f4-9121-6e50c889abd2"
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
[compat]
Documenter = "~0.20"

BIN
doc/assets/FIR_design.pdf Normal file

Binary file not shown.

Binary file not shown.

View File

@ -1,15 +1,29 @@
using Documenter, Weave
CI_FLG = get(ENV, "CI", nothing) == "true"
makedocs( modules = Weave, sitename="Weave.jl",
pages = ["index.md", "getting_started.md", "usage.md",
"publish.md", "chunk_options.md", "notebooks.md",
"function_index.md"]
makedocs(
modules = [Weave],
format = Documenter.HTML(
prettyurls = CI_FLG,
canonical = "http://weavejl.mpastell.com/stable/",
),
sitename = "Weave.jl",
pages = [
"index.md",
"getting_started.md",
"usage.md",
"publish.md",
"chunk_options.md",
"header.md",
"notebooks.md",
"function_index.md",
],
)
include("make_examples.jl")
CI_FLG && include("make_examples.jl")
deploydocs(
repo = "github.com/mpastell/Weave.jl.git",
target = "build"
repo = "github.com/JunoLab/Weave.jl.git",
push_preview = true,
)

View File

@ -1,29 +1,30 @@
using Weave
start_dir = pwd()
cd(@__DIR__)
weave("../examples/FIR_design.jmd",
informat="markdown", out_path = "build/examples", doctype = "pandoc")
let start_dir = pwd()
cd(@__DIR__)
weave("../examples/FIR_design.jmd",
informat="markdown", out_path = "build/examples", doctype = "md2html")
weave("../examples/FIR_design.jmd", doctype = "pandoc", out_path = "build/examples")
weave("../examples/FIR_design.jmd", doctype = "md2html", out_path = "build/examples")
weave("../examples/FIR_design_plots.jl", doctype = "md2html", out_path = "build/examples")
cp("../examples/FIR_design.jmd",
"build/examples/FIR_design.jmd", force = true)
# PDF outputs
if haskey(ENV, "TRAVIS")
# in Travis, just cp already generated PDFs
cp("assets/FIR_design.pdf", "build/examples/FIR_design.pdf", force = true)
cp("assets/FIR_design_plots.pdf", "build/examples/FIR_design_plots.pdf", force = true)
else
# otherwise try to generate them
try
weave("../examples/FIR_design.jmd", doctype = "md2pdf", out_path = "assets")
weave("../examples/FIR_design_plots.jl", doctype = "md2pdf", out_path = "assets")
catch err
@error err
end
end
cp("build/examples/FIR_design.md",
"build/examples/FIR_design.txt", force = true)
cp("../examples/FIR_design.jmd", "build/examples/FIR_design.jmd", force = true)
cp("build/examples/FIR_design.md", "build/examples/FIR_design.txt", force = true)
cp("../examples/FIR_design_plots.jl", "build/examples/FIR_design_plots.jl", force = true)
weave("../examples/FIR_design_plots.jl", out_path = "build/examples")
cp("../examples/FIR_design_plots.jl",
"build/examples/FIR_design_plots.jl", force = true)
if !haskey(ENV, "TRAVIS")
weave("../examples/FIR_design.jmd",
informat="markdown", out_path = "build/examples", doctype = "md2pdf")
weave("../examples/FIR_design_plots.jl", doctype = "md2pdf", out_path = "build/examples")
cd(start_dir)
end
cd(start_dir)

View File

@ -1,55 +1,81 @@
# 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:
## Options for code
* `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`. 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, depends 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.
## Options for figures
* `fig_width`. Figure width passed to plotting library e.g. `800`
* `fig_height` Figure height passed to plotting library
* `out_width`. Width of saved figure in output markup e.g. "50%", "12cm", `\\0.5linewidth`
* `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="htpb"`. Figure position in Latex.
* `fig_env="figure"`. Figure environment in Latex.
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).
## Set default chunk options
## Syntax
You can set the default chunk options (and `weave` arguments) for a document using the YAML header `options` field. e.g to set the default `out_width` of all figures you can use:
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.
- `term = false`: If `true` the output emulates a REPL session. Otherwise only stdout and figures will be included in output.
- `wrap = true`: Wrap long lines from output.
- `line_width = 75`: Line width for wrapped lines.
- `hold = false`: Hold all results until the end of the chunk.
### 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.
- `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.
## 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:
```yaml
---
options:
out_width : 50%
weave_options:
out_width : 50%
---
```
You can also set or change the default chunk options for a document either before weave using the `set_chunk_defaults function`.
You can also set or change the default chunk options for a document either before weave using the `set_chunk_defaults` function.
```@docs
set_chunk_defaults(opts)
get_chunk_defaults()
restore_chunk_defaults()
set_chunk_defaults!
get_chunk_defaults
restore_chunk_defaults!
```

View File

@ -1,18 +1,18 @@
# Getting started
The best way to get started using Weave.jl is to look at the example input and
output documents. Examples for different formats are included in the packages `examples` directory.
The best way to get started using Weave.jl is to look at the example input and output documents.
Examples for different formats are included in the package's [`examples`](https://github.com/JunoLab/Weave.jl/tree/master/examples) directory.
First have a look at source document using markdown code chunks and Plots.jl for
figures: [FIR_design.jmd](../examples/FIR_design.jmd) and then see the
output in different formats:
First have a look at source document using markdown code chunks and [Plots.jl](https://github.com/JuliaPlots/Plots.jl) for figures:
- HTML: [FIR_design.html](../examples/FIR_design.html)
- pdf: [FIR_design.pdf](../examples/FIR_design.pdf)
- Pandoc markdown: [FIR_design.txt](../examples/FIR_design.txt)
All the different format documents below are generated from a single Weave document [`FIR_design.jmd`](../examples/FIR_design.jmd):
- HTML: [`FIR_design.html`](../examples/FIR_design.html)
- PDF: [`FIR_design.pdf`](../examples/FIR_design.pdf)
- Pandoc markdown: [`FIR_design.txt`](../examples/FIR_design.txt)
*Producing pdf output requires that you have XeLateX installed.*
!!! note
Producing PDF output requires that you have XeLateX installed.
Add dependencies for the example if needed:
@ -20,20 +20,22 @@ Add dependencies for the example if needed:
using Pkg; Pkg.add.(["Plots", "DSP"])
```
Weave the files to your working directory using:
Weave the files to your working directory:
```julia
using Weave
#HTML
weave(joinpath(dirname(pathof(Weave)), "../examples", "FIR_design.jmd"),
out_path=:pwd,
doctype = "md2html")
#pdf
weave(joinpath(dirname(pathof(Weave)), "../examples", "FIR_design.jmd"),
out_path=:pwd,
doctype = "md2pdf")
#Markdown
weave(joinpath(dirname(pathof(Weave)), "../examples", "FIR_design.jmd"),
doctype="pandoc"
out_path=:pwd)
filename = normpath(Weave.EXAMPLE_FOLDER, "FIR_design.jmd")
# Julia markdown to HTML
weave(filename; doctype = "md2html", out_path = :pwd)
# Julia markdown to PDF
weave(filename; doctype = "md2pdf", out_path = :pwd)
# Julia markdown to Pandoc markdown
weave(filename; doctype = "pandoc", out_path = :pwd)
```
!!! tips
`Weave.EXAMPLE_FOLDER` points to [the `examples` directory](https://github.com/JunoLab/Weave.jl/tree/master/examples).

101
doc/src/header.md Normal file
View File

@ -0,0 +1,101 @@
# Header Configuration
When `weave`ing a markdown document, you use YAML header to provide additional metadata and configuration options.
A YAML header should be in the beginning of the input document delimited with `---`.
!!! warning
YAML header configuration is only supported when `weave`ing [markdown or Noweb syntax documents](@ref document-syntax).
## Document Metadata
You can set additional document metadata in YAML header.
When `weave`ing to Julia markdown documents to HTML or PDF, Weave respects the following metadata specification:
- `title`
- `author`
- `date`
An example:
```yaml
---
title : Header Example
author : Shuhei Kadowaki
date: 16th May 2020
---
```
!!! note
You can also have other metadata, but they won't appear in the resulting HTML and PDF.
If you weave to Julia markdown to GitHub/Hugo markdown, all the metadata will be preserved.
### Dynamic Metadata
The metadata can be given "dynamically"; if you have [inline code](@ref) within YAML header, they will be evaluated _after_ evaluating all the chunks and replaced with the results.
The example document below will set `date` metadata dynamically.
Note that `Date` is available since the chunk is evaluated first.
```md
---
title : Header Example
author : Shuhei Kadowaki
date: `j import Dates; Dates.Date(Dates.now())`
---
```julia; echo = false
using Dates
```
```
## Configuration Options
Each of keyword arguments of [`weave`](@ref) can be set in the YAML header under `options` field.
You can also set [Chunks Options](@ref) there that will be applied globally.
The example below sets `out_path` and `doctype` options and overwrites `term` and `wrap` chunk options:
```yaml
---
title : Header Example
author : Shuhei Kadowaki
date: 16th May 2020
weave_options:
out_path: relative/path/to/this/document
doctype: github
term: true
wrap: false
---
```
!!! note
- configurations specified within the YAML header have higher precedence than those specified via `weave` keyword arguments
- chunk options specified within each chunk have higher precedence than the global global chunk options specified within the YAML header
!!! warning
As opposed to metadata, _most_ of those configuration options can't be given dynamically (i.e. can't be via inline code),
since they are needed for evaluation of chunks themselves.
But some configuration options that are needed "formatting" document can still be given dynamically:
- `template`
- `css`
- `highlight_theme`
- `pandoc_options`
- `latex_cmd`
- `keep_unicode`
See also: [`weave`](@ref)
## Format Specific Options
The header configurations can be format specific.
Here is how to set different `out_path` for `md2html` and `md2pdf` and set `fig_ext` globally:
```yaml
---
weave_options:
md2html:
out_path : html
md2pdf:
out_path : pdf
fig_ext : .png
---
```

View File

@ -1,27 +1,38 @@
# Weave.jl - Scientific Reports Using Julia
This is the documentation of [Weave.jl](http://github.com/mpastell/weave.jl). Weave is a scientific report generator/literate programming tool
for Julia. It resembles [Pweave](http://mpastell.com/pweave), Knitr, rmarkdown
and Sweave.
This is the documentation of [Weave.jl](http://github.com/mpastell/weave.jl).
Weave is a scientific report generator/literate programming tool for Julia.
It resembles
[Pweave](http://mpastell.com/pweave),
[knitr](https://yihui.org/knitr/),
[R Markdown](https://rmarkdown.rstudio.com/),
and [Sweave](https://stat.ethz.ch/R-manual/R-patched/library/utils/doc/Sweave.pdf).
**Current features**
* Markdown, script of Noweb syntax for input documents.
* Publish markdown directly to html and pdf using Julia or Pandoc markdown.
* Execute code as terminal or "script" chunks.
* Capture Plots.jl or Gadfly.jl figures
* Supports LaTex, Pandoc, Github markdown, MultiMarkdown, Asciidoc and reStructuredText output
* Simple caching of results
* Convert to and from IJulia notebooks
- Publish markdown directly to HTML and PDF using Julia or [Pandoc](https://pandoc.org/MANUAL.html)
- Execute code as in terminal or in a unit of code chunk
- Capture [Plots.jl](https://github.com/JuliaPlots/Plots.jl) or [Gadfly.jl](https://github.com/GiovineItalia/Gadfly.jl) figures
- Supports various input format: Markdown, [Noweb](https://www.cs.tufts.edu/~nr/noweb/), [Jupyter Notebook](https://jupyter.org/), and ordinal Julia script
- Conversions between those input formats
- Supports various output document formats: HTML, PDF, GitHub markdown, Jupyter Notebook, MultiMarkdown, Asciidoc and reStructuredText
- Simple caching of results
![Weave code and output](http://mpastell.com/images/weave_demo.png)
![Weave in Juno demo](https://user-images.githubusercontent.com/40514306/76081328-32f41900-5fec-11ea-958a-375f77f642a2.png)
## Contents
## Index
```@contents
Pages = ["getting_started.md", "usage.md",
"publish.md", "chunk_options.md", "notebooks.md",
"function_index.md"]
Pages = [
"index.md",
"getting_started.md",
"usage.md",
"publish.md",
"chunk_options.md",
"header.md",
"notebooks.md",
"function_index.md",
]
```

View File

@ -3,30 +3,34 @@
## Weaving from Jupyter notebooks
Weave supports using Jupyter notebooks as input format, this means you
can weave notebooks to any supported formats. You can't use chunk options with notebooks.
Weave supports using [Jupyter Notebook](https://jupyter.org/)s as input format.
This means you can [`weave`](@ref) notebooks to any supported formats;
by default, it will be weaved to HTML.
```julia
weave("notebook.ipynb")
weave("notebook.ipynb") # will be weaved to HTML
```
!!! warning
You can't use chunk options with notebooks.
## Output to Jupyter notebooks
As of Weave 0.5.1. there is new `notebook` method to convert Weave documents
to Jupyter notebooks using [nbconvert](http://nbconvert.readthedocs.io/en/latest/execute_api.html). The code **is not executed by Weave**
and the output doesn't always work properly,
see [#116](https://github.com/mpastell/Weave.jl/issues/116).
As of Weave 0.5.1. there is new [`notebook`](@ref) method to convert Weave documents to Jupyter notebooks using
[nbconvert](http://nbconvert.readthedocs.io/en/latest/execute_api.html).
```@docs
notebook(source::String, out_path=:pwd)
notebook
```
You might wan't to use the `convert_doc` method below instead and run the code in Jupyter.
You can specify `jupyter` used to execute the notebook with the `jupyter_path` keyword argument
(this defaults to the `"jupyter"`, i.e. whatever you have linked to that location).
Instead, you might want to use the [`convert_doc`](@ref) method below and run the code in Jupyter.
## Converting between formats
You can convert between all supported input formats using the `convert_doc`
function.
You can convert between all supported input formats using the [`convert_doc`](@ref) function.
To convert from script to notebook:
@ -34,12 +38,12 @@ To convert from script to notebook:
convert_doc("examples/FIR_design.jl", "FIR_design.ipynb")
```
and from notebooks to markdown use:
and from notebook to Markdown use:
```julia
convert_doc("FIR_design.ipynb", "FIR_design.jmd")
```
```@docs
convert_doc(infile::String, outfile::String)
convert_doc
```

View File

@ -1,10 +1,12 @@
# Publishing to html and pdf
# Publishing to HTML and PDF
You can also publish any supported input format using markdown for doc chunks to html and pdf documents. Producing pdf output requires that you have pdflatex installed and in your path.
You can also publish any supported input format to HTML and PDF documents.
You can use a YAML header in the beginning of the input document delimited with "---"
to set the document title, author and date e.g.
!!! note
Producing PDF output requires that you have XeLaTex installed and in your path.
You can use a YAML header in the beginning of the input document delimited with `---`
to set the document title, author and date, e.g.:
```
---
title : Weave example
@ -13,37 +15,48 @@ date: 15th December 2016
---
```
Here is a a sample document and output:
[FIR_design_plots.jl](../examples/FIR_design_plots.jl), [FIR_design_plots.html](../examples/FIR_design_plots.html) , [FIR_design_plots.pdf](../examples/FIR_design_plots.pdf).
Here are sample input and outputs:
- input (Julia markdown format): [`FIR_design_plots.jl`](../examples/FIR_design_plots.jl) (its path is bound to `Weave.SAMPLE_JL_DOC`)
- HTML output: [`FIR_design_plots.html`](../examples/FIR_design_plots.html)
- PDF output: [`FIR_design_plots.pdf`](../examples/FIR_design_plots.pdf)
They are generated as follows:
```julia
weave("FIR_design_plots.jl")
weave("FIR_design_plots.jl", docformat = "md2pdf")
weave(Weave.SAMPLE_JL_DOC)) # default to md2html output format
weave(Weave.SAMPLE_JL_DOC; doctype = "md2pdf")
```
**Note:** docformats `md2pdf` and `md2html` use Julia markdown and `pandoc2pdf` and `pandoc2html`
use Pandoc.
!!! tips
`Weave.SAMPLE_JL_DOC` is the path of [FIR_design.jl](../examples/FIR_design.jl).
!!! note
`"md2html"` and `"md2pdf"` assume Julia markdown format as an input,
while `pandoc2pdf` and `pandoc2html` assume Noweb input format (i.e. Pandoc markdown).
## Templates
You can use a custom template with `md2pdf` and `md2html` formats with `template`
argument (e.g) `weave("FIR_design_plots.jl", template = "custom.tpl"`). You can use
the existing templates as starting point.
You can use a custom template with `md2html` and `md2pdf` formats with `template` keyword option,
e.g.: `weave("FIR_design_plots.jl", template = "custom.tpl"`.
For HTML: [julia_html.tpl](https://github.com/mpastell/Weave.jl/blob/master/templates/julia_html.tpl) and LaTex: [julia_tex.tpl](https://github.com/mpastell/Weave.jl/blob/master/templates/julia_tex.tpl)
As starting point, you can use the existing templates:
- 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).
## Supported Markdown syntax
The markdown variant used by Weave is [Julia markdown](http://docs.julialang.org/en/latest/manual/documentation.html#Markdown-syntax-1). In addition Weave supports few additional Markdown features:
The markdown variant used by Weave is [Julia markdown](https://docs.julialang.org/en/v1/stdlib/Markdown/#).
In addition Weave supports few additional Markdown features:
**Comments**
### Comments
You can add comments using html syntax: `<!-- -->`
**Multiline equations**
### Multiline equations
You can add multiline equations using:

View File

@ -1,58 +1,65 @@
# Using Weave
You can write your documentation and code in input document using Markdown, Noweb or script
syntax and use `weave` function to execute to document to capture results and figures.
syntax and use [`weave`](@ref) function to execute to document to capture results and figures.
## Weave
## `weave`
Weave document with markup and julia code using `Plots.jl` for plots,
`out_path = :pwd` makes the results appear in the current working directory.
> A prepared example: [`Weave.SAMPLE_JL_DOC`](../examples/FIR_design.jmd)
```julia
#First add depencies for the example
# First add depencies for the example
using Pkg; Pkg.add.(["Plots", "DSP"])
using Weave
weave(joinpath(dirname(pathof(Weave)), "../examples", "FIR_design.jmd"), out_path=:pwd)
weave(Weave.SAMPLE_JL_DOC; out_path=:pwd)
```
```@docs
weave(source)
weave
```
## Tangle
## `tangle`
Tangling extracts the code from document:
```@docs
tangle(source)
tangle
```
## Supported output formats
## Supported Output Formats
Weave sets the output format based on the file extension, but you can also set
it using `doctype` option. The rules for detecting the format are:
Weave automatically detects the output format based on the file extension.
The auto output format detection is handled by `detect_doctype(path::AbstractString)`:
```julia
ext == ".jl" && return "md2html"
contains(ext, ".md") && return "md2html"
contains(ext, ".rst") && return "rst"
contains(ext, ".tex") && return "texminted"
contains(ext, ".txt") && return "asciidoc"
return "pandoc"
function detect_doctype(path::AbstractString)
_, ext = lowercase.(splitext(path))
match(r"^\.(jl|.?md|ipynb)", ext) !== nothing && return "md2html"
ext == ".rst" && return "rst"
ext == ".tex" && return "texminted"
ext == ".txt" && return "asciidoc"
return "pandoc"
end
```
You can also manually specify it using the `doctype` keyword option.
You can get a list of supported output formats:
```@docs
list_out_formats
```
```@example
using Weave # hide
list_out_formats()
```
```@docs
list_out_formats()
```
## Document syntax
## [Document Syntax](@id document-syntax)
Weave uses markdown, Noweb or script syntax for defining the code chunks and
documentation chunks. You can also weave Jupyter notebooks. The format is detected based on the file extension, but you can also set it manually using the `informat` parameter.
@ -66,121 +73,110 @@ ext == ".ipynb" && return "notebook"
return "noweb"
```
## 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.
### Documentation Chunks
## Code chunks
### Markdown format
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:
` ```julia; echo=false`
[Sample document]( https://github.com/mpastell/Weave.jl/blob/master/examples/FIR_design.jmd)
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.
### Noweb format
### [Code Chunks](@id code-chunks)
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/).
Code chunks are written in different ways in different formats.
#### Markdown Format
### Script format
Weave also support script input format with a markup in comments.
These scripts can be executed normally using Julia or published with
Weave. Documentation is in lines starting with
`#'`, `#%%` or `# %%`, and code is executed and results are included
in the weaved document.
All lines that are not documentation are treated as code. You can set chunk options
using lines starting with `#+` just before code e.g. `#+ term=true`.
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)
## Inline code
You can also add inline code to your documents using
```
`j juliacode`
```
syntax. The code will be replaced with the output of running the code.
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)`)
```
## Setting document options in header
You can use a YAML header in the beginning of the input document delimited with "---" to set the document title, author and date e.g. and default document options. Each of Weave command line arguments and chunk options can be set in header using `options` field. Below is an example that sets document `out_path` and `doctype` using the header.
```yaml
---
title : Weave example
author : Matti Pastell
date: 15th December 2016
options:
out_path : reports/example.md
doctype : github
---
```
You can also set format specific options. Here is how to set different out_path for `md2html` and `md2pdf` and set `fig_ext` for both:
```
---
options:
md2html:
out_path : html
md2pdf:
out_path : pdf
fig_ext : .png
---
```
## Passing arguments to documents
You can pass arguments as dictionary to the weaved document using the `args` argument
to `weave`. The dictionary will be available as `WEAVE_ARGS` variable in the 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.
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:
```
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
print(WEAVE_ARGS["filename"])
code
...
```
```
You can use the `out_path` argument to control the name of the
output document.
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
...
```
```
## Include Weave document in Julia
#### Noweb Format
You can call `include_weave` on a Weave document to run the contents
of all code chunks in Julia.
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.
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:
```
! display("text/html", HTML("Header from julia"));
```
### Script Format
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.
All non-document lines are treated as code.
You can set chunk options using lines starting with `#+` just before code e.g:
```julia
#+ term=true
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.
!!! 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
When `weave`ing markdown files, you can use YAML header to provide additional metadata and configuration options.
See [Header Configuration](@ref) section for more details.
## Passing Runtime Arguments to Documents
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.
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`
You can call `include_weave` on a Weave document and run all code chunks within in the current session.
```@docs
include_weave(doc, informat=:auto)
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
@ -22,6 +22,13 @@ If you're viewing the published version have a look at the
[source](FIR_design_plots.jl) to see the markup.
<!-- this setup dependencies, but doesn't appear in the generated document -->
```julia; echo = false; results = "hidden"
using Pkg
"Plots" ∉ keys(Pkg.project().dependencies) && Pkg.add("Plots")
"DSP" ∉ keys(Pkg.project().dependencies) && Pkg.add("DSP")
```
# FIR Filter Design

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

46
examples/beamer.tpl Normal file
View File

@ -0,0 +1,46 @@
\documentclass{beamer}
\usepackage{lmodern}
\usepackage{amssymb,amsmath}
\usepackage{bm}
\usepackage{graphicx}
\usepackage{microtype}
\usepackage{hyperref}
\setlength{\parindent}{0pt}
\setlength{\parskip}{1.2ex}
\hypersetup
{ pdfauthor = { {{{:author}}} },
pdftitle={ {{{:title}}} },
colorlinks=TRUE,
linkcolor=black,
citecolor=blue,
urlcolor=blue
}
{{#:title}}
\title{ {{{ :title }}} }
{{/:title}}
{{#:author}}
\author{ {{{ :author }}} }
{{/:author}}
{{#:date}}
\date{ {{{ :date }}} }
{{/:date}}
{{ :highlight }}
\begin{document}
{{{#:title}}}
\begin{frame}
\titlepage
\end{frame}
{{{/:title}}}
{{{ :body }}}
\end{document}

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

@ -3,7 +3,7 @@
This a sample [Julia](http://julialang.org/) noweb document that can
be executed using Weave. Output from code chunks and PyPlot
plots will be included in the weaved document. You also need to install Pweave from Github in order to use Weave.
plots will be included in the weaved document. You also need to install Pweave from GitHub in order to use Weave.
This documented can be turned into Pandoc markdown with captured
result from Julia prompt.

View File

@ -0,0 +1,29 @@
---
title: A minimal beamer example using Weave markdown
author: Matti Pastell
weave_options:
doctype : md2pdf
out_path : pdf
template : beamer.tpl
---
```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)}")
```
! Begin("frame", "Random plot")
```julia; out_width="0.5\\textwidth"
using Plots
scatter(randn(1000), randn(1000))
```
! End("frame")

View File

@ -1,242 +1,344 @@
module Weave
import Highlights
using Compat
using Requires
using Highlights, Mustache, Requires, Pkg, REPL, RelocatableFolders, Base64
# directories
const PKG_DIR = normpath(@__DIR__, "..")
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"
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" Base.include(Main, "plots.jl")
@require Gadfly="c91e804a-d5a3-530f-b6f0-dfbca275c004" Base.include(Main, "gadfly.jl")
@require Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" include("plots.jl")
@require Gadfly = "c91e804a-d5a3-530f-b6f0-dfbca275c004" include("gadfly.jl")
end
"""
`list_out_formats()`
List supported output formats
"""
function list_out_formats()
for format = keys(formats)
println(string(format,": ", formats[format].description))
end
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]
"""
`tangle(source ; out_path=:doc, informat="noweb")`
list_out_formats()
List supported output formats with its description.
"""
list_out_formats() = [k => v.description for (k,v) in FORMATS]
"""
tangle(source::AbstractString; kwargs...)
Tangle source code from input document to .jl file.
* `informat`: `"noweb"` of `"markdown"`
* `out_path`: Path where the output is generated. Can be: `:doc`: Path of the source document, `:pwd`: Julia working directory, `"somepath"`, directory name as a string e.g `"/home/mpastell/weaveout"`
or filename as string e.g. ~/outpath/outfile.jl.
## Keyword options
- `informat::Union{Nothing,AbstractString} = nothing`: Input document format. By default (i.e. given `nothing`), Weave will set it automatically based on file extension. You can also specify either of `"script"`, `"markdown"`, `"notebook"`, or `"noweb"`
- `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"`
"""
function tangle(source ; out_path=:doc, informat=:auto)
doc = read_doc(source, informat)
function tangle(
source::AbstractString;
out_path::Union{Symbol,AbstractString} = :doc,
informat::Union{Nothing,AbstractString} = nothing,
)
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
for chunk in doc.chunks
if typeof(chunk) == CodeChunk
options = merge(doc.chunk_defaults, chunk.options)
if options[:tangle]
write(io, chunk.content*"\n")
end
end
open(out_path, "w") do io
for chunk in doc.chunks
if typeof(chunk) == CodeChunk
options = merge(doc.chunk_defaults, chunk.options)
options[:tangle] && write(io, chunk.content * "\n")
end
end
end
end
doc.cwd == pwd() && (outname = basename(outname))
@info("Writing to file $outname")
@info "Tangled to $(out_path)"
end
"""
weave(source ; doctype = :auto,
informat=:auto, out_path=:doc, args = Dict(),
mod::Union{Module, Symbol} = Main,
fig_path = "figures", fig_ext = nothing,
cache_path = "cache", cache=:off,
template = nothing, highlight_theme = nothing, css = nothing,
pandoc_options = "",
latex_cmd = "xelatex")
weave(source::AbstractString; kwargs...)
Weave an input document to output file.
* `doctype`: :auto = set based on file extension or specify one of the supported formats.
See `list_out_formats()`
* `informat`: :auto = set based on file extension or set to `"noweb"`, `"markdown"` or `script`
* `out_path`: Path where the output is generated. Can be: `:doc`: Path of the source document, `:pwd`:
Julia working directory, `"somepath"`: output directory as a String e.g `"/home/mpastell/weaveout"` or filename as
string e.g. ~/outpath/outfile.tex.
* `args`: dictionary of arguments to pass to document. Available as WEAVE_ARGS
* `mod`: Module where Weave `eval`s code. Defaults to `:sandbox`
to create new sandbox module, you can also pass a module e.g. `Main`.
* `fig_path`: where figures will be generated, relative to out_path
* `fig_ext`: Extension for saved figures e.g. `".pdf"`, `".png"`. Default setting depends on `doctype`.
* `cache_path`: where of cached output will be saved.
* `cache`: controls caching of code: `:off` = no caching, `:all` = cache everything,
`:user` = cache based on chunk options, `:refresh`, run all code chunks and save new cache.
* `throw_errors` if `false` errors are included in output document and the whole document is
executed. if `true` errors are thrown when they occur.
* `template` : Template (file path) for md2html or md2tex formats.
* `highlight_theme` : Theme (Highlights.AbstractTheme) for used syntax highlighting
* `css` : CSS (file path) used for md2html format
* `pandoc_options` = String array of options to pass to pandoc for `pandoc2html` and
`pandoc2pdf` formats e.g. ["--toc", "-N"]
* `latex_cmd` the command used to make pdf from .tex
## Keyword options
**Note:** Run Weave from terminal and not using IJulia, Juno or ESS, they tend to mess with capturing output.
- `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
- `informat::Union{Nothing,AbstractString} = nothing`: Input document format. By default (i.e. given `nothing`), Weave will set it automatically based on file extension. You can also specify either of `"script"`, `"markdown"`, `"notebook"`, or `"noweb"`
- `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::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::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:
* `:off` means no caching (default)
* `:all` caches everything
* `:user` caches based on chunk options
* `:refresh` runs all code chunks and save new cache
- `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} = $(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
Run Weave from terminal and try to avoid weaving from IJulia or ESS; they tend to mess with capturing output.
"""
function weave(source ; doctype = :auto,
informat=:auto, out_path=:doc, args = Dict(),
mod::Union{Module, Symbol} = :sandbox,
fig_path = "figures", fig_ext = nothing,
cache_path = "cache", cache=:off,
throw_errors = false,
template = nothing, highlight_theme = nothing, css = nothing,
pandoc_options = String[]::Array{String},
latex_cmd = "xelatex")
function weave(
source::AbstractString;
doctype::Union{Nothing,AbstractString} = nothing,
informat::Union{Nothing,AbstractString} = nothing,
out_path::Union{Symbol,AbstractString} = :doc,
args::Any = Dict(),
mod::Union{Module,Nothing} = nothing,
fig_path::Union{Nothing,AbstractString} = nothing,
fig_ext::Union{Nothing,AbstractString} = nothing,
cache_path::AbstractString = "cache",
cache::Symbol = :off,
template::Union{Nothing,AbstractString,Mustache.MustacheTokens} = nothing,
css::Union{Nothing,AbstractString} = nothing, # TODO: rename to `stylesheet`
highlight_theme::Union{Nothing,Type{<:Highlights.AbstractTheme}} = nothing,
pandoc_options::Vector{<:AbstractString} = DEFAULT_PANDOC_OPTIONS,
latex_cmd::Vector{<:AbstractString} = DEFAULT_LATEX_CMD,
keep_unicode::Bool = false,
)
doc = WeaveDoc(source, informat)
doc = read_doc(source, informat)
doctype == :auto && (doctype = detect_doctype(doc.source))
doc.doctype = doctype
# run document
# ------------
# Read args from document header, overrides command line args
if haskey(doc.header, "options")
(doctype, informat, out_path, args, mod, fig_path, fig_ext,
cache_path, cache, throw_errors, template, highlight_theme, css,
pandoc_options, latex_cmd) = header_args(doc)
# overwrites options with those specified in header, that are needed for running document
# NOTE: these YAML options can NOT be given dynamically
weave_options = get(doc.header, WEAVE_OPTION_NAME, nothing)
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
weave_options = get(doc.header, WEAVE_OPTION_NAME_DEPRECATED, nothing)
end
highlight_theme != nothing && (doc.highlight_theme = highlight_theme)
#theme != nothing && (doc.theme = theme) #Reserved for themes
css != nothing && (doc.css = css)
template != nothing && (doc.template = template)
if !isnothing(weave_options)
doctype = get(weave_options, "doctype", doctype)
specific_options!(weave_options, doctype)
if haskey(weave_options, "out_path")
out_path = let
out_path = weave_options["out_path"]
if out_path == ":doc" || out_path == ":pwd"
Symbol(out_path)
else
normpath(dirname(source), out_path) # resolve relative to this document
end
end
end
mod = get(weave_options, "mod", mod)
mod isa AbstractString && (mod = Main.eval(Meta.parse(mod)))
fig_path = get(weave_options, "fig_path", fig_path)
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))
end
try
doc = run(doc, doctype = doctype,
mod = mod,
out_path=out_path, args = args,
fig_path = fig_path, fig_ext = fig_ext, cache_path = cache_path, cache=cache,
throw_errors = throw_errors)
formatted = format(doc)
doc = run_doc(
doc;
doctype = doctype,
mod = mod,
out_path = out_path,
args = args,
fig_path = fig_path,
fig_ext = fig_ext,
cache_path = cache_path,
cache = cache,
)
outname = get_outname(out_path, doc)
# 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
template isa AbstractString && (template = normpath(dirname(source), template))
end
if haskey(weave_options, "css")
css = weave_options["css"]
# resolve relative to this document
css isa AbstractString && (css = normpath(dirname(source), css))
end
highlight_theme = get(weave_options, "highlight_theme", highlight_theme)
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
open(outname, "w") do io
write(io, formatted)
end
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,
)
#Special for that need external programs
if doc.doctype == "pandoc2html"
mdname = outname
outname = get_outname(out_path, doc, ext = "html")
pandoc2html(formatted, doc, outname, pandoc_options)
rm(mdname)
elseif doc.doctype == "pandoc2pdf"
mdname = outname
outname = get_outname(out_path, doc, ext = "pdf")
pandoc2pdf(formatted, doc, outname, pandoc_options)
rm(mdname)
elseif doc.doctype == "md2pdf"
success = run_latex(doc, outname, latex_cmd)
success && rm(doc.fig_path, force = true, recursive = true)
success || return
outname = get_outname(out_path, doc, ext = "pdf")
end
# render document
# ---------------
rendered = render_doc(doc)
doc.cwd == pwd() && (outname = basename(outname))
@info("Report weaved to $outname")
return abspath(outname)
catch err
@warn("Something went wrong during weaving")
@error(sprint(showerror, err))
return nothing
finally
doctype == :auto && (doctype = detect_doctype(doc.source))
if occursin("2pdf", doctype)
rm(doc.fig_path, force = true, recursive = true)
elseif occursin("2html", doctype)
rm(doc.fig_path, force = true, recursive = true)
# write documents
# ---------------
out_path = write_doc(doc, rendered, get_out_path(doc, out_path))
@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)
for (k,v) in weave_options
if k in fmts
k == doctype && merge!(weave_options, v)
delete!(weave_options, k)
end
end
end
function weave(doc::AbstractString, doctype::AbstractString)
weave(doc, doctype=doctype)
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...)
Convert Weave document `source` to Jupyter Notebook and execute the code
using [`nbconvert`](https://nbconvert.readthedocs.io/en/latest/).
**Ignores** all chunk options.
## Keyword options
- `out_path::Union{Symbol,AbstractString} = :pwd`: Path where the output is generated can be either of:
* `:doc`: Path of the source document
* `:pwd`: Julia working directory (default)
* `"somepath"`: `String` of output directory e.g. `"~/outdir"`, or of filename e.g. `"~/outdir/outfile.tex"`
- `timeout = -1`: nbconvert cell timeout in seconds. Defaults to `-1` (no timeout)
- `nbconvert_options::AbstractString = ""`: `String` of additional options to pass to nbconvert, such as `"--allow-errors"`
- `jupyter_path::AbstractString = "jupyter"`: Path/command for the Jupyter you want to use. Defaults to `"jupyter"`, which runs whatever is linked/alias to that
!!! 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/JunoLab/Weave.jl/issues/116).
!!! note
In order to _just_ convert Weave document to Jupyter Notebook,
use [`convert_doc`](@ref) instead.
"""
function notebook(
source::AbstractString;
out_path::Union{Symbol,AbstractString} = :pwd,
timeout = -1,
nbconvert_options::AbstractString = "",
jupyter_path::AbstractString = "jupyter",
)
doc = WeaveDoc(source)
converted = convert_to_notebook(doc)
doc.cwd = get_cwd(doc, out_path)
out_path = get_out_path(doc, out_path, "ipynb")
write(out_path, converted)
@info "Running nbconvert ..."
return read(
`$jupyter_path nbconvert --ExecutePreprocessor.timeout=$timeout --to notebook --execute $(out_path) $nbconvert_options --output $(out_path)`,
String,
)
end
"""
notebook(source::String, out_path=:pwd, timeout=-1, nbconvert_options="")
include_weave(source::AbstractString, informat::Union{Nothing,AbstractString} = nothing)
include_weave(m::Module, source::AbstractString, informat::Union{Nothing,AbstractString} = nothing)
Convert Weave document `source` to Jupyter notebook and execute the code
using nbconvert. Requires IJulia. **Ignores** all chunk options
* `out_path`: Path where the output is generated. Can be: `:doc`: Path of the source document,
`:pwd`: Julia working directory, `"somepath"`: Path as a
String e.g `"/home/mpastell/weaveout"`
* `timeout`: nbconvert cell timeout in seconds. Defaults to -1 (no timeout)
* `nbconvert_options`: string of additional options to pass to nbconvert, such as `--allow-errors`
Include code from Weave document calling `include_string` on all code from doc.
Code is run in the path of the include document.
"""
function notebook(source::String, out_path=:pwd, timeout=-1, nbconvert_options=[])
doc = read_doc(source)
converted = convert_doc(doc, NotebookOutput())
doc.cwd = get_cwd(doc, out_path)
outfile = get_outname(out_path, doc, ext="ipynb")
open(outfile, "w") do f
write(f, converted)
end
@info("Running nbconvert")
Base.eval(Main, Meta.parse("import IJulia"))
out = read(`$(Main.IJulia.JUPYTER) nbconvert --ExecutePreprocessor.timeout=$timeout --to notebook --execute $outfile $nbconvert_options --output $outfile`, String)
function include_weave(
m::Module,
source::AbstractString,
informat::Union{Nothing,AbstractString} = nothing,
)
old_path = pwd()
doc = WeaveDoc(source, informat)
cd(dirname(doc.path))
try
code = join(
[x.content for x in filter(x -> isa(x, Weave.CodeChunk), doc.chunks)],
"\n",
)
include_string(m, code)
catch err
throw(err)
finally
cd(old_path)
end
return nothing
end
"""
include_weave(doc, informat=:auto)
include_weave(source, informat = nothing) = include_weave(Main, source, informat)
export weave,
list_out_formats,
tangle,
convert_doc,
notebook,
set_chunk_defaults!,
get_chunk_defaults,
restore_chunk_defaults!,
include_weave
Include code from Weave document calling `include_string` on
all code from doc. Code is run in the path of the include document.
"""
function include_weave(source, informat=:auto)
old_path = pwd()
doc = read_doc(source, informat)
cd(doc.path)
try
code = join([x.content for x in
filter(x -> isa(x,Weave.CodeChunk), doc.chunks)], "\n")
include_string(code)
catch e
cd(old_path)
throw(e)
end
end
#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(preexecute_hooks, f))
const postexecute_hooks = Function[]
push_postexecute_hook(f::Function) = push!(postexecute_hooks, f)
pop_postexecute_hook(f::Function) = splice!(postexecute_hooks, findfirst(postexecute_hooks, f))
include("chunks.jl")
include("config.jl")
include("WeaveMarkdown/markdown.jl")
include("display_methods.jl")
include("readers.jl")
include("run.jl")
include("cache.jl")
include("formatters.jl")
include("format.jl")
include("pandoc.jl")
include("writers.jl")
export weave, list_out_formats, tangle, convert_doc, notebook,
set_chunk_defaults, get_chunk_defaults, restore_chunk_defaults,
include_weave
end

View File

@ -1,16 +1,28 @@
#module Markdown2HTML
# Markdown to HTML writer, Modified from Julia Base.Markdown html writer
using Markdown: MD, Header, Code, Paragraph, BlockQuote, Footnote,
Admonition, List, HorizontalRule, Bold, Italic, Image, Link, LineBreak,
LaTeX, isordered
function tohtml(io::IO, m::MIME"text/html", x)
show(io, m, x)
end
using Markdown:
MD,
Header,
Code,
Paragraph,
BlockQuote,
Footnote,
Table,
Admonition,
List,
HorizontalRule,
Bold,
Italic,
Image,
Link,
LineBreak,
LaTeX,
isordered
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,""")
@ -18,11 +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
@ -35,7 +43,6 @@ end
tohtml(io::IO, x) = tohtml(io, bestmime(x), x)
# Utils
function withtag(f, io::IO, tag, attrs...)
@ -56,10 +63,13 @@ end
tag(io::IO, tag, attrs...) = withtag(nothing, io, tag, attrs...)
const _htmlescape_chars = Dict('<'=>"&lt;", '>'=>"&gt;",
'"'=>"&quot;", '&'=>"&amp;",
# ' '=>"&nbsp;",
)
const _htmlescape_chars = Dict(
'<' => "&lt;",
'>' => "&gt;",
'"' => "&quot;",
'&' => "&amp;",
# ' '=>"&nbsp;",
)
for ch in "'`!\$%()=+{}[]"
_htmlescape_chars[ch] = "&#$(Int(ch));"
end
@ -93,7 +103,7 @@ end
html(io::IO, md::MD) = html(io, md.content)
function html(io::IO, header::Header{l}) where l
function html(io::IO, header::Header{l}) where {l}
withtag(io, "h$l") do
htmlinline(io, header.text)
end
@ -141,7 +151,7 @@ function html(io::IO, md::Admonition)
end
function html(io::IO, md::List)
maybe_attr = md.ordered > 1 ? Any[:start => string(md.ordered)] : []
maybe_attr = md.ordered > 1 ? Any[:start=>string(md.ordered)] : []
withtag(io, isordered(md) ? :ol : :ul, maybe_attr...) do
for item in md.items
println(io)
@ -153,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
@ -163,8 +171,20 @@ function html(io::IO, tex::LaTeX)
end
end
function html(io::IO, comment::Comment)
write(io, "\n<!-- $(comment.text) -->\n")
html(io::IO, comment::Comment) = write(io, "\n<!-- $(comment.text) -->\n")
function html(io::IO, md::Table)
withtag(io, :table) do
for (i, row) in enumerate(md.rows)
withtag(io, :tr) do
for c in md.rows[i]
withtag(io, i == 1 ? :th : :td) do
htmlinline(io, c)
end
end
end
end
end
end
html(io::IO, x) = tohtml(io, x)
@ -189,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
@ -205,10 +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
@ -217,23 +232,17 @@ function htmlinline(io::IO, f::Footnote)
end
function htmlinline(io::IO, link::Link)
withtag(io, :a, :href=>link.url) do
withtag(io, :a, :href => link.url) do
htmlinline(io, link.text)
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,20 +1,9 @@
import Markdown: latex, latexinline
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
#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,14 +1,28 @@
#This module extends the julia markdown parser to improve compatibility with Jupyter, Pandoc etc.
# 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
# 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
text::String
end
@breaking true ->
function dollarmath(stream::IO, block::MD)
@breaking true -> function dollarmath(stream::IO, block::MD)
withstream(stream) do
str = Markdown.startswith(stream, r"^\$\$$"m)
isempty(str) && return false
@ -20,29 +34,28 @@ function dollarmath(stream::IO, block::MD)
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
seek(stream, line_start)
end
write(buffer, readline(stream, keep=true))
write(buffer, readline(stream, keep = true))
end
return false
end
end
@breaking true ->
function topcomment(stream::IO, block::MD)
@breaking true -> function topcomment(stream::IO, block::MD)
buffer = IOBuffer()
withstream(stream) do
str = Markdown.startswith(stream, r"^<!--")
isempty(str) && return false
while !eof(stream)
line = readline(stream, keep=true)
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
@ -51,12 +64,11 @@ function topcomment(stream::IO, block::MD)
end
end
@trigger '<' ->
function comment(stream::IO, md::MD)
@trigger '<' -> function comment(stream::IO, md::MD)
withstream(stream) do
Markdown.startswith(stream, "<!--") || return
text = Markdown.readuntil(stream, "-->")
text nothing && return
isnothing(text) && return
return Comment(text)
end
end
@ -73,6 +85,8 @@ for key in keys(Markdown.julia.inner)
end
end
include("html.jl")
include("latex.jl")
end
end # module

View File

@ -1,9 +1,9 @@
#Serialization is imported only if cache is used
# Serialization is imported only if cache is used
function write_cache(doc::WeaveDoc, cache_path)
cache_dir = joinpath(doc.cwd, cache_path)
isdir(cache_dir) || mkpath(cache_dir)
open(joinpath(cache_dir, doc.basename * ".cache"),"w") do io
isdir(cache_dir) || mkpath(cache_dir)
open(joinpath(cache_dir, doc.basename * ".cache"), "w") do io
Serialization.serialize(io, doc)
end
return nothing
@ -11,47 +11,47 @@ end
function read_cache(doc::WeaveDoc, cache_path)
name = joinpath(doc.cwd, cache_path, doc.basename * ".cache")
isfile(name) || return nothing
open(name,"r") do io
isfile(name) || return nothing
open(name, "r") do io
doc = Serialization.deserialize(io)
end
return doc
end
function restore_chunk(chunk::CodeChunk, cached)
chunks = filter(x -> x.number == chunk.number &&
string(typeof(x)) == "Weave.CodeChunk", cached.chunks)
chunks = filter(
x -> x.number == chunk.number && string(typeof(x)) == "Weave.CodeChunk",
cached.chunks,
)
#Chunk types, don't match after loading. Fix by constructing chunks
#from loaded content
new_chunks = Any[]
# Chunk types, don't match after loading. Fix by constructing chunks
# from loaded content
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
newc.rich_output = c.rich_output
push!(new_chunks, newc)
newc = CodeChunk(c.content, c.number, c.start_line, c.optionstring, c.options)
newc.figures = c.figures
newc.result = c.result
newc.output = c.output
newc.rich_output = c.rich_output
push!(new_chunks, newc)
end
return new_chunks
end
#Restore inline code
# Restore inline code
function restore_chunk(chunk::DocChunk, cached::WeaveDoc)
#Get chunk from cached doc
c_chunk = filter(x -> x.number == chunk.number &&
isa(x, DocChunk), cached.chunks)
# Get chunk from cached doc
c_chunk = filter(x -> x.number == chunk.number && isa(x, DocChunk), cached.chunks)
isempty(c_chunk) && return chunk
c_chunk = c_chunk[1]
#Collect cached code
# Collect cached code
c_inline = filter(x -> isa(x, InlineCode), c_chunk.content)
isempty(c_inline) && return chunk
#Restore cached results for Inline code
# Restore cached results for Inline code
n = length(chunk.content)
for i in 1:n
for i = 1:n
if isa(chunk.content[i], InlineCode)
ci = filter(x -> x.number == chunk.content[i].number, c_inline)
isempty(ci) && continue

View File

@ -1,90 +0,0 @@
using Compat
abstract type WeaveChunk end
abstract type Inline end
mutable struct WeaveDoc
source::AbstractString
basename::AbstractString
path::AbstractString
chunks::Array{WeaveChunk}
cwd::AbstractString
format
doctype::AbstractString
header_script::String
header::Dict
template::AbstractString
css::AbstractString
highlight_theme
fig_path::AbstractString
chunk_defaults::Dict{Symbol,Any}
function WeaveDoc(source, chunks, header)
path, fname = splitdir(abspath(source))
basename = splitext(fname)[1]
new(source, basename, path, chunks, "", nothing, "", "", header,
"", "", Highlights.Themes.DefaultTheme, "", deepcopy(rcParams[:chunk_defaults]))
end
end
struct ChunkOutput
code::AbstractString
stdout::AbstractString
displayed::AbstractString
rich_output::AbstractString
figures::Array{AbstractString}
end
mutable struct CodeChunk <: WeaveChunk
content::AbstractString
number::Int
result_no::Int
start_line::Int
optionstring::AbstractString
options::Dict{Symbol, Any}
output::AbstractString
rich_output::AbstractString
figures::Array{AbstractString}
result::Array{ChunkOutput}
function CodeChunk(content, number, start_line, optionstring, options)
new(rstrip(content) * "\n", number, 0, start_line, optionstring, options, "","", AbstractString[], ChunkOutput[])
end
end
mutable struct DocChunk <: WeaveChunk
content::Array{Inline}
number::Int
start_line::Int
function DocChunk(text::AbstractString, number::Int, start_line::Int, inline_regex = nothing)
chunks = parse_inline(text, inline_regex)
new(chunks, number, start_line)
end
end
mutable struct InlineText <: Inline
content::AbstractString
si::Int
ei::Int
number::Int
end
mutable struct InlineCode <: Inline
content::AbstractString
si::Int
ei::Int
number::Int
output::AbstractString
rich_output::AbstractString
figures::Array{AbstractString}
function InlineCode(content, si, ei, number)
new(content, si, ei, number, "", "", AbstractString[])
end
end
mutable struct TermResult
end
mutable struct ScriptResult
end
mutable struct CollectResult
end

View File

@ -1,136 +1,58 @@
#Default options
const defaultParams =
Dict{Symbol,Any}(:storeresults => false,
:doc_number => 0,
: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
)
)
#This one can be changed at runtime, initially a copy of defaults
const rcParams = deepcopy(defaultParams)
# 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,
)
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
to see the current values.
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> set_chunk_defaults(Dict{Symbol, Any}(: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))`
"""
function set_chunk_defaults(opts::Dict{Symbol, Any})
merge!(rcParams[:chunk_defaults], opts)
return nothing
end
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_chunk_defaults()
Get default options used for code chunks.
"""
function get_chunk_defaults()
return(rcParams[:chunk_defaults])
end
get_chunk_defaults() = DEFAULT_PARAMS
"""
`restore_chunk_defaults()`
restore_chunk_defaults!()
Restore Weave.jl default chunk options
Restore Weave.jl default chunk options.
"""
function restore_chunk_defaults()
rcParams[:chunk_defaults] = defaultParams[:chunk_defaults]
return nothing
end
"""Combine format specific and common options from document header"""
function combine_args(args, doctype)
common = Dict()
specific = Dict()
for key in keys(args)
if key keys(Weave.formats)
specific[key] = args[key]
else
common[key] = args[key]
end
end
haskey(specific, doctype) && merge!(common, specific[doctype])
common
end
getvalue(d::Dict, key , default) = haskey(d, key) ? d[key] : default
"""
header_args(doc::WeaveDoc)`
Get weave arguments from document header
"""
function header_args(doc::WeaveDoc)
args = getvalue(doc.header, "options", Dict())
doctype = getvalue(args, "doctype", doc.doctype)
args = combine_args(args, doctype)
informat = getvalue(args, "informat", :auto)
out_path = getvalue(args, "out_path", :doc)
out_path == ":pwd" && (out_path = :pwd)
mod = Symbol(getvalue(args, "mod", :sandbox))
fig_path = getvalue(args, "fig_path", "figures")
fig_ext = getvalue(args, "fig_ext", nothing)
cache_path = getvalue(args, "cache_path", "cache")
cache = Symbol(getvalue(args, "cache", :off))
throw_errors = getvalue(args, "throw_errors", false)
template = getvalue(args, "template", nothing)
highlight_theme = getvalue(args, "highlight_theme", nothing)
css = getvalue(args, "css", nothing)
pandoc_options = getvalue(args, "pandoc_options", String[])
latex_cmd = getvalue(args, "latex_cmd", "xelatex")
return (doctype, informat, out_path, args, mod, fig_path, fig_ext,
cache_path, cache, throw_errors, template, highlight_theme, css,
pandoc_options, latex_cmd)
end
"""
`header_chunk_defaults!(doc::WeaveDoc)`
Get chunk defaults from header and update
"""
function header_chunk_defaults!(doc::WeaveDoc)
for key in keys(doc.chunk_defaults)
if haskey(doc.header["options"], String(key))
doc.chunk_defaults[key] = doc.header["options"][String(key)]
end
end
end
restore_chunk_defaults!() = for (k,v) in _DEFAULT_PARAMS; DEFAULT_PARAMS[k] = v; end

144
src/converter.jl Normal file
View File

@ -0,0 +1,144 @@
using JSON, Mustache
"""
convert_doc(infile::AbstractString, outfile::AbstractString; outformat::Union{Nothing,AbstractString} = nothing)
Convert Weave documents between different formats
- `infile`: Path of the input document
- `outfile`: Path of the output document
- `outformat = nothing`: Output document format (optional). By default (i.e. given `nothing`) Weave will try to automatically detect it from the `outfile`'s extension. You can also specify either of `"script"`, `"markdown"`, `"notebook"`, or `"noweb"`
"""
function convert_doc(
infile::AbstractString,
outfile::AbstractString;
outformat::Union{Nothing,AbstractString} = nothing,
)
doc = WeaveDoc(infile)
if isnothing(outformat)
ext = lowercase(splitext(outfile)[2])
outformat =
ext == ".jl" ? "script" :
ext == ".jmd" ? "markdown" :
ext == ".ipynb" ? "notebook" :
"noweb" # fallback
end
converted = _convert_doc(doc, outformat)
open(outfile, "w") do f
write(f, converted)
end
return outfile
end
function _convert_doc(doc, outformat)
outformat == "script" ? convert_to_script(doc) :
outformat == "markdown" ? convert_to_markdown(doc) :
outformat == "notebook" ? convert_to_notebook(doc) :
convert_to_noweb(doc)
end
function convert_to_script(doc)
output = ""
for chunk in doc.chunks
if typeof(chunk) == Weave.DocChunk
content = join([repr(c) for c in chunk.content], "")
output *= join(["#' " * s for s in split(content, "\n")], "\n")
else
output *= "\n#+ "
isempty(chunk.optionstring) || (output *= strip(chunk.optionstring))
output *= "\n\n" * lstrip(chunk.content)
output *= "\n"
end
end
return output
end
function convert_to_markdown(doc)
output = ""
for chunk in doc.chunks
if isa(chunk, DocChunk)
output *= join([repr(c) for c in chunk.content], "")
else
output *= "\n" * "```julia"
isempty(chunk.optionstring) || (output *= ";" * chunk.optionstring)
output *= "\n" * lstrip(chunk.content)
output *= "```\n"
end
end
return output
end
function convert_to_notebook(doc)
nb = Dict()
nb["nbformat"] = 4
nb["nbformat_minor"] = 2
metadata = Dict()
kernelspec = Dict()
kernelspec["language"] = "julia"
kernelspec["name"] = "julia-$(VERSION.major).$(VERSION.minor)"
kernelspec["display_name"] = "Julia $(VERSION.major).$(VERSION.minor).$(VERSION.patch)"
metadata["kernelspec"] = kernelspec
language_info = Dict()
language_info["file_extension"] = ".jl"
language_info["mimetype"] = "application/julia"
language_info["name"] = "julia"
language_info["version"] = "$(VERSION.major).$(VERSION.minor).$(VERSION.patch)"
metadata["language_info"] = language_info
cells = []
ex_count = 1
for chunk in doc.chunks
if isa(chunk, DocChunk)
push!(
cells,
Dict(
"cell_type" => "markdown",
"metadata" => Dict(),
"source" => [strip(join([repr(c) for c in chunk.content], ""))],
),
)
else
push!(
cells,
Dict(
"cell_type" => "code",
"metadata" => Dict(),
"source" => [strip(chunk.content)],
"execution_count" => nothing,
"outputs" => [],
),
)
end
end
nb["cells"] = cells
nb["metadata"] = metadata
json_nb = JSON.json(nb, 2)
return json_nb
end
function convert_to_noweb(doc)
output = ""
for chunk in doc.chunks
if isa(chunk, DocChunk)
output *= join([repr(c) for c in chunk.content], "")
else
output *= "\n" * "<<"
isempty(chunk.optionstring) || (output *= strip(chunk.optionstring))
output *= ">>="
output *= "\n" * lstrip(chunk.content)
output *= "@\n"
end
end
return output
end
Base.repr(c::InlineText) = c.content
Base.repr(c::InlineCode) = "`j $(c.content)`"

View File

@ -1,56 +1,51 @@
using Compat
using Markdown
import .WeaveMarkdown
using Markdown, .WeaveMarkdown
#Contains report global properties
# 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
fignum::Int
figures::Array{AbstractString}
term_state::Symbol
cur_chunk
mimetypes::Array{AbstractString}
first_plot::Bool
header_script::String
throw_errors::Bool
cwd::String
basename::String
format::WeaveFormat
rich_output::String
fignum::Int
figures::Vector{String}
cur_chunk::Union{Nothing,CodeChunk}
mimetypes::Vector{String}
first_plot::Bool
header_script::String
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
# 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"]
#const default_mime_types = ["image/png", "image/svg+xml", "text/html", "text/plain"]
#From IJulia as a reminder
#const supported_mime_types = [ "text/html", "text/latex", "image/svg+xml", "image/png", "image/jpeg", "text/plain", "text/markdown" ]
# const default_mime_types = ["image/png", "image/svg+xml", "text/html", "text/plain"]
# From IJulia as a reminder
# const supported_mime_types = [ "text/html", "text/latex", "image/svg+xml", "image/png", "image/jpeg", "text/plain", "text/markdown" ]
const mimetype_ext =
Dict(".png" => "image/png",
".jpg" => "image/jpeg",
".jpeg" => "image/jpeg",
".svg" => "image/svg+xml",
".pdf" => "application/pdf")
const mimetype_ext = Dict(
".png" => "image/png",
".jpg" => "image/jpeg",
".jpeg" => "image/jpeg",
".svg" => "image/svg+xml",
".js.svg" => "image/svg+xml",
".pdf" => "application/pdf",
".ps" => "application/postscript",
".tex" => "text/latex",
)
function Base.display(report::Report, data)
#Set preferred mimetypes for report based on format
# Set preferred mimetypes for report based on format
fig_ext = report.cur_chunk.options[:fig_ext]
for m in unique([mimetype_ext[fig_ext] ; report.mimetypes])
if showable(m, data)
for m in unique([mimetype_ext[fig_ext]; report.mimetypes])
if Base.invokelatest(showable, m, data)
try
if !istextmime(m)
Compat.invokelatest(display, report, m, data)
Base.invokelatest(display, report, m, data)
elseif report.cur_chunk.options[:term]
Compat.invokelatest(display, report, "text/plain", data)
Base.invokelatest(display, report, "text/plain", data)
else
Compat.invokelatest(display, report, m, data)
Base.invokelatest(display, report, m, data)
end
catch e
throw(e)
@ -62,19 +57,13 @@ function Base.display(report::Report, data)
end
end
function Base.display(report::Report, m::MIME"image/png", data)
figname = add_figure(report, data, m, ".png")
end
Base.display(report::Report, m::MIME"image/png", data) = add_figure(report, data, m, ".png")
function Base.display(report::Report, m::MIME"image/svg+xml", data)
figname = add_figure(report, data, m, ".svg")
end
Base.display(report::Report, m::MIME"image/svg+xml", data) = add_figure(report, data, m, ".svg")
function Base.display(report::Report, m::MIME"application/pdf", data)
figname = add_figure(report, data, m, ".pdf")
end
Base.display(report::Report, m::MIME"application/pdf", data) = add_figure(report, data, m, ".pdf")
#Text is written to stdout, called from "term" mode chunks
# Text is written to stdout, called from "term" mode chunks
function Base.display(report::Report, m::MIME"text/plain", data)
io = PipeBuffer()
show(IOContext(io, :limit => true), m, data)
@ -93,24 +82,25 @@ function Base.display(report::Report, m::MIME"text/html", data::Exception)
end
function Base.show(io, m::MIME"text/html", data::Exception)
println(io ,"<pre class=\"julia-error\">")
println(io, "<pre class=\"julia-error\">")
println(io, Markdown.htmlesc("ERROR: " * sprint(showerror, data)))
println(io ,"</pre>")
println(io, "</pre>")
end
#Catch "rich_output"
# Catch "rich_output"
function Base.display(report::Report, m::MIME"text/html", data)
s = repr(m, data)
report.rich_output *= "\n" * s
io = IOBuffer()
show(IOContext(io, :limit => true), m, data)
report.rich_output *= string('\n', take2string!(io))
end
#Catch "rich_output"
# Catch "rich_output"
function Base.display(report::Report, m::MIME"text/markdown", data)
s = repr(m, data)
# Convert to "richer" type of possible
for m in report.mimetypes
if m == "text/html" || m == "text/latex"
display(Markdown.parse(s, flavor=WeaveMarkdown.weavemd))
display(Markdown.parse(s, flavor = WeaveMarkdown.weavemd))
break
elseif m == "text/markdown"
report.rich_output *= "\n" * s
@ -121,23 +111,23 @@ 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"""
function add_figure(report::Report, data, m, ext)
chunk = report.cur_chunk
full_name, rel_name = get_figname(report, chunk, ext = ext)
chunk = report.cur_chunk
full_name, rel_name = get_figname(report, chunk, ext = ext)
open(full_name, "w") do io
if ext == ".pdf"
write(io, repr(m, data))
else
show(io, m, data)
end
end
open(full_name, "w") do io
if ext == ".pdf"
write(io, repr(m, data))
else
show(io, m, data)
end
end
push!(report.figures, rel_name)
report.fignum += 1
return full_name
push!(report.figures, rel_name)
report.fignum += 1
return full_name
end

View File

@ -1,343 +0,0 @@
import Mustache, Highlights
import .WeaveMarkdown
using Compat
using Dates
using Markdown
using REPL.REPLCompletions: latex_symbols
function format(doc::WeaveDoc)
formatted = AbstractString[]
docformat = doc.format
#Complete format dictionaries with defaults
formatdict = docformat.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)
docformat.formatdict[:cwd] = doc.cwd #pass wd to figure formatters
docformat.formatdict[:theme] = doc.highlight_theme
#strip header
if isa(doc.chunks[1], DocChunk)
if occursin("md2", doc.doctype)
doc.chunks[1] = strip_header(doc.chunks[1])
end
end
for chunk in copy(doc.chunks)
result = format_chunk(chunk, formatdict, docformat)
push!(formatted, result)
end
formatted = join(formatted, "\n")
# Render using a template if needed
rendered = render_doc(formatted, doc, doc.format)
return rendered
end
"""
render_doc(formatted::AbstractString, format)
Render formatted document to a template
"""
function render_doc(formatted, doc::WeaveDoc, format)
return formatted
end
function highlight(mime::MIME, source::AbstractString, lexer, theme=Highlights.Themes.DefaultTheme)
return sprint( (io, x) -> Highlights.highlight(io, mime, x, lexer, theme), source)
end
function stylesheet(m::MIME, theme)
return sprint( (io, x) -> Highlights.stylesheet(io, m, x), theme)
end
function render_doc(formatted, doc::WeaveDoc, format::JMarkdown2HTML)
css = stylesheet(MIME("text/html"), doc.highlight_theme)
path, wsource = splitdir(abspath(doc.source))
#wversion = string(Pkg.installed("Weave"))
wversion = ""
wtime = string(Date(now()))
if isempty(doc.css)
theme_css = read(joinpath(dirname(@__FILE__), "../templates/skeleton_css.css"), String)
else
theme_css = read(doc.css, String)
end
if isempty(doc.template)
template = Mustache.template_from_file(joinpath(dirname(@__FILE__), "../templates/julia_html.tpl"))
else
template = Mustache.template_from_file(doc.template)
end
return Mustache.render(template; themecss = theme_css,
highlightcss = css, body = formatted, header_script = doc.header_script,
source = wsource, wtime = wtime, wversion = wversion,
[Pair(Symbol(k), v) for (k,v) in doc.header]...)
end
function render_doc(formatted, doc::WeaveDoc, format::JMarkdown2tex)
highlight = stylesheet(MIME("text/latex"), doc.highlight_theme)
path, wsource = splitdir(abspath(doc.source))
#wversion = string(Pkg.installed("Weave"))
wversion = ""
wtime = string(Date(now()))
if isempty(doc.template)
template = Mustache.template_from_file(joinpath(dirname(@__FILE__), "../templates/julia_tex.tpl"))
else
template = Mustache.template_from_file(doc.template)
end
return Mustache.render(template; body = formatted,
highlight = highlight,
[Pair(Symbol(k), v) for (k,v) in doc.header]...)
end
function strip_header(chunk::DocChunk)
if occursin(r"^---$(?<header>.+)^---$"ms, chunk.content[1].content)
chunk.content[1].content = lstrip(replace(chunk.content[1].content, r"^---$(?<header>.+)^---$"ms => ""))
end
return chunk
end
function format_chunk(chunk::DocChunk, formatdict, docformat)
return join([format_inline(c) for c in chunk.content], "")
end
function format_inline(inline::InlineText)
return inline.content
end
function format_inline(inline::InlineCode)
isempty(inline.rich_output) || return inline.rich_output
isempty(inline.figures) || return inline.figures[end]
isempty(inline.output) || return inline.output
end
function format_chunk(chunk::DocChunk, formatdict, docformat::JMarkdown2HTML)
text = format_chunk(chunk, formatdict, nothing)
#invokelatest seems to be needed here
#to fix "invalid age range" on 0.6 #21653
#m = Compat.invokelatest(Markdown.parse, text)
m = Markdown.parse(text, flavor=WeaveMarkdown.weavemd)
return string(WeaveMarkdown.html(m))
end
function format_chunk(chunk::DocChunk, formatdict, docformat::JMarkdown2tex)
text = format_chunk(chunk, formatdict, nothing)
m = Markdown.parse(text, flavor=WeaveMarkdown.weavemd)
return uc2tex(Markdown.latex(m))
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
function format_output(result::AbstractString, docformat)
return result
end
function format_output(result::AbstractString, docformat::JMarkdown2HTML)
return Markdown.htmlesc(result)
end
function format_output(result::AbstractString, docformat::JMarkdown2tex)
return uc2tex(result, true)
end
function format_code(result::AbstractString, docformat)
return result
end
function format_code(result::AbstractString, docformat::JMarkdown2tex)
highlighted = highlight(MIME("text/latex"), strip(result),
Highlights.Lexers.JuliaLexer, docformat.formatdict[:theme])
return uc2tex(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::AbstractString, docformat::JMarkdown2HTML)
return highlight(MIME("text/html"), strip(result),
Highlights.Lexers.JuliaLexer, docformat.formatdict[:theme])
end
function format_code(result::AbstractString, 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 indent(text, nindent)
return join(map(x->
string(repeat(" ", nindent), x), split(text, "\n")), "\n")
end
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,534 +0,0 @@
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"]
))
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]{julia}",
: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"]
))
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"))
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 = 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 formatfigures(chunk, docformat::Tex)
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]
if f_env == nothing && caption != nothing
f_env = "figure"
end
f_pos == nothing && (f_pos = "!h")
result = ""
figstring = ""
#Set size
attribs = ""
width == nothing || (attribs = "width=$width")
(attribs != "" && height != nothing ) && (attribs *= ",")
height == nothing || (attribs *= "height=$height")
if f_env != nothing
result *= """\\begin{$f_env}[$f_pos]\n"""
end
for fig = fignames
if splitext(fig)[2] == ".tex" #Tikz figures
figstring *= "\\resizebox{$width}{!}{\\input{$fig}}\n"
else
figstring *= "\\includegraphics[$attribs]{$fig}\n"
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
function formatfigures(chunk, docformat::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=$width")
(attribs != "" && height != nothing ) && (attribs *= ",")
height == nothing || (attribs *= "height=$height")
if f_env != nothing
result *= """\\begin{$f_env}[$f_pos]\n"""
end
for fig = 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 = 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 = 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 = 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=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=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{AbstractString, Any}("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,27 +1,28 @@
module GadflyPlots
import Gadfly
import Weave
try
import Cairo
catch
@warn("Cairo.jl is required to be installed to generate raster images")
end
using ..Weave, ..Gadfly
Gadfly.set_default_plot_format(:svg)
Base.showable(m::MIME"application/pdf", p::Gadfly.Plot) = true
Base.showable(m::MIME"application/png", p::Gadfly.Plot) = true
function Base.display(report::Weave.Report, m::MIME"application/pdf", p::Gadfly.Plot)
display(report, MIME("image/svg+xml"), p)
end
function Base.display(report::Weave.Report, m::MIME"image/png", p::Gadfly.Plot)
display(report, MIME("image/svg+xml"), p)
end
#Gadfly doesn't call the default display methods, this catches
#all Gadfly plots
# Gadfly doesn't call the default display methods, this catches
# all Gadfly plots
function Base.display(report::Weave.Report, m::MIME"image/svg+xml", p::Gadfly.Plot)
chunk = report.cur_chunk
w = chunk.options[:fig_width]Gadfly.inch
h = chunk.options[:fig_height]Gadfly.inch
w = chunk.options[:fig_width] * Gadfly.inch
h = chunk.options[:fig_height] * Gadfly.inch
format = chunk.options[:fig_ext]
dpi = chunk.options[:dpi]
@ -35,15 +36,16 @@ function Base.display(report::Weave.Report, m::MIME"image/svg+xml", p::Gadfly.Pl
elseif format == ".js.svg"
Gadfly.draw(Gadfly.SVGJS(full_name, w, h), p)
elseif format == ".png"
Gadfly.draw(Gadfly.PNG(full_name, w, h, dpi=dpi), p)
Gadfly.draw(Gadfly.PNG(full_name, w, h, dpi = dpi), p)
elseif format == ".pdf"
Gadfly.draw(Gadfly.PDF(full_name, w, h), p)
elseif format == ".ps"
Gadfly.draw(Gadfly.PS(full_name, w, h), p)
elseif format == ".tex"
Gadfly.draw(Gadfly.PGF(full_name, w, h, true ), p)
Gadfly.draw(Gadfly.PGF(full_name, w, h, true), p)
else
@warn("Can't save figure. Unsupported format, $format")
end
end
end
end

View File

@ -1,126 +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")
css = stylesheet(MIME("text/html"), doc.highlight_theme)
path, wsource = splitdir(abspath(doc.source))
#wversion = string(Pkg.installed("Weave"))
wversion = ""
wtime = string(Date(now()))
#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
old_wd = pwd()
cd(doc.cwd)
html =""
outname = basename(outname)
open("temp.md", "w") do io
println(io, formatted)
end
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 wtime=$wtime -V wsource=$wsource
-V highlightcss=$css
-V headerscript=$header_script
-o $outname`
proc = open(cmd, "r+")
println(proc.in, formatted)
close(proc.in)
proc_output = read(proc.out, String)
cd(old_wd)
catch e
cd(old_wd)
@warn("Error converting document to HTML")
throw(e)
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))
#wversion = string(Pkg.installed("Weave"))
wversion = ""
wtime = Date(now())
outname = basename(outname)
#Change path for pandoc
old_wd = pwd()
cd(doc.cwd)
html =""
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)
cd(old_wd)
catch e
cd(old_wd)
@warn("Error converting document to pdf")
throw(e)
end
end
function run_latex(doc::WeaveDoc, outname, latex_cmd = "xelatex")
old_wd = pwd()
cd(doc.cwd)
xname = basename(outname)
@info("Weaved code to $outname. Running $latex_cmd")
textmp = mktempdir(".")
try
out = read(`$latex_cmd -shell-escape $xname -aux-directory $textmp -include-directory $(doc.cwd)`, String)
out = read(`$latex_cmd -shell-escape $xname -aux-directory $textmp -include-directory $(doc.cwd)`, String)
rm(xname)
rm(textmp, recursive=true)
cd(old_wd)
return true
catch e
@warn("Error converting document to pdf. Try running latex manually")
cd(old_wd)
rm(textmp)
return false
end
end

View File

@ -1,67 +1,81 @@
module WeavePlots
import Plots
import Weave
"""Pre-execute hooks to set the plot size for the 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
using ..Base64, ..Plots, ..Weave
# Pre-execute hooks to set the plot size for the 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))
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")
start = split(splitted[1], r"(?=<div)")
#script = lstrip(start[1]) #local
# 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")
start = split(splitted[1], r"(?=<div)")
# script = lstrip(start[1]) # local
div = lstrip(start[2])
plot = join(map(lstrip, splitted[2:end]), "\n")
div = lstrip(start[2])
plot = join(map(lstrip, splitted[2:end]), "\n")
if report.first_plot
report.header_script *= "<script src=\"https://cdn.plot.ly/plotly-latest.min.js\"></script>"
report.first_plot = false
end
if report.first_plot
report.header_script *= "<script src=\"https://cdn.plot.ly/plotly-latest.min.js\"></script>"
report.first_plot = false
end
report.rich_output *= "\n" * div * "\n" * plot
end
function Base.display(report::Weave.Report, m::MIME"image/png", data::Plots.Plot{Plots.PlotlyBackend})#
display(report, MIME("image/svg+xml"), data)
function Base.display(
report::Weave.Report,
m::MIME"image/png",
data::Plots.Plot{Plots.PlotlyBackend},
)
display(report, MIME("image/svg+xml"), data)
end
# PNG or SVG is not working, output html
function Base.display(
report::Weave.Report,
m::MIME"image/svg+xml",
plot::Plots.Plot{Plots.PlotlyJSBackend},
)
body = Plots.PlotlyJS.html_body(plot.o.plot)
#PNG or SVG is not working, output html
function Base.display(report::Weave.Report, m::MIME"image/svg+xml", plot::Plots.Plot{Plots.PlotlyJSBackend})
body = Plots.PlotlyJS.html_body(plot.o.plot)
if report.first_plot
report.header_script *= "<script src=\"https://cdn.plot.ly/plotly-latest.min.js\"></script>"
report.first_plot = false
end
if report.first_plot
report.header_script *= "<script src=\"https://cdn.plot.ly/plotly-latest.min.js\"></script>"
report.first_plot = false
end
report.rich_output *= "\n" * body
report.rich_output *= "\n" * body
end
function Base.display(report::Weave.Report, m::MIME"image/png", plot::Plots.Plot{Plots.PlotlyJSBackend})
display(report, MIME("image/svg+xml"), data)
function Base.display(
report::Weave.Report,
m::MIME"image/png",
plot::Plots.Plot{Plots.PlotlyJSBackend},
)
display(report, MIME("image/svg+xml"), data)
end
"""Add saved figure name to results and return the name"""
function add_plots_figure(report::Weave.Report, plot::Plots.Plot, ext)
chunk = report.cur_chunk
full_name, rel_name = Weave.get_figname(report, chunk, ext = ext)
chunk = report.cur_chunk
full_name, rel_name = Weave.get_figname(report, chunk, ext = ext)
Plots.savefig(plot, full_name)
push!(report.figures, rel_name)
report.fignum += 1
return full_name
Plots.savefig(plot, full_name)
push!(report.figures, rel_name)
report.fignum += 1
return full_name
end
function Base.display(report::Weave.Report, m::MIME"application/pdf", plot::Plots.Plot)
@ -78,21 +92,21 @@ end
# write out html to view Animated gif
function Base.display(report::Weave.Report, ::MIME"text/html", agif::Plots.AnimatedGif)
ext = agif.filename[end-2:end]
res = ""
if ext == "gif"
img = stringmime(MIME("image/gif"), read(agif.filename))
res = "<img src=\"data:image/gif;base64,$img\" />"
elseif ext in ("mov", "mp4")
#Uncomment to embed mp4, make global or chunk option?
#img = stringmime(MIME("video/$ext"), read(agif.filename))
#res = "<video controls><source src=\"data:video/$(ext);base64,$img\" type=\"video/$ext\"></video>"
res = "<video controls><source src=\"$(relpath(agif.filename))\" type=\"video/$ext\"></video>"
else
error("Cannot show animation with extension $ext: $agif")
end
ext = agif.filename[end-2:end]
res = ""
if ext == "gif"
img = stringmime(MIME("image/gif"), read(agif.filename))
res = "<img src=\"data:image/gif;base64,$img\" />"
elseif ext in ("mov", "mp4")
# Uncomment to embed mp4, make global or chunk option?
# img = stringmime(MIME("video/$ext"), read(agif.filename))
# res = "<video controls><source src=\"data:video/$(ext);base64,$img\" type=\"video/$ext\"></video>"
res = "<video controls><source src=\"$(relpath(agif.filename))\" type=\"video/$ext\"></video>"
else
error("Cannot show animation with extension $ext: $agif")
end
report.rich_output *= "\n" * res * "\n"
report.rich_output *= "\n" * res * "\n"
end
end

View File

@ -1,20 +0,0 @@
import PyPlot
function savefigs_pyplot(report::Report)
chunk = report.cur_chunk
fignames = AbstractString[]
ext = report.formatdict[:fig_ext]
figpath = joinpath(report.cwd, chunk.options[:fig_path])
isdir(figpath) || mkdir(figpath)
chunkid = (chunk.options[:label] == nothing) ? chunk.number : chunk.options[:label]
#Iterate over all open figures, save them and store names
for fig = PyPlot.plt[:get_fignums]()
full_name, rel_name = get_figname(report, chunk, fignum=fig)
PyPlot.savefig(full_name, dpi=chunk.options[:dpi])
push!(report.figures, rel_name)
report.fignum += 1
PyPlot.plt[:draw]()
PyPlot.plt[:close]()
end
end

95
src/reader/markdown.jl Normal file
View File

@ -0,0 +1,95 @@
function parse_markdown(document_body; is_pandoc = false)
header_text, document_body, offset = separate_header_text(document_body)
header = parse_header(header_text)
code_start, code_end = if is_pandoc
r"^<<(?<options>.*?)>>=\s*$",
r"^@\s*$"
else
r"^[`~]{3}(\{?)julia\s*([;,\{]?)\s*(?<options>.*?)(\}|\s*)$",
r"^[`~]{3}\s*$"
end
return header, parse_markdown_body(document_body, code_start, code_end, offset)
end
# headers
# -------
const HEADER_REGEX = r"^---$(?<header>((?!---).)+)^---$"ms
# TODO: non-Weave headers should keep live in a doc
# separates header section from `text`
function separate_header_text(text)
m = match(HEADER_REGEX, text)
isnothing(m) && return "", text, 0
header_text = m[:header]
offset = @static if VERSION v"1.4"
count("\n", header_text)
else
count(c->c==='\n', header_text)
end
return header_text, replace(text, HEADER_REGEX => ""; count = 1), offset
end
# HACK:
# YAML.jl can't parse text including ``` characters, so first replace all the inline code
# with these temporary code start/end string
const HEADER_INLINE_START = "<weave_header_inline_start>"
const HEADER_INLINE_END = "<weave_header_inline_end>"
function parse_header(header_text)
isempty(header_text) && return Dict()
pat = INLINE_REGEX => SubstitutionString("$(HEADER_INLINE_START)\\1$(HEADER_INLINE_END)")
header_text = replace(header_text, pat)
return YAML.load(header_text)
end
# body
# ----
function parse_markdown_body(document_body, code_start, code_end, offset)
lines = split(document_body, '\n')
state = :doc
doc_no = 0
code_no = 0
content = ""
start_line = offset
options = OptionDict()
option_string = ""
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)
isempty(strip(content)) || push!(chunks, DocChunk(content, doc_no += 1, start_line))
start_line = line_no + offset
content = ""
continue
end
if occursin(code_end, line) && state === :code
push!(chunks, CodeChunk(content, code_no += 1, start_line, option_string, options))
start_line = line_no + offset
content = ""
state = :doc
continue
end
content *= isone(line_no) ? line : string('\n', line)
end
# Remember the last chunk
isempty(strip(content)) || push!(chunks, DocChunk(content, doc_no += 1, start_line))
return chunks
end

23
src/reader/notebook.jl Normal file
View File

@ -0,0 +1,23 @@
using JSON
function parse_notebook(document_body)
nb = JSON.parse(document_body)
code_no = 0
doc_no = 0
# TODO: handle some of options ?
options = Dict{Symbol,Any}()
opt_string = ""
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
DocChunk(text, doc_no += 1, 0; notebook = true)
end
end
return Dict(), chunks
end

128
src/reader/reader.jl Normal file
View File

@ -0,0 +1,128 @@
using YAML
function WeaveDoc(source, informat = nothing)
path = abspath(source)
_, fname = splitdir(path)
basename = splitext(fname)[1]
isnothing(informat) && (informat = detect_informat(source))
header, chunks = parse_doc(read(source, String), informat)
# update default chunk options from header
chunk_defaults = deepcopy(get_chunk_defaults())
if (weave_options = get(header, WEAVE_OPTION_NAME, nothing)) !== nothing
for key in keys(chunk_defaults)
if (val = get(weave_options, string(key), nothing)) !== nothing
chunk_defaults[key] = val
end
end
end
if haskey(header, WEAVE_OPTION_NAME_DEPRECATED)
@warn "Weave: `options` key is deprecated. Use `weave_options` key instead." _id = WEAVE_OPTION_DEPRECATE_ID maxlog = 1
for key in keys(chunk_defaults)
if (val = get(header[WEAVE_OPTION_NAME_DEPRECATED], string(key), nothing)) !== nothing
chunk_defaults[key] = val
end
end
end
return WeaveDoc(
source,
basename,
path,
chunks,
"",
nothing,
"",
"",
header,
chunk_defaults,
)
end
"""
detect_informat(path)
Detect Weave input format based on file extension of `path`.
"""
function detect_informat(path)
ext = lowercase(last(splitext(path)))
ext == ".jl" && return "script"
ext == ".jmd" && return "markdown"
ext == ".ipynb" && return "notebook"
return "noweb"
end
function parse_doc(document, informat)
document = replace(document, "\r\n" => "\n") # normalize line ending
return informat == "markdown" ? parse_markdown(document) :
informat == "noweb" ? parse_markdown(document; is_pandoc = true) :
informat == "script" ? parse_script(document) :
informat == "notebook" ? parse_notebook(document) :
error("unsupported input format given: $informat")
end
# inline
# ------
function DocChunk(text::AbstractString, number, start_line; notebook = false)
# don't parse inline code in notebook
content = notebook ? parse_inline(text) : parse_inlines(text)
return DocChunk(content, number, start_line)
end
const INLINE_REGEX = r"`j\s+(.*?)`"
const INLINE_REGEXES = r"`j\s+(.*?)`|^!\s(.*)$"m
# handle code units correctly !
function parse_inlines(str)
ret = Inline[]
s = 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!(ret, InlineText(str[s:end], text_no += 1))
return ret
end
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")
include("notebook.jl")

67
src/reader/script.jl Normal file
View File

@ -0,0 +1,67 @@
function parse_script(document_body)
lines = split(document_body, '\n')
doc_line = r"(^#'.*)|(^#%%.*)|(^# %%.*)"
doc_start = r"(^#')|(^#%%)|(^# %%)"
opt_line = r"(^#\+.*$)|(^#%%\+.*$)|(^# %%\+.*$)"
opt_start = r"(^#\+)|(^#%%\+)|(^# %%\+)"
content = ""
state = :code
doc_no = 0
code_no = 0
start_line = 1
options = OptionDict()
option_string = ""
chunks = WeaveChunk[]
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)
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
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
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
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
continue
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 = line_no
end
content *= string(line, '\n')
end
# Handle the last chunk
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

View File

@ -1,312 +0,0 @@
import JSON, YAML
pushopt(options::Dict,expr::Expr) = Base.Meta.isexpr(expr,:(=)) && (options[expr.args[1]] = expr.args[2])
mutable struct MarkupInput
codestart::Regex
codeend::Regex
inline::Regex
end
mutable struct ScriptInput
doc_line::Regex
doc_start::Regex
opt_line::Regex
opt_start::Regex
inline::Regex
end
mutable struct NotebookInput
inline
end
const input_formats = Dict{AbstractString, Any}(
"noweb" => MarkupInput(r"^<<(.*?)>>=\s*$",
r"^@\s*$",
r"`j\s+(.*?)`"s
),
"markdown" => MarkupInput(
r"^[`~]{3,}(?:\{|\{\.|)julia(?:;|)\s*(.*?)(\}|\s*)$",
r"^[`~]{3,}\s*$",
r"`j\s+(.*?)`"s),
"script" => ScriptInput(
r"(^#'.*)|(^#%%.*)|(^# %%.*)",
r"(^#')|(^#%%)|(^# %%)",
r"(^#\+.*$)|(^#%%\+.*$)|(^# %%\+.*$)",
r"(^#\+)|(^#%%\+)|(^# %%\+)",
r"`j\s+(.*?)`"s),
"notebook" => NotebookInput(nothing) #Don't parse inline code from notebooks
)
"""Detect the input format based on file extension"""
function detect_informat(source::AbstractString)
ext = lowercase(splitext(source)[2])
ext == ".jl" && return "script"
ext == ".jmd" && return "markdown"
ext == ".ipynb" && return "notebook"
return "noweb"
end
"""Read and parse input document"""
function read_doc(source::AbstractString, format=:auto)
format == :auto && (format = detect_informat(source))
document = read(source, String)
document = replace(document, "\r\n" => "\n")
parsed = parse_doc(document, format)
header = parse_header(parsed[1])
doc = WeaveDoc(source, parsed, header)
haskey(header, "options") && header_chunk_defaults!(doc)
return doc
end
function parse_header(chunk::CodeChunk)
return Dict()
end
function parse_header(chunk::DocChunk)
m = match(r"^---$(?<header>.+)^---$"ms, chunk.content[1].content)
if m !== nothing
header = YAML.load(string(m[:header]))
else
header = Dict()
end
return header
end
function parse_doc(document::AbstractString, format="noweb"::AbstractString)
return parse_doc(document, input_formats[format])
end
"""Parse documents with Weave.jl markup"""
function parse_doc(document::AbstractString, format::MarkupInput)
document = replace(document, "\r\n" => "\n")
lines = split(document, "\n")
codestart = format.codestart
codeend = format.codeend
state = "doc"
docno = 1
codeno = 1
content = ""
start_line = 0
options = Dict()
optionString = ""
parsed = Any[]
for lineno in 1:length(lines)
line = lines[lineno]
if (m = match(codestart, line)) != nothing && state=="doc"
state = "code"
if m.captures[1] == nothing
optionString = ""
else
optionString=strip(m.captures[1])
end
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
haskey(options, :label) && (options[:name] = options[:label])
haskey(options, :name) || (options[:name] = nothing)
if !isempty(strip(content))
chunk = DocChunk(content, docno, start_line, format.inline)
docno += 1
push!(parsed, chunk)
end
content = ""
start_line = lineno
continue
end
if occursin(codeend, line) && state=="code"
chunk = CodeChunk(content, codeno, start_line, optionString, options)
codeno+=1
start_line = lineno
content = ""
state = "doc"
push!(parsed, chunk)
continue
end
if lineno == 1
content *= line
else
content *= "\n" * line
end
end
#Remember the last chunk
if strip(content) != ""
chunk = DocChunk(content, docno, start_line, format.inline)
#chunk = Dict{Symbol,Any}(:type => "doc", :content => content,
# :number => docno, :start_line => start_line)
push!(parsed, chunk)
end
return parsed
end
"""Parse .jl scripts with Weave.jl markup"""
function parse_doc(document::AbstractString, format::ScriptInput)
document = replace(document, "\r\n" => "\n")
lines = split(document, "\n")
doc_line = format.doc_line
doc_start = format.doc_start
opt_line = format.opt_line
opt_start = format.opt_start
read = ""
chunks = []
docno = 1
codeno = 1
content = ""
start_line = 1
options = Dict{Symbol,Any}()
optionString = ""
parsed = Any[]
state = "code"
lineno = 1
n_emptylines = 0
for lineno in 1:length(lines)
line = lines[lineno]
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)
end
if state == "code" && strip(read) != ""
chunk = CodeChunk("\n" * strip(read), codeno, start_line, optionString, options)
push!(parsed, chunk)
codeno +=1
read = ""
start_line = lineno
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!(parsed, 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!(parsed, chunk)
read = ""
docno += 1
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
haskey(options, :label) && (options[:name] = options[:label])
haskey(options, :name) || (options[:name] = nothing)
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, format.inline)
push!(parsed, chunk)
options = Dict{Symbol,Any}()
start_line = lineno
read = ""
docno += 1
end
read *= line * "\n"
if strip(line) == ""
n_emptylines += 1
else
n_emptylines = 0
end
end
# Handle the last chunk
if state == "code"
chunk = CodeChunk("\n" * strip(read), codeno, start_line, optionString, options)
push!(parsed, chunk)
else
chunk = DocChunk(read, docno, start_line, format.inline)
push!(parsed, chunk)
end
return parsed
end
"""Parse IJUlia notebook"""
function parse_doc(document::String, format::NotebookInput)
document = replace(document, "\r\n" => "\n")
nb = JSON.parse(document)
parsed = Any[]
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!(parsed, chunk)
codeno += 1
else
chunk = DocChunk(srctext * "\n", docno, 0)
push!(parsed, chunk)
docno +=1
end
end
return parsed
end
#Use this if regex is undefined
function parse_inline(text, noex)
return Inline[InlineText(text, 1, length(text), 1)]
end
function parse_inline(text::AbstractString, inline_ex::Regex)
occursin(inline_ex, text) || return Inline[InlineText(text, 1, length(text), 1)]
inline_chunks = eachmatch(inline_ex, text)
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)
push!(res, InlineCode(ic.captures[1], s, e, codeno))
codeno += 1
end
push!(res, InlineText(text[e:end], e, length(text), textno))
return res
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

@ -1,185 +1,181 @@
using Base64
"""
run(doc::WeaveDoc; doctype = :auto,
mod::Union{Module, Symbol} = :sandbox, out_path=:doc,
args=Dict(), fig_path = "figures", fig_ext = nothing,
cache_path = "cache", cache = :off, throw_errors=false)
Run code chunks and capture output from parsed document.
const PROGRESS_ID = "weave_progress"
* `doctype`: :auto = set based on file extension or specify one of the supported formats.
See `list_out_formats()`
* `out_path`: Path where the output is generated. Can be: `:doc`: Path of the source document, `:pwd`: Julia working directory,
`"somepath"`: Path as a AbstractString e.g `"/home/mpastell/weaveout"`
* `args`: dictionary of arguments to pass to document. Available as WEAVE_ARGS.
* `mod`: Module where Weave `eval`s code. Defaults to `:sandbox`
to create new sandbox module, you can also pass a module e.g. `Main`.
* `fig_path`: where figures will be generated, relative to out_path
* `fig_ext`: Extension for saved figures e.g. `".pdf"`, `".png"`. Default setting depends on `doctype`.
* `cache_path`: where of cached output will be saved.
* `cache`: controls caching of code: `:off` = no caching, `:all` = cache everything,
`:user` = cache based on chunk options, `:refresh`, run all code chunks and save new cache.
function run_doc(
doc::WeaveDoc;
doctype::Union{Nothing,AbstractString} = nothing,
out_path::Union{Symbol,AbstractString} = :doc,
args::Any = Dict(),
mod::Union{Module,Nothing} = nothing,
fig_path::Union{Nothing,AbstractString} = nothing,
fig_ext::Union{Nothing,AbstractString} = nothing,
cache_path::AbstractString = "cache",
cache::Symbol = :off,
)
# cache :all, :user, :off, :refresh
**Note:** Run command from terminal and not using IJulia, Juno or ESS, they tend to mess with capturing output.
"""
function Base.run(doc::WeaveDoc; doctype = :auto,
mod::Union{Module, Symbol} = :sandbox, out_path=:doc,
args=Dict(), fig_path = "figures", fig_ext = nothing,
cache_path = "cache", cache = :off, throw_errors=false)
#cache :all, :user, :off, :refresh
doc.doctype = isnothing(doctype) ? (doctype = detect_doctype(doc.source)) : doctype
doc.format = deepcopy(get_format(doctype))
doc.cwd = get_cwd(doc, out_path)
doctype == :auto && (doctype = detect_doctype(doc.source))
doc.doctype = doctype
doc.format = formats[doctype]
isdir(doc.cwd) || mkpath(doc.cwd)
cwd = doc.cwd = get_cwd(doc, out_path)
mkpath(cwd)
if occursin("2pdf", doctype) && cache == :off
fig_path = mktempdir(abspath(doc.cwd))
elseif occursin("2html", doctype)
fig_path = mktempdir(abspath(doc.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
cache == :off || @eval import Serialization
#This is needed for latex and should work on all output formats
Sys.iswindows() && (fig_path = replace(fig_path, "\\" => "/"))
doc.fig_path = fig_path
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)
#New sandbox for each document with args exposed
if mod == :sandbox
sandbox = "WeaveSandBox$(rcParams[:doc_number])"
mod = Core.eval(Main, Meta.parse("module $sandbox\nend"))
end
@eval mod WEAVE_ARGS = Dict()
merge!(mod.WEAVE_ARGS, args)
cache === :off || @eval import Serialization # XXX: evaluate in a more sensible module
rcParams[:doc_number] += 1
# New sandbox for each document with args exposed
isnothing(mod) && (mod = sandbox = Core.eval(Main, :(module $(gensym(:WeaveSandBox)) end))::Module)
Core.eval(mod, :(WEAVE_ARGS = $(args)))
if haskey(doc.format.formatdict, :mimetypes)
mimetypes = doc.format.formatdict[:mimetypes]
else
mimetypes = default_mime_types
end
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)
if cache != :off && cache != :refresh
cached = read_cache(doc, cache_path)
cached == nothing && @info("No cached results found, running code")
else
cached = nothing
end
executed = Any[]
n = length(doc.chunks)
for i = 1:n
chunk = doc.chunks[i]
if isa(chunk, CodeChunk)
options = merge(doc.chunk_defaults, chunk.options)
merge!(chunk.options, options)
end
restore = (cache ==:user && typeof(chunk) == CodeChunk && chunk.options[:cache])
if cached != nothing && (cache == :all || restore)
result_chunks = restore_chunk(chunk, cached)
try
if cache !== :off && cache !== :refresh
cached = read_cache(doc, cache_path)
isnothing(cached) && @info "No cached results found, running code"
else
result_chunks = run_chunk(chunk, doc, report, mod)
cached = nothing
end
executed = [executed; result_chunks]
end
executed = []
n = length(filter(chunk->isa(chunk,CodeChunk), doc.chunks))
i = 0
for chunk in doc.chunks
if chunk isa CodeChunk
options = merge(doc.chunk_defaults, chunk.options)
merge!(chunk.options, options)
doc.header_script = report.header_script
@info "Weaving chunk $(chunk.number) from line $(chunk.start_line)" progress=(i)/n _id=PROGRESS_ID
i+=1
end
popdisplay(report)
restore = (cache === :user && chunk isa CodeChunk && chunk.options[:cache])
result_chunks = if cached nothing && (cache === :all || restore)
restore_chunk(chunk, cached)
else
run_chunk(chunk, doc, report, mod)
end
executed = [executed; result_chunks]
end
#Clear variables from used sandbox
mod == :sandbox && clear_sandbox(SandBox)
doc.chunks = executed
replace_header_inline!(doc, report, mod) # evaluate and replace inline code in header
if cache != :off
write_cache(doc, cache_path)
doc.header_script = report.header_script
doc.chunks = executed
cache !== :off && write_cache(doc, cache_path)
@isdefined(sandbox) && clear_module!(sandbox)
catch err
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
end
"""Detect the output format based on file extension"""
function detect_doctype(source::AbstractString)
ext = lowercase(splitext(source)[2])
ext == ".jl" && return "md2html"
occursin("md", ext) && return "md2html"
occursin("rst", ext) && return "rst"
occursin("tex", ext) && return "texminted"
occursin("txt", ext) && return "asciidoc"
run_doc(doc::WeaveDoc, doctype::Union{Nothing,AbstractString}; kwargs...) =
run_doc(doc; doctype = doctype, kwargs...)
return "pandoc"
"""
detect_doctype(path)
Detect the output format based on file extension.
"""
function detect_doctype(path)
_, ext = lowercase.(splitext(path))
match(r"^\.(jl|.?md|ipynb)", ext) !== nothing && return "md2html"
ext == ".rst" && return "rst"
ext == ".tex" && return "texminted"
ext == ".txt" && return "asciidoc"
return "pandoc"
end
function run_chunk(chunk::CodeChunk, doc::WeaveDoc, report::Report, SandBox::Module)
@info("Weaving chunk $(chunk.number) from line $(chunk.start_line)")
result_chunks = eval_chunk(chunk, report, SandBox)
occursin("2html", report.formatdict[:doctype]) && (result_chunks = embed_figures(result_chunks, report.cwd))
return result_chunks
end
function embed_figures(chunk::CodeChunk, cwd)
chunk.figures = [img2base64(fig, cwd) for fig in chunk.figures]
return chunk
end
function embed_figures(result_chunks, cwd)
for i in 1:length(result_chunks)
figs = result_chunks[i].figures
if !isempty(figs)
result_chunks[i].figures = [img2base64(fig, cwd) for fig in figs]
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
return result_chunks
end |> abspath
end
function run_chunk(chunk::CodeChunk, doc, report, mod)
result = eval_chunk(doc, chunk, report, mod)
occursin("2html", doc.doctype) && (embed_figures!(result, report.cwd))
return result
end
function embed_figures!(chunk::CodeChunk, cwd)
for (i, fig) in enumerate(chunk.figures)
chunk.figures[i] = img2base64(fig, 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")
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
close(f)
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::WeaveDoc, report::Report, SandBox::Module)
chunk.content = [run_inline(c, doc, report, SandBox) for c in chunk.content]
function run_chunk(chunk::DocChunk, doc, report, mod)
chunk.content = [run_inline(c, doc, report, mod) for c in chunk.content]
return chunk
end
function run_inline(inline::InlineText, doc::WeaveDoc, report::Report, SandBox::Module)
return inline
end
run_inline(inline::InlineText, ::WeaveDoc, ::Report, ::Module) = inline
function run_inline(inline::InlineCode, doc::WeaveDoc, report::Report, SandBox::Module)
#Make a temporary CodeChunk for running code. Collect results and don't wrap
chunk = CodeChunk(inline.content, 0, 0, "", Dict(:hold => true, :wrap => false))
const INLINE_OPTIONS = Dict(
:term => false,
:hold => true,
:wrap => false
)
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]) && (chunks = 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])
@ -189,262 +185,267 @@ 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) = 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
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 results
return res
end
getstdout() = stdout
function capture_output(code, mod, path, error, report)
reset_report!(report)
function capture_output(expr, SandBox::Module, term, disp,
lastline, throw_errors=false)
#oldSTDOUT = STDOUT
oldSTDOUT = getstdout()
out = nothing
obj = nothing
old = stdout
rw, wr = redirect_stdout()
reader = @async read(rw, String)
try
obj = Core.eval(SandBox, expr)
if (term || disp) && typeof(expr) == Expr && expr.head != :toplevel
obj != nothing && display(obj)
elseif typeof(expr) == Symbol
display(obj)
#This shows images and lone variables, result can
#Handle last line sepately
elseif lastline && obj != nothing
(expr.head != :toplevel) && display(obj)
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
catch E
throw_errors && throw(E)
display(E)
@warn("ERROR: $(typeof(E)) occurred, including output in Weaved document")
finally
redirect_stdout(oldSTDOUT)
close(wr)
out = fetch(reader)
close(rw)
end
out = replace(out, r"\u001b\[.*?m" => "") #Remove ANSI color codes
return (obj, out)
return ChunkOutput(code, remove_ansi_control_chars(out), report.rich_output, report.figures)
end
#Parse chunk input to array of expressions
function parse_input(input::AbstractString)
parsed = Tuple{AbstractString, Any}[]
input = lstrip(input)
n = length(input)
pos = 1 #The first character is extra line end
while pos n
oldpos = pos
code, pos = Meta.parse(input, pos)
push!(parsed, (input[oldpos:pos-1] , code ))
end
parsed
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
function eval_chunk(chunk::CodeChunk, report::Report, SandBox::Module)
# 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 = Compat.invokelatest(hook, chunk)
end
execute_prehooks!(chunk)
report.fignum = 1
report.cur_chunk = chunk
if haskey(report.formatdict, :out_width) && chunk.options[:out_width] == nothing
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)
execute_posthooks!(chunk)
#Run post_execute chunks
for hook in postexecute_hooks
chunk = Compat.invokelatest(hook, chunk)
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())
end
#else
# chunk.options[:fig] && (chunk.figures = copy(report.figures))
#end
chunks
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
#function eval_chunk(chunk::DocChunk, report::Report, SandBox)
# chunk
#end
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
end
#Set all variables to nothing
function clear_sandbox(SandBox::Module)
for name = names(SandBox, all=true)
if name != :eval && name != names(SandBox)[1]
try eval(SandBox, Meta.parse(AbstractString(AbstractString(name), "=nothing"))) catch; end
"""
clear_module!(mod::Module)
Recursively sets variables in `mod` to `nothing` so that they're GCed.
!!! warning
`const` variables can't be reassigned, as such they can't be cleared.
"""
function clear_module!(mod::Module)
for name in names(mod; all = true)
name === :eval && continue
try
v = getfield(mod, name)
if v isa Module && v != mod
clear_module!(v)
continue
end
isconst(mod, name) && continue # can't clear constant
Core.eval(mod, :($name = nothing))
catch err
@debug err
end
end
end
function get_figname(report::Report, chunk; fignum = nothing, ext = nothing)
figpath = joinpath(report.cwd, chunk.options[:fig_path])
isdir(figpath) || mkpath(figpath)
ext == nothing && (ext = chunk.options[:fig_ext])
fignum == nothing && (fignum = report.fignum)
isnothing(ext) && (ext = chunk.options[:fig_ext])
isnothing(fignum) && (fignum = report.fignum)
chunkid = (chunk.options[:label] == nothing) ? 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
chunkid = isnothing(chunk.options[:label]) ? chunk.number : chunk.options[:label]
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)
ext == nothing && (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)
ext == nothing && (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 fig_ext == nothing
doc.chunk_defaults[:fig_ext] = formatdict[:fig_ext]
else
doc.chunk_defaults[:fig_ext] = fig_ext
end
doc.chunk_defaults[:fig_path] = fig_path
return nothing
doc.chunk_defaults[:fig_ext] = isnothing(fig_ext) ? doc.format.fig_ext : fig_ext
doc.chunk_defaults[:fig_path] = fig_path
end
function collect_results(chunk::CodeChunk, fmt::ScriptResult)
function collect_results(chunk::CodeChunk)
content = ""
result_no = 1
result_chunks = CodeChunk[ ]
for r = chunk.result
#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
rchunk = CodeChunk(content, chunk.number, chunk.start_line, chunk.optionstring, copy(chunk.options))
content = ""
rchunk.result_no = result_no
result_no *=1
rchunk.figures = r.figures
rchunk.output = r.stdout * r.displayed
result_chunks = CodeChunk[]
for r in chunk.result
content *= r.code
# Check if there is any output from chunk
if any(!isempty strip, (r.stdout, r.rich_output)) || !isempty(r.figures)
rchunk = CodeChunk(
content,
chunk.number,
chunk.start_line,
chunk.optionstring,
copy(chunk.options),
)
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)
rchunk = CodeChunk(content, chunk.number, chunk.start_line, chunk.optionstring, copy(chunk.options))
if !isempty(content)
rchunk = CodeChunk(
content,
chunk.number,
chunk.start_line,
chunk.optionstring,
copy(chunk.options),
)
push!(result_chunks, rchunk)
end
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 = chunk.result
output *= prompt * r.code
output *= r.displayed * r.stdout
result_chunks = CodeChunk[]
for r in chunk.result
output *= string('\n', indent_term_code(prompt, r.code), '\n', r.stdout)
if !isempty(r.figures)
rchunk = CodeChunk("", chunk.number, chunk.start_line, chunk.optionstring, copy(chunk.options))
rchunk = CodeChunk(
"",
chunk.number,
chunk.start_line,
chunk.optionstring,
copy(chunk.options),
)
rchunk.output = output
output = ""
rchunk.figures = r.figures
push!(result_chunks, rchunk)
end
end
if output != ""
rchunk = CodeChunk("", chunk.number, chunk.start_line, chunk.optionstring, copy(chunk.options))
rchunk.output = output
if !isempty(output)
rchunk = CodeChunk(
"",
chunk.number,
chunk.start_line,
chunk.optionstring,
copy(chunk.options),
)
rchunk.output = output
push!(result_chunks, rchunk)
end
return result_chunks
end
function collect_results(chunk::CodeChunk, fmt::CollectResult)
result_no = 1
for r =chunk.result
chunk.output *= r.stdout
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
chunk.figures = [chunk.figures; r.figures]
end
return [chunk]
end
const HEADER_INLINE = Regex("$(HEADER_INLINE_START)(?<code>.+)$(HEADER_INLINE_END)")
replace_header_inline!(doc, report, mod) = _replace_header_inline!(doc, doc.header, report, mod)
function _replace_header_inline!(doc, header, report, mod)
replace!(header) do (k,v)
return k =>
v isa Dict ? _replace_header_inline!(doc, v, report, mod) :
!isa(v, AbstractString) ? v :
replace(v, HEADER_INLINE => s -> begin
code = replace(s, HEADER_INLINE => s"\g<code>")
run_inline_code(code, doc, report, mod)
end)
end
return header
end
function run_inline_code(code, doc, report, mod)
inline = InlineCode(code, 1, :inline)
inline = run_inline(inline, doc, report, mod)
return strip(inline.output, '"')
end

72
src/types.jl Normal file
View File

@ -0,0 +1,72 @@
# TODO: concreate typing
abstract type WeaveChunk end
abstract type Inline end
abstract type WeaveFormat end
mutable struct WeaveDoc
source::AbstractString
basename::AbstractString
path::AbstractString
chunks::Vector{WeaveChunk}
cwd::AbstractString
format::Any
doctype::String
header_script::String
header::Dict
chunk_defaults::Dict{Symbol,Any}
end
struct ChunkOutput
code::String
stdout::String
rich_output::String
figures::Vector{String}
end
mutable struct CodeChunk <: WeaveChunk
content::String
number::Int
start_line::Int
optionstring::String
options::Dict{Symbol,Any}
output::AbstractString
rich_output::AbstractString
figures::Vector{String}
result::Vector{ChunkOutput}
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}
number::Int
start_line::Int
end
struct InlineText <: Inline
content::String
number::Int
end
mutable struct InlineCode <: Inline
content::String
number::Int
ctype::Symbol
output::String
rich_output::String
figures::Vector{String}
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

@ -1,179 +0,0 @@
import JSON
import Mustache
mutable struct NotebookOutput
end
mutable struct MarkdownOutput
end
mutable struct NowebOutput
end
mutable struct ScriptOutput
end
const output_formats = Dict{String, Any}(
"noweb" => NowebOutput(),
"notebook" => NotebookOutput(),
"markdown" => MarkdownOutput(),
"script" => ScriptOutput()
)
"""Autodetect format for converter"""
function detect_outformat(outfile::String)
ext = lowercase(splitext(outfile)[2])
ext == ".jl" && return "script"
ext == ".jmd" && return "markdown"
ext == ".ipynb" && return "notebook"
return "noweb"
end
"""
`convert_doc(infile::AbstractString, outfile::AbstractString; format = nothing)`
Convert Weave documents between different formats
* `infile` = Name of the input document
* `outfile` = Name of the output document
* `format` = Output format (optional). Detected from outfile extension, but can
be set to `"script"`, `"markdown"`, `"notebook"` or `"noweb"`.
"""
function convert_doc(infile::AbstractString, outfile::AbstractString; format = nothing)
doc = read_doc(infile)
if format == nothing
format = detect_outformat(outfile)
end
converted = convert_doc(doc, output_formats[format])
open(outfile, "w") do f
write(f, converted)
end
return nothing
end
"""Convert Weave document to Jupyter notebook format"""
function convert_doc(doc::WeaveDoc, format::NotebookOutput)
nb = Dict()
nb["nbformat"] = 4
nb["nbformat_minor"] = 2
metadata = Dict()
kernelspec = Dict()
kernelspec["language"] = "julia"
kernelspec["name"] = "julia-$(VERSION.major).$(VERSION.minor)"
kernelspec["display_name"] = "Julia $(VERSION.major).$(VERSION.minor).$(VERSION.patch)"
metadata["kernelspec"] = kernelspec
language_info = Dict()
language_info["file_extension"] = ".jl"
language_info["mimetype"] = "application/julia"
language_info["name"]= "julia"
language_info["version"] = "$(VERSION.major).$(VERSION.minor).$(VERSION.patch)"
metadata["language_info"] = language_info
cells = []
ex_count = 1
# Handle header
head_tpl = """
{{#:title}}# {{:title}}{{/:title}}
{{#:author}}### {{{:author}}}{{/:author}}
{{#:date}}### {{{:date}}}{{/:date}}
"""
if isa(doc.chunks[1], DocChunk)
doc.chunks[1] = strip_header(doc.chunks[1])
doc.chunks[1].content[1].content = Mustache.render(head_tpl;
[Pair(Symbol(k), v) for (k,v) in doc.header]...) * doc.chunks[1].content[1].content
end
for chunk in doc.chunks
if isa(chunk, DocChunk)
push!(cells,
Dict("cell_type" => "markdown",
"metadata" => Dict(),
"source" => [strip(join([repr(c) for c in chunk.content], ""))])
)
elseif haskey(chunk.options, :skip) && chunk.options[:skip] == "notebook"
continue
else
push!(cells,
Dict("cell_type" => "code",
"metadata" => Dict(),
"source" => [strip(chunk.content)],
"execution_count" => nothing,
"outputs" => []
))
end
end
nb["cells"] = cells
nb["metadata"] = metadata
json_nb = JSON.json(nb, 2)
return json_nb
end
"""Convert Weave document to Jupyter notebook format"""
function convert_doc(doc::WeaveDoc, format::MarkdownOutput)
output = ""
for chunk in doc.chunks
if isa(chunk, DocChunk)
output *= join([repr(c) for c in chunk.content], "")
else
output *= "\n" * "```julia"
isempty(chunk.optionstring) || (output *= ";" * chunk.optionstring)
output *= "\n" * lstrip(chunk.content)
output *= "```\n"
end
end
return output
end
"""Convert Weave document to noweb format"""
function convert_doc(doc::WeaveDoc, format::NowebOutput)
output = ""
for chunk in doc.chunks
if isa(chunk, DocChunk)
output *= join([repr(c) for c in chunk.content], "")
else
output *= "\n" * "<<"
isempty(chunk.optionstring) || (output *= strip(chunk.optionstring))
output *= ">>="
output *= "\n" * lstrip(chunk.content)
output *= "@\n"
end
end
return output
end
"""Convert Weave document to script format"""
function convert_doc(doc::WeaveDoc, format::ScriptOutput)
output = ""
for chunk in doc.chunks
if typeof(chunk) == Weave.DocChunk
content = join([repr(c) for c in chunk.content], "")
output *= join(["#' " * s for s in split(content, "\n")], "\n")
else
output *= "\n#+ "
isempty(chunk.optionstring) || (output *= strip(chunk.optionstring))
output *= "\n\n" * lstrip(chunk.content)
output *= "\n"
end
end
return output
end
function Base.repr(c::InlineText)
return c.content
end
function Base.repr(c::InlineCode)
return "`j $(c.content)`"
end

View File

@ -523,7 +523,7 @@ kbd,
pre,
samp {
font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
font-size: 13px;
font-size: 0.9em;
}

View File

@ -1,54 +0,0 @@
<!DOCTYPE html>
<HTML lang = "en">
<HEAD>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
{{#:title}}<title>{{:title}}</title>{{/:title}}
{{{ :header_script }}}
<script type="text/x-mathjax-config">
MathJax.Hub.Config({
tex2jax: {inlineMath: [['$','$'], ['\\(','\\)']]},
TeX: { equationNumbers: { autoNumber: "AMS" } }
});
</script>
<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 }}}
<style type="text/css">
{{{ :themecss }}}
</style>
</HEAD>
<BODY>
<div class ="container">
<div class = "row">
<div class = "col-md-12 twelve columns">
<div class="title">
{{#:title}}<h1 class="title">{{:title}}</h1>{{/:title}}
{{#:author}}<h5>{{{:author}}}</h5>{{/:author}}
{{#:date}}<h5>{{{:date}}}</h5>{{/:date}}
</div>
{{{ :body }}}
<HR/>
<div class="footer"><p>
Published from <a href="{{{:source}}}">{{{:source}}}</a> using
<a href="http://github.com/mpastell/Weave.jl">Weave.jl</a>
{{:wversion}} on {{:wtime}}.
<p></div>
</div>
</div>
</div>
</BODY>
</HTML>

50
templates/md2html.tpl Normal file
View File

@ -0,0 +1,50 @@
<!DOCTYPE html>
<HTML lang = "en">
<HEAD>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
{{#:title}}<title>{{:title}}</title>{{/:title}}
{{{ :header_script }}}
<script type="text/x-mathjax-config">
MathJax.Hub.Config({
tex2jax: {inlineMath: [['$','$'], ['\\(','\\)']]},
TeX: { equationNumbers: { autoNumber: "AMS" } }
});
</script>
<script type="text/javascript" async src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML">
</script>
{{{ :highlight_stylesheet }}}
<style type="text/css">
{{{ :stylesheet }}}
</style>
</HEAD>
<BODY>
<div class ="container">
<div class = "row">
<div class = "col-md-12 twelve columns">
<div class="title">
{{#:title}}<h1 class="title">{{:title}}</h1>{{/:title}}
{{#:author}}<h5>{{{:author}}}</h5>{{/:author}}
{{#:date}}<h5>{{{:date}}}</h5>{{/:date}}
</div>
{{{ :body }}}
<HR/>
<div class="footer">
<p>
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>
</div>
</div>
</BODY>
</HTML>

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 $wtime$.
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,18 +0,0 @@
using Weave
using Test
cleanup = true
VER = "$(VERSION.major).$(VERSION.minor)"
weave("documents/chunk_options.noweb")
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,18 +0,0 @@
using Weave
using Test
cleanup = true
#Test hold and term options
weave("documents/test_hold.mdw", doctype="pandoc", plotlib="Gadfly")
result = read("documents/test_hold.md", String)
ref = read("documents/test_hold_ref.md", String)
@test result == ref
cleanup && rm("documents/test_hold.md")
#Test setting and restoring chunk options
Weave.weave("documents/default_opts.noweb", doctype = "tex")
result = read("documents/default_opts.tex", String)
ref = read("documents/default_opts_ref.tex", String)
@test result == ref
cleanup && rm("documents/default_opts.tex")

View File

@ -1,80 +0,0 @@
#' % FIR filter design with Julia
#' % Matti Pastell
#' % 21th April 2016
#' # Introduction
#' This an example of a julia script that can be published using
#' [Weave](http://mpastell.github.io/Weave.jl/latest/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
#' is executed and results are included in the published document.
#' Notice that you don't need to define chunk options, but you can using
#' `#+`. just before code e.g. `#+ term=True, caption='Fancy plots.'`.
#' If you're viewing the published version have a look at the
#' [source](FIR_design.jl) to see the markup.
#' # FIR Filter Design
#' We'll implement lowpass, highpass and ' bandpass FIR filters. If
#' you want to read more about DSP I highly recommend [The Scientist
#' and Engineer's Guide to Digital Signal
#' Processing](http://www.dspguide.com/) which is freely available
#' online.
#' ## Calculating frequency response
#' DSP.jl package doesn't (yet) have a method to calculate the
#' the frequency response of a FIR filter so we define it:
using Gadfly, DSP
function FIRfreqz(b::Array, w = range(0, stop=π, length=1024))
n = length(w)
h = Array{ComplexF32}(n)
sw = 0
for i = 1:n
for j = 1:length(b)
sw += b[j]*exp(-im*w[i])^-j
end
h[i] = sw
sw = 0
end
return h
end
#' ## Design Lowpass FIR filter
#' Designing a lowpass FIR filter is very simple to do with DSP.jl, all you
#' need to do is to define the window length, cut off frequency and the
#' window. We will define a lowpass filter with cut off frequency at 5Hz for a signal
#' sampled at 20 Hz.
#' We will use the Hamming window, which is defined as:
#' $w(n) = \alpha - \beta\cos\frac{2\pi n}{N-1}$, where $\alpha=0.54$ and $\beta=0.46$
fs = 20
f = digitalfilter(Lowpass(5, fs = fs), FIRWindow(hamming(61)))
w = range(0, stop=pi, length=1024)
h = FIRfreqz(f, w)
#' ## Plot the frequency and impulse response
h_db = log10(abs(h))
ws = w/pi*(fs/2)
#' The next code chunk is executed in term mode, see the [script](FIR_design.jl) for syntax.
#+ term=true
plot(y = h_db, x = ws, Geom.line,
Guide.xlabel("Frequency (Hz)"), Guide.ylabel("Magnitude (db)"))
#' And again with default options
h_phase = unwrap(-atan(imag(h),real(h)))
plot(y = h_phase, x = ws, Geom.line,
Guide.xlabel("Frequency (Hz)"), Guide.ylabel("Phase (radians)"))

View File

@ -1,112 +0,0 @@
% FIR filter design with Julia
% Matti Pastell
% 21th April 2016
# Introduction
This an example of a julia script that can be published using
[Weave](http://mpastell.github.io/Weave.jl/latest/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
is executed and results are included in the published document.
Notice that you don't need to define chunk options, but you can using
`#+`. just before code e.g. `#+ term=True, caption='Fancy plots.'`.
If you're viewing the published version have a look at the
[source](FIR_design.jl) to see the markup.
# FIR Filter Design
We'll implement lowpass, highpass and ' bandpass FIR filters. If
you want to read more about DSP I highly recommend [The Scientist
and Engineer's Guide to Digital Signal
Processing](http://www.dspguide.com/) which is freely available
online.
## Calculating frequency response
DSP.jl package doesn't (yet) have a method to calculate the
the frequency response of a FIR filter so we define it:
~~~~{.julia}
using Gadfly, DSP
function FIRfreqz(b::Array, w = linspace(0, π, 1024))
n = length(w)
h = Array{Complex64}(n)
sw = 0
for i = 1:n
for j = 1:length(b)
sw += b[j]*exp(-im*w[i])^-j
end
h[i] = sw
sw = 0
end
return h
end
~~~~~~~~~~~~~
## Design Lowpass FIR filter
Designing a lowpass FIR filter is very simple to do with DSP.jl, all you
need to do is to define the window length, cut off frequency and the
window. We will define a lowpass filter with cut off frequency at 5Hz for a signal
sampled at 20 Hz.
We will use the Hamming window, which is defined as:
$w(n) = \alpha - \beta\cos\frac{2\pi n}{N-1}$, where $\alpha=0.54$ and $\beta=0.46$
~~~~{.julia}
fs = 20
f = digitalfilter(Lowpass(5, fs = fs), FIRWindow(hamming(61)))
w = linspace(0, pi, 1024)
h = FIRfreqz(f, w)
~~~~~~~~~~~~~
## Plot the frequency and impulse response
~~~~{.julia}
h_db = log10(abs(h))
ws = w/pi*(fs/2)
~~~~~~~~~~~~~
The next code chunk is executed in term mode, see the [script](FIR_design.jl) for syntax.
~~~~{.julia}
julia> plot(y = h_db, x = ws, Geom.line,
Guide.xlabel("Frequency (Hz)"), Guide.ylabel("Magnitude (db)"))
Plot(...)
~~~~~~~~~~~~~
![](figures/FIR_design_4_1.png)\
And again with default options
~~~~{.julia}
h_phase = unwrap(-atan2(imag(h),real(h)))
plot(y = h_phase, x = ws, Geom.line,
Guide.xlabel("Frequency (Hz)"), Guide.ylabel("Phase (radians)"))
~~~~~~~~~~~~~
![](figures/FIR_design_5_1.png)\

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,30 +0,0 @@
<<>>=
using Gadfly
print(1:10)
plot(x = 1:10)
@
<<>>=
import Weave
Weave.set_chunk_defaults(Dict{Symbol, Any}(
:out_width => "\\0.5linewidth",
:results => "tex"
))
@
<<>>=
print(1:10)
plot(x = 1:10)
@
<<echo = false>>=
Weave.restore_chunk_defaults()
@
<<>>=
print(1:10)
plot(x = 1:10)
@

View File

@ -1,43 +0,0 @@
\begin{juliacode}
using Gadfly
print(1:10)
\end{juliacode}
\begin{juliaout}
1:10
\end{juliaout}
\begin{juliacode}
plot(x = 1:10)
\end{juliacode}
\includegraphics[width=\linewidth]{figures/default_opts_1_1.pdf}
\begin{juliacode}
import Weave
Weave.set_chunk_defaults(Dict{Symbol, Any}(
:out_width => "\\0.5linewidth",
:results => "tex"
))
\end{juliacode}
\begin{juliacode}
print(1:10)
\end{juliacode}
1:10
\begin{juliacode}
plot(x = 1:10)
\end{juliacode}
\includegraphics[width=\0.5linewidth]{figures/default_opts_3_1.pdf}
\begin{juliacode}
print(1:10)
\end{juliacode}
\begin{juliaout}
1:10
\end{juliaout}
\begin{juliacode}
plot(x = 1:10)
\end{juliacode}
\includegraphics[width=\linewidth]{figures/default_opts_5_1.pdf}

View File

@ -1,29 +0,0 @@
<<fig_cap="sin(x) function."; label="sin_fun"; fig_pos="ht">>=
using Gadfly
x = linspace(0, 2π, 200)
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)
@
<<echo=false; label="cos2_fun">>=
plot(x=x, y = cos(2x), Geom.line)
@
<<term=true;fig_width=5>>=
x = linspace(0, 2π, 200)
plot(x=x, y = sin(x), Geom.line)
y = 20
plot(x=x, y = cos(x), Geom.line)
@
<<out_width="15cm">>=
x = linspace(0, 2π, 200)
plot(x=x, y = sin(x), Geom.line)
y = 20
plot(x=x, y = cos(x), Geom.line)
@

View File

@ -1,53 +0,0 @@
````julia
using Gadfly
x = range(0, stop=2π, length=200)
plot(x=x, y = sin(x), Geom.line)
````
![sin(x) function.](figures/gadfly_formats_test_sin_fun_1.js.svg)
![cos(x) function.](figures/gadfly_formats_test_2_1.js.svg)
![](figures/gadfly_formats_test_cos2_fun_1.js.svg)
````julia
julia> x = range(0, stop=2π, length=200)
200-element LinSpace{Float64}:
0.0,0.0315738,0.0631476,0.0947214,0.126295,…,6.18846,6.22004,6.25161,6.28319
julia> plot(x=x, y = sin(x), Geom.line)
Plot(...)
````
![](figures/gadfly_formats_test_4_1.js.svg)
````julia
julia> y = 20
20
julia> plot(x=x, y = cos(x), Geom.line)
Plot(...)
````
![](figures/gadfly_formats_test_4_2.js.svg)
````julia
x = range(0, stop=2π, length=200)
plot(x=x, y = sin(x), Geom.line)
````
![](figures/gadfly_formats_test_5_1.js.svg)
````julia
y = 20
plot(x=x, y = cos(x), Geom.line)
````
![](figures/gadfly_formats_test_5_2.js.svg)

View File

@ -1,67 +0,0 @@
````julia
using Gadfly
x = range(0, stop=2π, length=200)
plot(x=x, y = sin(x), Geom.line)
````
![sin(x) function.][figures/gadfly_formats_test_sin_fun_1.png]
[figures/gadfly_formats_test_sin_fun_1.png]: figures/gadfly_formats_test_sin_fun_1.png
![cos(x) function.][figures/gadfly_formats_test_2_1.png]
[figures/gadfly_formats_test_2_1.png]: figures/gadfly_formats_test_2_1.png
![][figures/gadfly_formats_test_cos2_fun_1.png]
[figures/gadfly_formats_test_cos2_fun_1.png]: figures/gadfly_formats_test_cos2_fun_1.png
````julia
julia> x = range(0, stop=2π, length=200)
200-element LinSpace{Float64}:
0.0,0.0315738,0.0631476,0.0947214,0.126295,…,6.18846,6.22004,6.25161,6.28319
julia> plot(x=x, y = sin(x), Geom.line)
Plot(...)
````
![][figures/gadfly_formats_test_4_1.png]
[figures/gadfly_formats_test_4_1.png]: figures/gadfly_formats_test_4_1.png
````julia
julia> y = 20
20
julia> plot(x=x, y = cos(x), Geom.line)
Plot(...)
````
![][figures/gadfly_formats_test_4_2.png]
[figures/gadfly_formats_test_4_2.png]: figures/gadfly_formats_test_4_2.png
````julia
x = range(0, stop=2π, length=200)
plot(x=x, y = sin(x), Geom.line)
````
![][figures/gadfly_formats_test_5_1.png]
[figures/gadfly_formats_test_5_1.png]: figures/gadfly_formats_test_5_1.png width=15cm
````julia
y = 20
plot(x=x, y = cos(x), Geom.line)
````
![][figures/gadfly_formats_test_5_2.png]
[figures/gadfly_formats_test_5_2.png]: figures/gadfly_formats_test_5_2.png width=15cm

View File

@ -1,58 +0,0 @@
~~~~{.julia}
using Gadfly
x = linspace(0, 2π, 200)
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)
![](figures/gadfly_formats_test_cos2_fun_1.png)\
~~~~{.julia}
julia> x = linspace(0, 2π, 200)
200-element LinSpace{Float64}:
0.0,0.0315738,0.0631476,0.0947214,0.126295,…,6.18846,6.22004,6.25161,6.28319
julia> plot(x=x, y = sin(x), Geom.line)
Plot(...)
~~~~~~~~~~~~~
![](figures/gadfly_formats_test_4_1.png)\
~~~~{.julia}
julia> y = 20
20
julia> plot(x=x, y = cos(x), Geom.line)
Plot(...)
~~~~~~~~~~~~~
![](figures/gadfly_formats_test_4_2.png)\
~~~~{.julia}
x = linspace(0, 2π, 200)
plot(x=x, y = sin(x), Geom.line)
~~~~~~~~~~~~~
![](figures/gadfly_formats_test_5_1.png){width=15cm}\
~~~~{.julia}
y = 20
plot(x=x, y = cos(x), Geom.line)
~~~~~~~~~~~~~
![](figures/gadfly_formats_test_5_2.png){width=15cm}\

View File

@ -1,52 +0,0 @@
\begin{juliacode}
using Gadfly
x = linspace(0, 2π, 200)
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}
\includegraphics[width=\linewidth]{figures/gadfly_formats_test_cos2_fun_1.ps}
\begin{juliaterm}
julia> x = linspace(0, 2π, 200)
200-element LinSpace{Float64}:
0.0,0.0315738,0.0631476,0.0947214,0.126295,…,6.18846,6.22004,6.25161,6.28319
julia> plot(x=x, y = sin(x), Geom.line)
Plot(...)
\end{juliaterm}
\includegraphics[width=\linewidth]{figures/gadfly_formats_test_4_1.ps}
\begin{juliaterm}
julia> y = 20
20
julia> plot(x=x, y = cos(x), Geom.line)
Plot(...)
\end{juliaterm}
\includegraphics[width=\linewidth]{figures/gadfly_formats_test_4_2.ps}
\begin{juliacode}
x = linspace(0, 2π, 200)
plot(x=x, y = sin(x), Geom.line)
\end{juliacode}
\includegraphics[width=15cm]{figures/gadfly_formats_test_5_1.ps}
\begin{juliacode}
y = 20
plot(x=x, y = cos(x), Geom.line)
\end{juliacode}
\includegraphics[width=15cm]{figures/gadfly_formats_test_5_2.ps}

View File

@ -1,76 +0,0 @@
.. code-block:: julia
using Gadfly
x = linspace(0, 2π, 200)
plot(x=x, y = sin(x), Geom.line)
.. figure:: figures/gadfly_formats_test_sin_fun_1.png
:width: 15 cm
sin(x) function.
.. figure:: figures/gadfly_formats_test_2_1.png
:width: 15 cm
cos(x) function.
.. image:: figures/gadfly_formats_test_cos2_fun_1.png
:width: 15 cm
.. code-block:: julia
julia> x = linspace(0, 2π, 200)
200-element LinSpace{Float64}:
0.0,0.0315738,0.0631476,0.0947214,0.126295,…,6.18846,6.22004,6.25161,6.28319
julia> plot(x=x, y = sin(x), Geom.line)
Plot(...)
.. image:: figures/gadfly_formats_test_4_1.png
:width: 15 cm
.. code-block:: julia
julia> y = 20
20
julia> plot(x=x, y = cos(x), Geom.line)
Plot(...)
.. image:: figures/gadfly_formats_test_4_2.png
:width: 15 cm
.. code-block:: julia
x = linspace(0, 2π, 200)
plot(x=x, y = sin(x), Geom.line)
.. image:: figures/gadfly_formats_test_5_1.png
:width: 15cm
.. code-block:: julia
y = 20
plot(x=x, y = cos(x), Geom.line)
.. image:: figures/gadfly_formats_test_5_2.png
:width: 15cm

View File

@ -1,52 +0,0 @@
\begin{juliacode}
using Gadfly
x = linspace(0, 2π, 200)
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}
\includegraphics[width=\linewidth]{figures/gadfly_formats_test_cos2_fun_1.pdf}
\begin{juliaterm}
julia> x = linspace(0, 2π, 200)
200-element LinSpace{Float64}:
0.0,0.0315738,0.0631476,0.0947214,0.126295,…,6.18846,6.22004,6.25161,6.28319
julia> plot(x=x, y = sin(x), Geom.line)
Plot(...)
\end{juliaterm}
\includegraphics[width=\linewidth]{figures/gadfly_formats_test_4_1.pdf}
\begin{juliaterm}
julia> y = 20
20
julia> plot(x=x, y = cos(x), Geom.line)
Plot(...)
\end{juliaterm}
\includegraphics[width=\linewidth]{figures/gadfly_formats_test_4_2.pdf}
\begin{juliacode}
x = linspace(0, 2π, 200)
plot(x=x, y = sin(x), Geom.line)
\end{juliacode}
\includegraphics[width=15cm]{figures/gadfly_formats_test_5_1.pdf}
\begin{juliacode}
y = 20
plot(x=x, y = cos(x), Geom.line)
\end{juliacode}
\includegraphics[width=15cm]{figures/gadfly_formats_test_5_2.pdf}

View File

@ -1,58 +0,0 @@
~~~~{.julia}
using Gadfly
x = linspace(0, 2π, 200)
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)
![](figures/gadfly_formats_test_cos2_fun_1.svg)\
~~~~{.julia}
julia> x = linspace(0, 2π, 200)
200-element LinSpace{Float64}:
0.0,0.0315738,0.0631476,0.0947214,0.126295,…,6.18846,6.22004,6.25161,6.28319
julia> plot(x=x, y = sin(x), Geom.line)
Plot(...)
~~~~~~~~~~~~~
![](figures/gadfly_formats_test_4_1.svg)\
~~~~{.julia}
julia> y = 20
20
julia> plot(x=x, y = cos(x), Geom.line)
Plot(...)
~~~~~~~~~~~~~
![](figures/gadfly_formats_test_4_2.svg)\
~~~~{.julia}
x = linspace(0, 2π, 200)
plot(x=x, y = sin(x), Geom.line)
~~~~~~~~~~~~~
![](figures/gadfly_formats_test_5_1.svg){width=15cm}\
~~~~{.julia}
y = 20
plot(x=x, y = cos(x), Geom.line)
~~~~~~~~~~~~~
![](figures/gadfly_formats_test_5_2.svg){width=15cm}\

View File

@ -1,52 +0,0 @@
\begin{juliacode}
using Gadfly
x = linspace(0, 2π, 200)
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}
\resizebox{\linewidth}{!}{\input{figures/gadfly_formats_test_cos2_fun_1.tex}}
\begin{juliaterm}
julia> x = linspace(0, 2π, 200)
200-element LinSpace{Float64}:
0.0,0.0315738,0.0631476,0.0947214,0.126295,…,6.18846,6.22004,6.25161,6.28319
julia> plot(x=x, y = sin(x), Geom.line)
Plot(...)
\end{juliaterm}
\resizebox{\linewidth}{!}{\input{figures/gadfly_formats_test_4_1.tex}}
\begin{juliaterm}
julia> y = 20
20
julia> plot(x=x, y = cos(x), Geom.line)
Plot(...)
\end{juliaterm}
\resizebox{\linewidth}{!}{\input{figures/gadfly_formats_test_4_2.tex}}
\begin{juliacode}
x = linspace(0, 2π, 200)
plot(x=x, y = sin(x), Geom.line)
\end{juliacode}
\resizebox{15cm}{!}{\input{figures/gadfly_formats_test_5_1.tex}}
\begin{juliacode}
y = 20
plot(x=x, y = cos(x), Geom.line)
\end{juliacode}
\resizebox{15cm}{!}{\input{figures/gadfly_formats_test_5_2.tex}}

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,80 +0,0 @@
# Gadfly
````julia
julia> using Gadfly
julia> x = range(0, stop=2π, length=200)
200-element LinSpace{Float64}:
0.0,0.0315738,0.0631476,0.0947214,0.126295,…,6.18846,6.22004,6.25161,6.28319
julia> plot(x=x, y = sin(x), Geom.line)
Plot(...)
````
![](figures/gadfly_markdown_test_1_1.png)
````julia
julia> y = 20
20
julia> plot(x=x, y = cos(x), Geom.line)
Plot(...)
````
![](figures/gadfly_markdown_test_1_2.png)
````julia
x = range(0, stop=200, length=50)
println(x)
````
````
linspace(0.0,200.0,50)
````
````julia
julia> using Gadfly
julia> x = range(0, stop=2π, length=200)
200-element LinSpace{Float64}:
0.0,0.0315738,0.0631476,0.0947214,0.126295,…,6.18846,6.22004,6.25161,6.28319
julia> plot(x=x, y = sin(x), Geom.line)
Plot(...)
````
![](figures/gadfly_markdown_test_3_1.png)
````julia
julia> y = 20
20
julia> plot(x=x, y = cos(x), Geom.line)
Plot(...)
````
![](figures/gadfly_markdown_test_3_2.png)
````julia
x = range(0, stop=200, length=50)
println(x)
````
````
linspace(0.0,200.0,50)
````

View File

@ -1,12 +0,0 @@
---
options:
md2html :
out_path : html
echo : false
out_width : 30%
---
```julia
repeat("🐐", 10)
```

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>

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