Compare commits

..

No commits in common. "master" and "v0.0.3" have entirely different histories.

132 changed files with 2680 additions and 8143 deletions

1
.gitattributes vendored
View File

@ -1 +0,0 @@
* text eol=lf

1
.github/FUNDING.yml vendored
View File

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

View File

@ -1,31 +0,0 @@
---
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 -->

View File

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

View File

@ -1,19 +0,0 @@
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()'

View File

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

View File

@ -1,67 +0,0 @@
# 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 }}

53
.gitignore vendored
View File

@ -1,29 +1,24 @@
Manifest.toml
examples/figures/
examples/*.md
examples/*.pdf
examples/*.html
examples/*.rst
examples/*.tex
test/**/cache
test/**/figures
test/documents/output/gadfly_formats_test.txt
test/**/*.tex
test/**/*.md
test/**/*.rst
test/**/*.html
test/**/*.pdf
test/**/*.png
test/**/chunk_options.jl
test/**/*.ipynb
!test/**/*ref.*
doc/build
doc/site
.idea
*.*~
*.aux
*.log
*.out
src/*.cov
test.jl
examples/figures/
examples/*.md
examples/*.pdf
examples/*.html
examples/*.rst
examples/*.tex
test/documents/figures
test/documents/*.tex
test/documents/*.md
test/documents/*.rst
test/documents/*.html
test/documents/*.pdf
!test/documents/*ref.*
tmp/
.idea
*.*~
*.aux
*.log
*.out

View File

@ -1,14 +1,25 @@
language: julia
jobs:
include:
- stage: "Documentation"
julia: 1.5
os: linux
script:
- julia --project=doc/ -e 'using Pkg; Pkg.develop(PackageSpec(path=pwd())); Pkg.instantiate()'
- julia --project=doc/ doc/make.jl
after_success: skip
language: cpp
compiler:
- clang
notifications:
email: false
env:
matrix:
- JULIAVERSION="juliareleases"
- JULIAVERSION="julianightlies"
before_install:
#- wget http://repo.continuum.io/miniconda/Miniconda-latest-Linux-x86_64.sh -O miniconda.sh
#- chmod +x miniconda.sh
#- ./miniconda.sh -b
#- export PATH=/home/travis/miniconda/bin:$PATH
#- conda update --yes conda
#- conda install --yes matplotlib
- sudo add-apt-repository ppa:staticfloat/julia-deps -y
- sudo add-apt-repository ppa:staticfloat/${JULIAVERSION} -y
- sudo apt-get update -qq -y
- sudo apt-get install libpcre3-dev julia python-matplotlib -y
- if [[ -a .git/shallow ]]; then git fetch --unshallow; fi
script:
- xvfb-run julia -e 'Pkg.init(); Pkg.add("PyPlot"); Pkg.add("Winston"); Pkg.add("Cairo"); Pkg.add("Gadfly"); Pkg.clone(pwd()); Pkg.test("Weave", coverage=true)'
after_success:
- julia -e 'cd(Pkg.dir("Weave")); Pkg.add("Coverage"); using Coverage; Coveralls.submit(Coveralls.process_folder())'

View File

@ -1,20 +1,22 @@
Copyright (c) 2020: Contributors
The Weave.jl package is licensed under the MIT "Expat" License:
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.
> Copyright (c) 2014: 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.

182
NEWS.md
View File

@ -1,182 +0,0 @@
## 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)
---
### v0.4.1
* 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
* Use Julia markdown for publishing to pdf and html
* Add `template`, `highlight_theme`, `latex_cmd` and `css` option to `weave` for customizing html and pdf output
* Bug fixes
* Fix plotting on Windows
* 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
* Add support for Plots.jl plotly and plotlyjs backends for including javascipt
output in published HTML documents.
* Fix semicolons for `term=true`
### v0.2
* Move to Julia 0.5 only
* New `display` and `prompt` chunk options by @gragusa
* Implemented fig_width and fig_height chunk option for Plots.jl
* Added pre and post chunk hooks, only used internally for now
* Automatic detection of plotting library, `:auto` is the new default options
* Support for displaying general multimedia objects e.g. Plots.jl and Images.jl
now work with weave.
* Support for including html, latex and markdown output from objects
* New logic for displaying output in script chunks, output is shown by default for:
- Writing to stdout
- Calling display
- Gadfly plots
- Variables on their own
- If the last line of a chunk is a function call that returns output e.g. plot(1:10)
* Bug fixes
- Fix parsing of lone variables from chunks
- Fix error with md2html formatter and dates #38
### v0.1.2
27th April 2016
* Fix a bug with `out_path` for md2html and md2pdf
* Fix md2html and md2pdf on Windows
* 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.
* Use Documenter.jl for documentation.
* Add chunk option `hold`, replaces results = "hold". This way you can use e.g. `hold = true, results=raw`.
* Methods for setting and restoring default chunk options for documents.
* New output options `md2pdf` and `md2html`, both use pandoc to output pdf
and html files directly with own templates.
* Restored and improved Winston support.
* New input format: scripts with markup in comments
* New output format: MultiMarkdown
* Added support for figure width in Pandoc
* Autodetect input and output formats based on filename
* Allow `out_path` be a file or directory.
### v0.1.0
19th April 2016
* Updated for Julia 0.4x, drop 0.3x support
* Each document is executed in separate sandbox module instead of redefining the same one. Fixes warnings and occasional segfaults.
* Change the output of chunks:
- Output will be added to the output directly where they are created (default).
- Use results = "hold" to push all output after the chunk.
* New chunk option: `line_width`.
* Winston support is not implemented yet for this version.
* Bug fix in wrapping output lines.
* Internal changes
- Chunks are now represented with their own type. Allows multiple dispatch
and easier implementation of new chunks.
### 0.0.4
4th January 2015
* Added AsciiDoc formatter
* Default plotting library changed to Gadfly
* 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
* Sandbox module for running code is cleared between documents
* Fixed Latex figure handling (with contributions from @wildart)
* Changed "tex" format: separate environment for term chunks
* Improved test coverage
* Fixed a bug with eval=false chunk option.
### 0.0.2
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

View File

@ -1,37 +0,0 @@
name = "Weave"
uuid = "44d3d7a6-8a23-5bf8-98c5-b353f8df5ec9"
version = "0.10.12"
[deps]
Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"
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"
Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7"
REPL = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb"
RelocatableFolders = "05181044-ff0b-4ac5-8273-598c1e38db00"
Requires = "ae029012-a4dd-5104-9daa-d747884805df"
Serialization = "9e88b42a-f829-5b0c-bbe9-9e923198166b"
YAML = "ddb6d928-2868-570f-bddf-ab3f9cf99eb6"
[compat]
Highlights = "0.3.1, 0.4, 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]
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 = ["DataFrames", "Test"]

182
README.md
View File

@ -1,104 +1,78 @@
# Weave
![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 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 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](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 in Juno demo](https://user-images.githubusercontent.com/40514306/76081328-32f41900-5fec-11ea-958a-375f77f642a2.png)
## Installation
You can install the latest release using Julia package manager:
```julia
using Pkg
Pkg.add("Weave")
```
## Usage
```julia
using Weave
# 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
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)](http://weavejl.mpastell.com/stable/)
[![](https://img.shields.io/badge/docs-dev-blue.svg)](http://weavejl.mpastell.com/dev/)
## Editor support
Install [language-weave](https://atom.io/packages/language-weave) to add Weave support to Juno.
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
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/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.
# Weave
[![Build Status](https://travis-ci.org/mpastell/Weave.jl.svg?branch=master)](https://travis-ci.org/mpastell/Weave.jl)[![Coverage Status](https://img.shields.io/coveralls/mpastell/Weave.jl.svg)](https://coveralls.io/r/mpastell/Weave.jl?branch=master)
Weave is a scientific report generator/literate programming tool
for Julia. It resembles [Pweave](http://mpastell.com/pweave) and, Knitr
and Sweave.
**Current features**
* Noweb or markdown syntax for input documents.
* Execute code as terminal or "script" chunks.
* Capture PyPlot, Gadfly or Winston figures.
* Supports LaTex, Pandoc and Github markdown and reStructuredText output
## Chunk options
I've tried to follow [Knitr](http://yihui.name/knitr/options)'s naming for chunk options, but not all options are implemented.
You can see [`src/config.jl`](https://github.com/mpastell/Weave.jl/blob/master/src/config.jl) for the current situation.
Options are separated using ";" and need to be valid Julia expressions. e.g.
<<term=true; fig_width=6; fig_height=4>>=
## File formats
You can get a list of supported output formats:
````julia
julia> list_out_formats()
pandoc: Pandoc markdown
rst: reStructuredText and Sphinx
texminted: Latex using minted for highlighting
github: Github markdown
tex: Latex with custom code environments
````
## Usage
Run from julia:
````julia
using Weave
weave(Pkg.dir("Weave","examples","julia_sample.mdw")
````
Using Winston for plots (Julia 0.3 only):
````julia
weave(Pkg.dir("Weave","examples","winston_sample.mdw"),
plotlib="Winston", doctype="pandoc")
````
Using Gadfly (Julia 0.3 only):
````julia
weave(Pkg.dir("Weave","examples","gadfly_sample.mdw"), plotlib="Gadfly")
````
The signature of weave functions is:
````julia
function weave(source ; doctype = "pandoc",
plotlib="PyPlot", informat="noweb", fig_path = "figures", fig_ext = nothing)
````
**Note:** Run Weave from terminal and not using IJulia, Juno or ESS, they tend to mess with capturing output.
## 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.
## Contributors
Douglas Bates has contributed a number of important fixes and comments.

24
RELEASE.md Normal file
View File

@ -0,0 +1,24 @@
# Release notes for Weave.jl
### 0.0.3
9th December 2014
* Sandbox module for running code is cleared between documents
* Fixed Latex figure handling (with contributions from @wildart)
* Changed "tex" format: separate environment for term chunks
* Improved test coverage
* Fixed a bug with eval=false chunk option.
### 0.0.2
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

2
REQUIRE Normal file
View File

@ -0,0 +1,2 @@
Compat
TextWrap

View File

@ -1,58 +0,0 @@
#!/usr/bin/env julia
using Weave
using ArgParse
ap = ArgParseSettings("Weave Julia documents using Weave.jl",
version = string(Pkg.installed("Weave")),
add_version = true)
@add_arg_table ap begin
"source"
nargs = '+'
help = "source document(s)"
required = true
"--doctype"
default = nothing
help = "output format"
"--plotlib"
arg_type = String
default = "Gadfly"
help = "output format"
"--informat"
default = nothing
help = "output format"
"--out_path"
arg_type = String
default = ":doc"
help = "output directory"
"--fig_path"
arg_type = String
default = "figures"
help = "figure output directory"
"--fig_ext"
default = nothing
help = "figure file format"
end
args = ArgParse.parse_args(ap)
source = args["source"]
delete!(args, "source")
args_col = []
#Check for special values of out_path
if args["out_path"] == ":doc"
args["out_path"] = :doc
elseif args["out_path"] == ":pwd"
args["out_path"] = :pwd
end
for (key, val) in args
push!(args_col, (Meta.parse(key), val))
end
for s=source
weave(s; args_col...)
end

View File

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

Binary file not shown.

Binary file not shown.

View File

@ -1,29 +0,0 @@
using Documenter, Weave
CI_FLG = get(ENV, "CI", nothing) == "true"
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",
],
)
CI_FLG && include("make_examples.jl")
deploydocs(
repo = "github.com/JunoLab/Weave.jl.git",
push_preview = true,
)

View File

@ -1,30 +0,0 @@
using Weave
let start_dir = pwd()
cd(@__DIR__)
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")
# 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("../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)
cd(start_dir)
end

View File

@ -1,81 +0,0 @@
# [Chunk Options](@id chunk-options)
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).
## Syntax
Chunk options come after [code chunk](@ref code-chunks) header.
There are two (slightly) different syntax to write them:
- (Julia's toplevel expression) options are separated by semicolon (`;`)
- (RMarkdown style) options are separated by comma (`,`)
Let's take a look at examples. All the following code chunk header are valid,
and so configured to hide the source code from generated output (`echo = false`)
and displays figures with 12cm width (`out_width = "12cm"`):
```md
```julia; echo = false; out_width = "12cm"
```{julia; echo = false; out_width = "12cm"}
```julia, echo = false, out_width = "12cm"
```{julia, echo = false, out_width = "12cm"}
```
## Weave Chunk Options
Weave currently supports the following chunk options:
we've mostly followed [RMarkdown's namings](http://yihui.name/knitr/options), but not all options are implemented.
### Evaluation
- `eval = true`: Evaluate the code chunk. If `false` the chunk wont be executed.
- `error = true`: If `true` [`weave`](@ref) won't stop on errors and rather they will be included in output document. If `false`, [`weave`](@ref) will halt on any of un-caught errors.
- `cache = false`: Cache results, depending on `cache` parameter on [`weave`](@ref) function.
- `tangle = true`: Set tangle to `false` to exclude chunk from tangled code.
### Rendering
- `echo = true`: Echo the code in the output document. If `false` the source code will be hidden.
- `results = "markup"`: The output format of the printed results. `"markup"` for literal block, `"hidden"` for hidden results, or anything else for raw output (I tend to use `"tex"` for Latex and `"rst"` for rest). Raw output is useful if you want to e.g. create tables from code chunks.
- `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
---
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.
```@docs
set_chunk_defaults!
get_chunk_defaults
restore_chunk_defaults!
```

View File

@ -1,5 +0,0 @@
# Function index
```@index
```

View File

@ -1,41 +0,0 @@
# 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 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](https://github.com/JuliaPlots/Plots.jl) for figures:
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)
!!! note
Producing PDF output requires that you have XeLateX installed.
Add dependencies for the example if needed:
```julia
using Pkg; Pkg.add.(["Plots", "DSP"])
```
Weave the files to your working directory:
```julia
using Weave
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).

View File

@ -1,101 +0,0 @@
# 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,38 +0,0 @@
# 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](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**
- 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 in Juno demo](https://user-images.githubusercontent.com/40514306/76081328-32f41900-5fec-11ea-958a-375f77f642a2.png)
## Index
```@contents
Pages = [
"index.md",
"getting_started.md",
"usage.md",
"publish.md",
"chunk_options.md",
"header.md",
"notebooks.md",
"function_index.md",
]
```

View File

@ -1,49 +0,0 @@
# Working with Jupyter notebooks
## Weaving from Jupyter 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") # 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`](@ref) method to convert Weave documents to Jupyter notebooks using
[nbconvert](http://nbconvert.readthedocs.io/en/latest/execute_api.html).
```@docs
notebook
```
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`](@ref) function.
To convert from script to notebook:
```julia
convert_doc("examples/FIR_design.jl", "FIR_design.ipynb")
```
and from notebook to Markdown use:
```julia
convert_doc("FIR_design.ipynb", "FIR_design.jmd")
```
```@docs
convert_doc
```

View File

@ -1,67 +0,0 @@
# Publishing to HTML and PDF
You can also publish any supported input format to HTML and PDF documents.
!!! 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
author : Matti Pastell
date: 15th December 2016
---
```
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(Weave.SAMPLE_JL_DOC)) # default to md2html output format
weave(Weave.SAMPLE_JL_DOC; doctype = "md2pdf")
```
!!! 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 `md2html` and `md2pdf` formats with `template` keyword option,
e.g.: `weave("FIR_design_plots.jl", template = "custom.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](https://docs.julialang.org/en/v1/stdlib/Markdown/#).
In addition Weave supports few additional Markdown features:
### Comments
You can add comments using html syntax: `<!-- -->`
### Multiline equations
You can add multiline equations using:
```
$$
x^2 = x*x
$$
```

View File

@ -1,182 +0,0 @@
# Using Weave
You can write your documentation and code in input document using Markdown, Noweb or script
syntax and use [`weave`](@ref) function to execute to document to capture results and figures.
## `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
using Pkg; Pkg.add.(["Plots", "DSP"])
using Weave
weave(Weave.SAMPLE_JL_DOC; out_path=:pwd)
```
```@docs
weave
```
## `tangle`
Tangling extracts the code from document:
```@docs
tangle
```
## Supported Output Formats
Weave automatically detects the output format based on the file extension.
The auto output format detection is handled by `detect_doctype(path::AbstractString)`:
```julia
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()
```
## [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.
The rules for autodetection are:
```julia
ext == ".jl" && return "script"
ext == ".jmd" && return "markdown"
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.
### [Code Chunks](@id code-chunks)
Code chunks are written in different ways in different formats.
#### Markdown Format
Weave code chunks are defined using fenced code blocks, same as with [common markdown](https://spec.commonmark.org/0.29/#fenced-code-blocks):
```markdown
```julia
code
...
```
```
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
...
```
```
#### Noweb Format
Code chunks start with a line marked with `<<>>=` or `<<options>>=` and end with line marked with `@`.
The code between the start and end markers is executed and the output is captured to the output document.
### [Inline Code](@id inline-code)
You can also add inline code to your documents using
```
`j juliacode`
```
or
```
! juliacode
```
syntax.
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
```

View File

@ -1,83 +0,0 @@
#' ---
#' title : FIR filter design with Julia
#' author : Matti Pastell
#' date : 21th April 2016
#' ---
#' # Introduction
#' This an example of a julia script that can be published using
#' [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
#' 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
#' The next code chunk is executed in term mode, see the [script](FIR_design.jl) for syntax.
#+ term=true
h_db = log10(abs.(h));
ws = w/pi*(fs/2)
#+
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,106 +0,0 @@
---
title: FIR filter design with Julia
author: Matti Pastell
date: 21th April 2016
---
# Introduction
This an example of a julia script that can be published using
[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
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_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
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 Plots, DSP
gr()
function FIRfreqz(b::Array, w = range(0, stop=π, length=1024))
n = length(w)
h = Array{ComplexF32}(undef, 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 = range(0, stop=pi, length=1024)
h = FIRfreqz(f, w)
```
## Plot the frequency and impulse response
The next code chunk is executed in term mode, see the [script](FIR_design.jl) for syntax.
```julia; term=true
h_db = log10.(abs.(h));
ws = w/pi*(fs/2)
```
```julia
plot(ws, h_db,
xlabel = "Frequency (Hz)", ylabel = "Magnitude (db)")
```
And again with default options
```julia
h_phase = unwrap(-atan.(imag.(h),real.(h)))
plot(ws, h_phase,
xlabel = "Frequency (Hz)", ylabel = "Phase (radians)")
```

View File

@ -1,85 +0,0 @@
#' ---
#' title: FIR filter design with Julia
#' author: Matti Pastell
#' date: 21th April 2016
#' ---
#' # Introduction
#' This an example of a julia script that can be published using
#' [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
#' 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_plots.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 Plots, DSP
gr()
function FIRfreqz(b::Array, w = range(0, stop=π, length=1024))
n = length(w)
h = Array{ComplexF32}(undef, 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
#' The next code chunk is executed in term mode, see the [script](FIR_design.jl) for syntax.
#+ term=true
h_db = log10.(abs.(h));
ws = w/pi*(fs/2)
#+
plot(ws, h_db,
xlabel = "Frequency (Hz)", ylabel = "Magnitude (db)")
#' And again with default options
h_phase = unwrap(-atan.(imag.(h),real.(h)))
plot(ws, h_phase,
xlabel = "Frequency (Hz)", ylabel = "Phase (radians)")

View File

@ -1,46 +0,0 @@
\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

@ -1,18 +0,0 @@
<<term=true>>=
using Gadfly
x = linspace(0, 2π, 200)
plot(x=x, y = sin(x), Geom.line)
y = 20
plot(x=x, y = cos(x), Geom.line)
@
<<>>=
x = linspace(0, 200)
println(x)
@
<<fig_cap="Cosine function">>=
plot(x=x, y = cos(x), Geom.line)
@

View File

@ -1,76 +0,0 @@
---
title : Intro to Weave.jl with Gadfly
author : Matti Pastell
date : 13th December 2016
---
# Intro
This a sample [Julia](http://julialang.org/) markdown document that can
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
[gadfly_md_sample.jmd](gadfly_md_sample.jmd)
in the examples directory of the package. The source document can be executed
and the results with Gadfly plots are captured in the resulting file.
You can create markdown output or pdf (with xelatex) and HTML directly using
the weave command as follows:
```{julia; eval=false}
using Weave
#Markdown
weave(Pkg.dir("Weave","examples","gadfly_md_sample.jmd"), informat="markdown",
out_path = :pwd, doctype = "pandoc")
#HTML
weave(Pkg.dir("Weave","examples","gadfly_md_sample.jmd"), informat="markdown",
out_path = :pwd, doctype = "md2html")
#pdf
weave(Pkg.dir("Weave","examples","gadfly_md_sample.jmd"), informat="markdown",
out_path = :pwd, doctype = "md2pdf")
```
*The markdown variant used for html and pdf output is Julia markdown.*
The documents will be written to the Julia working directory when you
use the `out_path = :pwd`.
# Capturing code
The basic code chunk will be run with default options and the code and
output will be captured.
```julia
using Gadfly
x = linspace(0, 2*pi)
println(x)
plot(x = x, y = sin.(x))
```
You can also control the way the results are captured, plot size etc.
using chunk options. Here is an example of a chunk that behaves like a repl.
```{julia;term=true}
x = 1:10
d = Dict("Weave" => "testing")
y = [2, 4 ,8]
```
You can also for instance hide the code and show only the figure, add a
caption to the figure and make it wider as follows (you can only see the
syntax from the source document):
```{julia;echo=false; fig_cap="A random walk."; label="random"; fig_width=7; fig_height=4}
plot(y = cumsum(randn(1000, 1)), Geom.line)
```
# Whats next
Read the documentation:
- stable: [http://mpastell.github.io/Weave.jl/stable/](http://mpastell.github.io/Weave.jl/stable/)
- latest: [http://weavejl.mpastell.com/dev/](http://weavejl.mpastell.com/dev/)
See other examples in the [GitHub repo](https://github.com/JunoLab/Weave.jl/tree/master/examples)

View File

@ -1,83 +0,0 @@
\documentclass{article}
%Minted for syntax hightlighting
\usepackage{minted}
%These are for plots
\usepackage{pgfplots}
\usepackage{fontspec}
\setmainfont{TeX Gyre Pagella}
\usepackage{amsmath}
\usepackage[active,tightpage]{preview}
%Hyperlinks
\usepackage{hyperref}
\hypersetup{colorlinks=true, urlcolor=blue}
%Some style changes
\setlength{\parindent}{0in}
\setlength{\parskip}{12pt}
\author{Matti Pastell}
\title{Using PGF plots with Weave and Gadfly}
\begin{document}
\maketitle
\section{Intro}
This is a minimal example on using PGF format with Gadfly plots in
\href{https://github.com/JunoLab/Weave.jl}{Weave.jl} document.
The source is in github:
\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:
<<eval=false>>=
using Weave
weave(Pkg.dir("Weave", "examples", "gadfly_pgf.texw"),
doctype="texminted", out_path=:pwd, fig_ext=".tex")
@
which will save the generated output in your working directory and use minted
package for syntax hightlighting. You'll need to use either xetex or luatex with
\texttt{-shell-escape} flag to get pdf e.g.
\begin{minted}{bash}
lualatex -shell-escape gadfly_pgf.tex
\end{minted}
\section{Sample code}
You can set the default font in Gadfly to match the font in the document.
Use the \texttt{fontspec} latex package (see preamble) and define the
defaults to Gadfly as follows.
If you want you can hide the chunk using the \texttt{echo=false} chunk option.
<<>>=
using Gadfly
Gadfly.default_theme.major_label_font = "Tex Gyre Pagella"
Gadfly.default_theme.minor_label_font = "Tex Gyre Pagella"
Gadfly.default_theme.major_label_color = colorant"black"
Gadfly.default_theme.minor_label_color = colorant"black"
@
Let's create a simple plot:
<<>>=
x = 1:10
plot(x=x, y=x)
@
And a figure with a caption
<<fig_cap="Nice Gadfly figure">>=
plot([sin, cos], 0, 25)
@
\end{document}

View File

@ -0,0 +1,30 @@
# Gadfly
```{julia;term=true;fig_width=5}
using Gadfly
x = linspace(0, 2π, 200)
plot(x=x, y = sin(x), Geom.line)
y = 20
plot(x=x, y = cos(x), Geom.line)
```
```julia
x = linspace(0, 200)
println(x)
```
~~~{julia;term=true;fig_width=5}
using Gadfly
x = linspace(0, 2π, 200)
plot(x=x, y = sin(x), Geom.line)
y = 20
plot(x=x, y = cos(x), Geom.line)
~~~
~~~julia
x = linspace(0, 200)
println(x)
~~~

View File

@ -1,70 +1,14 @@
% Intro to Weave.jl with Gadfly
% Matti Pastell
% 20th April 2016
# Introduction
This a sample [Julia](http://julialang.org/) noweb document that can
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
of the package. The source document can be executed and the results with Gadfly
plots are captured in the resulting file.
You can create markdown output or pdf and HTML directly (with Pandoc) using
the weave command as follows:
```julia
using Weave
#Markdown
weave(Pkg.dir("Weave","examples","gadfly_sample.mdw"),
out_path = :pwd, doctype = "pandoc")
#HTML
weave(Pkg.dir("Weave","examples","gadfly_sample.mdw"),
out_path = :pwd, doctype = "md2html")
#pdf
weave(Pkg.dir("Weave","examples","gadfly_sample.mdw"),
out_path = :pwd, doctype = "md2pdf")
```
*The documents will be written to the Julia working directory when you
use the `out_path = :pwd`.*
# Capturing code
The basic code chunk will be run with default options and the code and
output will be captured.
<<>>=
using Gadfly
x = linspace(0, 2*pi)
println(x)
plot(x = x, y = sin(x))
@
You can also control the way the results are captured, plot size etc.
using chunk options. Here is an example of a chunk that behaves like a repl.
# Gadfly
<<term=true>>=
x = 1:10
d = Dict("Weave" => "testing")
y = [2, 4 ,8]
using Gadfly
x = linspace(0, 2π, 200)
plot(x=x, y = sin(x), Geom.line)
y = 20
plot(x=x, y = cos(x), Geom.line)
@
You can also for instance hide the code and show only the figure, add a
caption to the figure and make it wider as follows (you can only see the
syntax from the source document):
<<echo=false; fig_cap="A random walk."; label="random"; fig_width=8; fig_height=4>>=
plot(y = cumsum(randn(1000, 1)), Geom.line)
<<>>=
x = linspace(0, 200)
println(x)
@
# Whats next
Read the documentation:
- stable: <http://mpastell.github.io/Weave.jl/stable/>
- latest: <http://weavejl.mpastell.com/dev/>
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.
@ -17,7 +17,7 @@ weave("examples/julia_sample.mdw")
<<term=true>>=
x = 1:10
d = Dict("Weave" => "testing")
d = {"Weave" => "testing"}
y = [2, 4 ,8]
@

BIN
examples/julia_sample.pdf Normal file

Binary file not shown.

View File

@ -1,29 +0,0 @@
---
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,14 +0,0 @@
<<>>=
using Plots
pyplot()
x = linspace(0, 2π, 2056)
@
<<>>=
plot(sinc(x))
@
<<>>=
plot(-sinc(x))
@

View File

@ -1,14 +0,0 @@
<<>>=
using Plots
plotly()
x = linspace(0, 2π, 2056)
@
<<>>=
plot(sinc(x))
@
<<>>=
plot(-sinc(x))
@

View File

@ -0,0 +1,57 @@
# Introducion to Weave
This a sample [Julia](http://julialang.org/) noweb document that can
be executed using Weave. Output from code chunks and Winston
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.
~~~~{.julia}
using Weave
weave(Pkg.dir("Weave","examples","winston_sample.mdw"), plotlib="Winston")
~~~~
## Terminal chunk
<<term=true>>=
x = 1:10
d = {"Weave" => "testing"}
y = [2, 4 ,8]
@
## Capturing figures
The figures and code can be included in the output.
<<term=true>>=
using Winston
t = linspace(0, 2*pi, 100)
p = plot(t, sinc(t))
@
You can also include a plot with caption and hide the code:
<<echo=false; fig_cap="Random walk."; label="random"; fig_width=8; fig_height=4>>=
p = plot(cumsum(randn(1000, 1)))
xlabel("x")
ylabel("sinc(x)")
display(p)
@
<<>>=
x = linspace(0, 3pi, 100)
c = cos(x)
s = sin(x)
p = FramedPlot(
title="title!",
xlabel="\\Sigma x^2_i",
ylabel="\\Theta_i")
add(p, FillBetween(x, c, x, s))
add(p, Curve(x, c, color="red"))
add(p, Curve(x, s, color="blue"))
display(p)
@

View File

@ -1,21 +0,0 @@
@article{julia,
author = {Jeff Bezanson and Alan Edelman and Stefan Karpinski and Viral B. Shah},
title = {Julia: A Fresh Approach to Numerical Computing},
journal = {SIAM Review},
volume = {59},
number = {1},
pages = {65-98},
year = {2017},
doi = {10.1137/141000671},
}
@Book{knitr,
title = {Dynamic Documents with {R} and knitr},
author = {Yihui Xie},
publisher = {Chapman and Hall/CRC},
address = {Boca Raton, Florida},
year = {2015},
edition = {2nd},
note = {ISBN 978-1498716963},
url = {http://yihui.name/knitr/},
}

View File

@ -1,40 +0,0 @@
---
title: 'Weave.jl: Scientific Reports Using Julia'
tags:
- Scientific reports
- Julia
authors:
- name: Matti Pastell
orcid: 0000-0002-5810-4801
affiliation: 1
affiliations:
- name: Natural Resources Institute Finland (Luke)
index: 1
date: 6 March 2017
bibliography: paper.bib
---
# Summary
Weave is a tool for writing scientific reports using Julia
[@julia]. It allows writing of text, mathematics and code in a single
document which can be run capturing results into a rich report.
Output can include text using several markup languages, plots
generated using one of the several Julia plotting libraries and other
objects displayed using Julia's multimedia output. The workflow is
very similar to using Knitr [@knitr] R-package.
Weave supports noweb, markdown, script syntax for delimiting code from
text in the source document and several output formats including
Markdown and Latex. The output from code can be controlled using chunk
options making it possible e.g. to hide code and only show output when
needed as well as set a figure caption and figure size. The library
also has methods for converting documents from all input formats to
Jupyter notebooks and vice versa.
The package aims to support writing scientific papers and enable easy
sharing of analysis in order to promote reproducible research. It also
aims to enable simple writing of educational material, tutorials and
blog posts.
# References

View File

@ -1,344 +1,275 @@
module Weave
using Compat
using Highlights, Mustache, Requires, Pkg, REPL, RelocatableFolders, Base64
#Contains report global properties
type Report <: Display
source::String
documentationmode::Bool
cwd::String
basename::String
formatdict
pending_code::String
cur_result::String
fignum::Int
figures::Array
term_state::Symbol
cur_chunk::Dict{Symbol, Any}
# 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"
function Report()
new("", false, "", "", Any[], "", "", 1, Any[], :text, @compat Dict{Symbol, Any}() )
end
const WEAVE_VERSION = try
'v' * Pkg.TOML.parsefile(normpath(PKG_DIR, "Project.toml"))["version"]
catch
""
end
weave_info() = WEAVE_VERSION, string(Date(now()))
function __init__()
@require Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" include("plots.jl")
@require Gadfly = "c91e804a-d5a3-530f-b6f0-dfbca275c004" include("gadfly.jl")
end
# utilitity functions
take2string!(io) = String(take!(io))
joinlines(lines) = join(lines, '\n')
const report = Report()
const supported_mime_types =
[MIME"image/png",
MIME"text/plain"]
include("types.jl")
include("config.jl")
include("WeaveMarkdown/markdown.jl")
include("display_methods.jl")
include("reader/reader.jl")
include("run.jl")
include("cache.jl")
include("rendering/rendering.jl")
include("writer/writer.jl")
include("converter.jl")
get_format(doctype::AbstractString) = FORMATS[doctype]
"""
list_out_formats()
List supported output formats 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.
## 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::AbstractString;
out_path::Union{Symbol,AbstractString} = :doc,
informat::Union{Nothing,AbstractString} = nothing,
)
doc = WeaveDoc(source, informat)
doc.cwd = get_cwd(doc, out_path)
out_path = get_out_path(doc, out_path, "jl")
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
@info "Tangled to $(out_path)"
end
"""
weave(source::AbstractString; kwargs...)
Weave an input document to output file.
## Keyword options
- `doctype::Union{Nothing,AbstractString} = nothing`: Output document format. By default (i.e. given `nothing`), Weave will set it automatically based on file extension. You can also manually specify it; see [`list_out_formats()`](@ref) for the supported formats
- `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::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)
# run document
# ------------
# 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
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
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,
)
# 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
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,
)
# render document
# ---------------
rendered = render_doc(doc)
# 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)
function Base.display(doc::Report, data)
for m in supported_mime_types
if mimewritable(m(), data)
display(doc, m(), data)
brea
end
end
end
get_out_path(doc, out_path, ext::Nothing = nothing) = get_out_path(doc, out_path, doc.format.extension)
function get_out_path(doc, out_path, ext)
if (out_path === :doc) || (out_path === :pwd)
abspath(get_cwd(doc, out_path), string(doc.basename, '.', ext))
elseif isempty(splitext(out_path)[2]) # directory given
abspath(get_cwd(doc, out_path), string(doc.basename, '.', ext))
function list_out_formats()
for format = keys(formats)
println(string(format,": ", formats[format].description))
end
end
#module ReportSandBox
#end
function weave(source ; doctype = "pandoc", plotlib="PyPlot", informat="noweb", fig_path = "figures", fig_ext = nothing)
cwd, fname = splitdir(abspath(source))
basename = splitext(fname)[1]
formatdict = formats[doctype].formatdict
if fig_ext == nothing
rcParams[:chunk_defaults][:fig_ext] = formatdict[:fig_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))
rcParams[:chunk_defaults][:fig_ext] = fig_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
report.source = source
report.cwd = cwd
report.basename = basename
rcParams[:chunk_defaults][:fig_path] = fig_path
report.formatdict = formatdict
!!! 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")
if plotlib == nothing
rcParams[:chunk_defaults][:fig] = false
else
l_plotlib = lowercase(plotlib)
rcParams[:chunk_defaults][:fig] = true
if l_plotlib == "winston"
eval(parse("""include(Pkg.dir("Weave","src","winston.jl"))"""))
rcParams[:plotlib] = "Winston"
elseif l_plotlib == "pyplot"
eval(Expr(:using, :PyPlot))
rcParams[:plotlib] = "PyPlot"
elseif l_plotlib == "gadfly"
eval(parse("""include(Pkg.dir("Weave","src","gadfly.jl"))"""))
rcParams[:plotlib] = "Gadfly"
end
end
write(out_path, converted)
pushdisplay(report)
parsed = read_document(source, informat)
executed = run(parsed)
popdisplay(report)
formatted = format(executed, doctype)
outname = "$(report.cwd)/$(report.basename).$(formatdict[:extension])"
open(outname, "w") do io
write(io, join(formatted, "\n"))
end
info("Report weaved to $(report.basename).$(formatdict[:extension])")
@info "Running nbconvert ..."
return read(
`$jupyter_path nbconvert --ExecutePreprocessor.timeout=$timeout --to notebook --execute $(out_path) $nbconvert_options --output $(out_path)`,
String,
)
end
"""
include_weave(source::AbstractString, informat::Union{Nothing,AbstractString} = nothing)
include_weave(m::Module, source::AbstractString, informat::Union{Nothing,AbstractString} = nothing)
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(
m::Module,
source::AbstractString,
informat::Union{Nothing,AbstractString} = nothing,
)
old_path = pwd()
doc = WeaveDoc(source, informat)
cd(dirname(doc.path))
function run_block(code_str)
oldSTDOUT = STDOUT
result = ""
rw, wr = redirect_stdout()
#If there is nothing to read code will hang
println()
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)
n = length(code_str)
pos = 1 #The first character is extra line end
while pos < n
oldpos = pos
code, pos = parse(code_str, pos)
s = eval(ReportSandBox, code)
if rcParams[:plotlib] == "Gadfly"
s != nothing && display(s)
end
end
finally
cd(old_path)
redirect_stdout(oldSTDOUT)
close(wr)
result = readall(rw)
close(rw)
end
return nothing
return string("\n", result)
end
include_weave(source, informat = nothing) = include_weave(Main, source, informat)
function run_term(code_str)
prompt = "\njulia> "
codestart = "\n\n"*report.formatdict[:codestart]
if haskey(report.formatdict, :indent)
prompt = indent(prompt, report.formatdict[:indent])
end
export weave,
list_out_formats,
tangle,
convert_doc,
notebook,
set_chunk_defaults!,
get_chunk_defaults,
restore_chunk_defaults!,
include_weave
#Emulate terminal
n = length(code_str)
pos = 2 #The first character is extra line end
while pos < n
oldpos = pos
code, pos = parse(code_str, pos)
report.term_state == :fig && (report.cur_result*= codestart)
prompts = string(prompt, rstrip(code_str[oldpos:(pos-1)]), "\n")
report.cur_result *= prompts
report.term_state = :text
s = eval(ReportSandBox, code)
s != nothing && display(s)
end
return string(report.cur_result)
end
function run(parsed)
#Clear sandbox for each document
#Raises a warning, couldn't find a "cleaner"
#way to do it.
eval(parse("module ReportSandBox\nend"))
i = 1
for chunk in copy(parsed)
if chunk[:type] == "code"
#print(chunk["content"])
info("Weaving chunk $(chunk[:number]) from line $(chunk[:start_line])")
defaults = copy(rcParams[:chunk_defaults])
options = copy(chunk[:options])
try
options = merge(rcParams[:chunk_defaults], options)
catch
options = rcParams[:chunk_defaults]
warn("Invalid format for chunk options line: $(chunk[:start_line])")
end
merge!(chunk, options)
delete!(chunk, :options)
if !chunk[:eval]
chunk[:result] = ""
parsed[i] = copy(chunk)
i += 1
continue #Do nothing if eval is false
end
report.fignum = 1
report.cur_result = ""
report.figures = String[]
report.cur_chunk = chunk
report.term_state = :text
if haskey(report.formatdict, :out_width) && chunk[:out_width] == nothing
chunk[:out_width] = report.formatdict[:out_width]
end
if chunk[:term]
chunk[:result] = run_term(chunk[:content])
chunk[:term_state] = report.term_state
else
chunk[:result] = run_block(chunk[:content])
end
if rcParams[:plotlib] == "PyPlot"
chunk[:fig] && (chunk[:figure] = savefigs(chunk))
else
chunk[:fig] && (chunk[:figure] = copy(report.figures))
end
end
parsed[i] = copy(chunk)
i += 1
end
parsed
end
function savefigs(chunk)
l_plotlib = lowercase(rcParams[:plotlib])
if l_plotlib == "pyplot"
return savefigs_pyplot(chunk)
end
end
function savefigs_pyplot(chunk)
fignames = String[]
ext = report.formatdict[:fig_ext]
figpath = joinpath(report.cwd, chunk[:fig_path])
isdir(figpath) || mkdir(figpath)
chunkid = (chunk[:name] == nothing) ? chunk[:number] : chunk[:name]
#Iterate over all open figures, save them and store names
for fig = plt.get_fignums()
full_name, rel_name = get_figname(report, chunk, fignum=fig)
savefig(full_name, dpi=chunk[:dpi])
push!(fignames, rel_name)
plt.draw()
plt.close()
end
return fignames
end
function Base.display(report::Report, m::MIME"text/plain", data)
if report.term_state == :fig #Catch Winston plot command output
report.cur_result *= "\n" * report.formatdict[:codestart] * "\n"
end
s = reprmime(m, data)
haskey(report.formatdict, :indent) && (s = indent(s, report.formatdict[:indent]))
report.cur_result *= s * "\n"
if report.term_state == :fig #Catch Winston plot command output
report.cur_result *= "\n" * report.formatdict[:codeend] * "\n"
end
end
function get_figname(report::Report, chunk; fignum = nothing)
figpath = joinpath(report.cwd, chunk[:fig_path])
isdir(figpath) || mkdir(figpath)
ext = chunk[:fig_ext]
fignum == nothing && (fignum = report.fignum)
chunkid = (chunk[:name] == nothing) ? chunk[:number] : chunk[:name]
full_name = joinpath(report.cwd, chunk[:fig_path], "$(report.basename)_$(chunkid)_$(fignum)$ext")
rel_name = "$(chunk[:fig_path])/$(report.basename)_$(chunkid)_$(fignum)$ext" #Relative path is used in output
return full_name, rel_name
end
export weave, list_out_formats
include("config.jl")
include("readers.jl")
include("formatters.jl")
end

View File

@ -1,248 +0,0 @@
# Markdown to HTML writer, Modified from Julia Base.Markdown html writer
using Markdown:
MD,
Header,
Code,
Paragraph,
BlockQuote,
Footnote,
Table,
Admonition,
List,
HorizontalRule,
Bold,
Italic,
Image,
Link,
LineBreak,
LaTeX,
isordered
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,""")
print(io, stringmime(m, img))
print(io, "\" />")
end
tohtml(m::MIME"image/svg+xml", img) = show(io, m, img)
# AbstractDisplay infrastructure
function bestmime(val)
for mime in ("text/html", "image/svg+xml", "image/png", "text/plain")
showable(mime, val) && return MIME(Symbol(mime))
end
error("Cannot render $val to Markdown.")
end
tohtml(io::IO, x) = tohtml(io, bestmime(x), x)
# Utils
function withtag(f, io::IO, tag, attrs...)
print(io, "<$tag")
for (attr, value) in attrs
print(io, " ")
htmlesc(io, attr)
print(io, "=\"")
htmlesc(io, value)
print(io, "\"")
end
f === nothing && return print(io, " />")
print(io, ">")
f()
print(io, "</$tag>")
end
tag(io::IO, tag, attrs...) = withtag(nothing, io, tag, attrs...)
const _htmlescape_chars = Dict(
'<' => "&lt;",
'>' => "&gt;",
'"' => "&quot;",
'&' => "&amp;",
# ' '=>"&nbsp;",
)
for ch in "'`!\$%()=+{}[]"
_htmlescape_chars[ch] = "&#$(Int(ch));"
end
function htmlesc(io::IO, s::AbstractString)
# s1 = replace(s, r"&(?!(\w+|\#\d+);)" => "&amp;")
for ch in s
print(io, get(_htmlescape_chars, ch, ch))
end
end
function htmlesc(io::IO, s::Symbol)
htmlesc(io, string(s))
end
function htmlesc(io::IO, xs::Union{AbstractString,Symbol}...)
for s in xs
htmlesc(io, s)
end
end
function htmlesc(s::Union{AbstractString,Symbol})
sprint(htmlesc, s)
end
# Block elements
function html(io::IO, content::Vector)
for md in content
html(io, md)
println(io)
end
end
html(io::IO, md::MD) = html(io, md.content)
function html(io::IO, header::Header{l}) where {l}
withtag(io, "h$l") do
htmlinline(io, header.text)
end
end
function html(io::IO, code::Code)
withtag(io, :pre) do
maybe_lang = !isempty(code.language) ? Any[:class=>"language-$(code.language)"] : []
withtag(io, :code, maybe_lang...) do
htmlesc(io, code.code)
# TODO should print newline if this is longer than one line ?
end
end
end
function html(io::IO, md::Paragraph)
withtag(io, :p) do
htmlinline(io, md.content)
end
end
function html(io::IO, md::BlockQuote)
withtag(io, :blockquote) do
println(io)
html(io, md.content)
end
end
function html(io::IO, f::Footnote)
withtag(io, :div, :class => "footnote", :id => "footnote-$(f.id)") do
withtag(io, :p, :class => "footnote-title") do
print(io, f.id)
end
html(io, f.text)
end
end
function html(io::IO, md::Admonition)
withtag(io, :div, :class => "admonition $(md.category)") do
withtag(io, :p, :class => "admonition-title") do
print(io, md.title)
end
html(io, md.content)
end
end
function html(io::IO, md::List)
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)
withtag(io, :li) do
html(io, item)
end
end
println(io)
end
end
html(io::IO, md::HorizontalRule) = tag(io, :hr)
function html(io::IO, tex::LaTeX)
withtag(io, :p, :class => "math") do
write(io, string("\\[\n", tex.formula, "\n\\]"))
end
end
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)
# Inline elements
function htmlinline(io::IO, content::Vector)
for x in content
htmlinline(io, x)
end
end
function htmlinline(io::IO, code::Code)
withtag(io, :code) do
htmlesc(io, code.code)
end
end
function htmlinline(io::IO, tex::LaTeX)
withtag(io, :span, :class => "math") do
write(io, string("\$", tex.formula, "\$"))
end
end
htmlinline(io::IO, md::Union{Symbol,AbstractString}) = htmlesc(io, md)
function htmlinline(io::IO, md::Bold)
withtag(io, :strong) do
htmlinline(io, md.text)
end
end
function htmlinline(io::IO, md::Italic)
withtag(io, :em) do
htmlinline(io, md.text)
end
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
print(io, "[", f.id, "]")
end
end
function htmlinline(io::IO, link::Link)
withtag(io, :a, :href => link.url) do
htmlinline(io, link.text)
end
end
htmlinline(io::IO, br::LineBreak) = tag(io, :br)
htmlinline(io::IO, comment::Comment) = write(io, "<!-- $(comment.text) -->")
htmlinline(io::IO, x) = tohtml(io, x)
# API
html(md) = sprint(html, md)

View File

@ -1,9 +0,0 @@
import Markdown: latex, latexinline
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,92 +0,0 @@
# 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)
withstream(stream) do
str = Markdown.startswith(stream, r"^\$\$$"m)
isempty(str) && return false
trailing = strip(readline(stream))
buffer = IOBuffer()
while !eof(stream)
line_start = position(stream)
estr = Markdown.startswith(stream, r"^\$\$$"m)
if !isempty(estr)
estr = Markdown.startswith(stream, r"^\$\$$"m)
if isempty(estr)
push!(block, LaTeX(take2string!(buffer) |> chomp))
end
return true
else
seek(stream, line_start)
end
write(buffer, readline(stream, keep = true))
end
return false
end
end
@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)
write(buffer, line)
if occursin(r"-->$", line)
s = replace(take2string!(buffer) |> chomp, r"-->$" => "")
push!(block, Comment(s))
return true
end
end
return false
end
end
@trigger '<' -> function comment(stream::IO, md::MD)
withstream(stream) do
Markdown.startswith(stream, "<!--") || return
text = Markdown.readuntil(stream, "-->")
isnothing(text) && return
return Comment(text)
end
end
# Create own flavor and copy all the features from julia flavor
Markdown.@flavor weavemd [dollarmath, comment, topcomment]
weavemd.breaking = [weavemd.breaking; Markdown.julia.breaking]
weavemd.regular = [weavemd.regular; Markdown.julia.regular]
for key in keys(Markdown.julia.inner)
if haskey(weavemd.inner, key)
weavemd.inner[key] = [weavemd.inner[key]; Markdown.julia.inner[key]]
else
weavemd.inner[key] = Markdown.julia.inner[key]
end
end
include("html.jl")
include("latex.jl")
end # module

View File

@ -1,64 +0,0 @@
# 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
Serialization.serialize(io, doc)
end
return nothing
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
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,
)
# 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.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
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)
isempty(c_chunk) && return chunk
c_chunk = c_chunk[1]
# Collect cached code
c_inline = filter(x -> isa(x, InlineCode), c_chunk.content)
isempty(c_inline) && return chunk
# Restore cached results for Inline code
n = length(chunk.content)
for i = 1:n
if isa(chunk.content[i], InlineCode)
ci = filter(x -> x.number == chunk.content[i].number, c_inline)
isempty(ci) && continue
chunk.content[i].output = ci[1].output
chunk.content[i].rich_output = ci[1].rich_output
chunk.content[i].figures = ci[1].figures
end
end
return chunk
end

View File

@ -1,58 +1,77 @@
# 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!(k, v)
set_chunk_defaults!(kv::Pair...)
set_chunk_defaults!(opts::AbstractDict)
Set default options for code chunks, use [`get_chunk_defaults`](@ref) to see the current values.
E.g.: all the three examples below will set default `dpi` to `200` and `fig_width` to `8`:
- `set_chunk_defaults!(:dpi, 200); set_chunk_defaults!(:fig_width, 8)`
- `set_chunk_defaults!(:dpi => 200, :fig_width => 8)`
- `set_chunk_defaults!(Dict(:dpi => 200, :fig_width => 8))`
"""
set_chunk_defaults!(k, v) = DEFAULT_PARAMS[k]= v
set_chunk_defaults!(kv::Pair...) = for (k,v) in kv; set_chunk_defaults!(k, v); end
set_chunk_defaults!(opts::AbstractDict) = merge!(DEFAULT_PARAMS, opts)
"""
get_chunk_defaults()
Get default options used for code chunks.
"""
get_chunk_defaults() = DEFAULT_PARAMS
"""
restore_chunk_defaults!()
Restore Weave.jl default chunk options.
"""
restore_chunk_defaults!() = for (k,v) in _DEFAULT_PARAMS; DEFAULT_PARAMS[k] = v; end
const rcParams =
@compat Dict{Symbol,Any}(:plotlib => "PyPlot",
:storeresults => false,
:chunk_defaults =>
Dict{Symbol,Any}(
:echo=> true,
:results=> "markup",
:fig=> true,
:include=> true,
:eval => true,
:fig_cap=> nothing,
#Size in inches
:fig_width => 6,
:fig_height => 4,
:fig_path=> "figures",
:dpi => 96,
:term=> false,
:name=> nothing,
:wrap=> true,
:engine=> "julia",
:option_string=> "",
#Defined in formats
:fig_ext => nothing,
:fig_pos=> nothing,
:fig_env=> nothing,
:out_width=> nothing,
:out_height=> nothing,
)
)
# Working towards Knitr compatible options, implemented options are
# added to defaultoptions dictionary above and work in progress stays here,
# options from https://github.com/yihui/knitr/blob/master/R/defaults.R
# If you need a particular options, consider implementing it and making a
# pull request.
#tidy = FALSE,
#tidy.opts = NULL,
#collapse = FALSE
#prompt = FALSE
#highlight = TRUE
#strip.white = TRUE
#size = 'normalsize'
#background = '#F7F7F7',
#cache = FALSE
#cache.path = 'cache/'
#cache.vars = NULL
#cache.lazy = TRUE,
#dependson = NULL
#autodep = FALSE,
#fig.keep = 'high'
#fig.show = 'asis'
#fig.align = 'default'
#dev = NULL
#dev.args = NULL
#fig.ext = NULL
#fig.scap = NULL
#fig.lp = 'fig:'
#fig.subcap = NULL,
#out.extra = NULL
#fig.retina = 1,
#external = TRUE
#sanitize = FALSE
#interval = 1
#aniopts = 'controls,loop',
#warning = TRUE
#error = TRUE
#message = TRUE,
#render = NULL,
#ref.label = NULL
#child = NULL
#split = FALSE
#purl = TRUE

View File

@ -1,144 +0,0 @@
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,133 +0,0 @@
using Markdown, .WeaveMarkdown
# Contains report global properties
mutable struct Report <: AbstractDisplay
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
Report(cwd, basename, format, mimetypes) =
Report(cwd, basename, format, "", 1, String[], nothing, mimetypes, true, "")
# Default mimetypes in order, can be overridden for some inside `run method` formats
const default_mime_types = ["image/svg+xml", "image/png", "text/html", "text/plain"]
# 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",
".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
fig_ext = report.cur_chunk.options[:fig_ext]
for m in unique([mimetype_ext[fig_ext]; report.mimetypes])
if Base.invokelatest(showable, m, data)
try
if !istextmime(m)
Base.invokelatest(display, report, m, data)
elseif report.cur_chunk.options[:term]
Base.invokelatest(display, report, "text/plain", data)
else
Base.invokelatest(display, report, m, data)
end
catch e
throw(e)
@warn("Failed to display data in \"$m\" format")
continue
end
break
end
end
end
Base.display(report::Report, m::MIME"image/png", data) = add_figure(report, data, m, ".png")
Base.display(report::Report, m::MIME"image/svg+xml", data) = add_figure(report, data, m, ".svg")
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
function Base.display(report::Report, m::MIME"text/plain", data)
io = PipeBuffer()
show(IOContext(io, :limit => true), m, data)
flush(io)
s = read(io, String)
close(io)
println(s)
end
function Base.display(report::Report, m::MIME"text/plain", data::Exception)
println("Error: " * sprint(showerror, data))
end
function Base.display(report::Report, m::MIME"text/html", data::Exception)
report.rich_output = sprint(show, m, data)
end
function Base.show(io, m::MIME"text/html", data::Exception)
println(io, "<pre class=\"julia-error\">")
println(io, Markdown.htmlesc("ERROR: " * sprint(showerror, data)))
println(io, "</pre>")
end
# Catch "rich_output"
function Base.display(report::Report, m::MIME"text/html", data)
io = IOBuffer()
show(IOContext(io, :limit => true), m, data)
report.rich_output *= string('\n', take2string!(io))
end
# 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))
break
elseif m == "text/markdown"
report.rich_output *= "\n" * s
break
end
end
end
function Base.display(report::Report, m::MIME"text/latex", data)
s = repr(m, data)
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)
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
end

293
src/formatters.jl Normal file
View File

@ -0,0 +1,293 @@
using TextWrap
#Format the executed document
function format(executed, doctype)
formatted = String[]
docformat = formats[doctype]
#@show docformat
#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)
for chunk in copy(executed)
if chunk[:type] == "doc"
push!(formatted, chunk[:content])
else
#Fill undefined options with format specific defaults
chunk[:out_width] == nothing && (chunk[:out_width] = docformat.formatdict[:out_width])
chunk[:fig_pos] == nothing && (chunk[:fig_pos] = docformat.formatdict[:fig_pos])
#Only use floats if chunk has caption or sets fig_env
if chunk[:fig_cap] != nothing && chunk[:fig_env] == nothing
(chunk[:fig_env] = docformat.formatdict[:fig_env])
end
#Format code
result = format_codechunk(chunk, formatdict)
#Handle figures
if chunk[:fig] && length(chunk[:figure]) > 0
if chunk[:include]
result *= formatfigures(chunk, docformat)
end
end
push!(formatted, result)
end
end
return formatted
end
function format_codechunk(chunk, formatdict)
if haskey(formatdict, :indent)
chunk[:content] = indent(chunk[:content], formatdict[:indent])
end
if !chunk[:eval]
if chunk[:echo]
result = "$(formatdict[:codestart])$(chunk[:content])\n$(formatdict[:codeend])"
return result
else
r = ""
return r
end
end
if chunk[:term]
result = format_termchunk(chunk, formatdict)
else
if chunk[:wrap]
chunk[:result] = "\n" * wrap(chunk[:result], replace_whitespace=false)
end
if chunk[:echo]
result = "$(formatdict[:codestart])$(chunk[:content])\n$(formatdict[:codeend])\n"
else
result = ""
end
if (strip(chunk[:result])!= "") && (chunk[:results] != "hidden")
#@show chunk
if chunk[:results] != "markup"
result *= "$(chunk[:result])"
elseif chunk[:results] == "markup"
if haskey(formatdict, :indent)
chunk[:result] = indent(chunk[:result], formatdict[:indent])
end
result *= "$(formatdict[:outputstart])$(chunk[:result])\n$(formatdict[:outputend])\n"
end
end
end
return result
end
function format_termchunk(chunk, formatdict)
if chunk[:echo] && chunk[:results] != "hidden"
result = "$(formatdict[:termstart])$(chunk[:result])\n"
#@show chunk[:term_state]
chunk[:term_state] == :text && (result*= "$(formatdict[:termend])\n")
else
result = ""
end
return result
end
function indent(text, nindent)
return join(map(x->
string(repeat(" ", nindent), x), split(text, "\n")), "\n")
end
type Tex
description::String
formatdict::Dict{Symbol,Any}
end
const tex = Tex("Latex with custom code environments",
@compat 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"
))
const texminted = Tex("Latex using minted for highlighting",
@compat 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"
))
type Markdown
description::String
formatdict::Dict{Symbol,Any}
end
const pandoc = Markdown("Pandoc markdown",
@compat Dict{Symbol,Any}(
:codestart => "~~~~{.julia}",
:codeend=>"~~~~~~~~~~~~~\n\n",
:outputstart=>"~~~~{.julia}",
:outputend=>"~~~~~~~~~~~~~\n\n",
:fig_ext=>".png",
:extension=>"md",
:doctype=>"pandoc"
))
const github = Markdown("Github markdown",
@compat Dict{Symbol,Any}(
:codestart => "````julia",
:codeend=> "````\n\n",
:outputstart=> "````julia",
:outputend=> "````\n\n",
:fig_ext=> ".png",
:extension=> "md",
:doctype=> "github"
))
type Rest
description::String
formatdict::Dict{Symbol,Any}
end
const rst = Rest("reStructuredText and Sphinx",
@compat 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"
))
function formatfigures(chunk, docformat::Tex)
fignames = chunk[:figure]
caption = chunk[:fig_cap]
width = chunk[:out_width]
f_pos = chunk[:fig_pos]
f_env = chunk[:fig_env]
result = ""
figstring = ""
if f_env != nothing
result *= """\\begin{$f_env}[$f_pos]\n"""
end
for fig = fignames
figstring *= "\\includegraphics[width=$width]{$fig}\n"
end
# Figure environment
if caption != nothing
result *= string("\\center\n",
"$figstring",
"\\caption{$caption}\n")
else
result *= figstring
end
if chunk[:name] != nothing && f_env !=nothing
label = chunk[:name]
result *= "\\label{fig:$label}\n"
end
if f_env != nothing
result *= "\\end{$f_env}\n"
end
return result
end
function formatfigures(chunk, docformat::Markdown)
fignames = chunk[:figure]
caption = chunk[: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::Rest)
fignames = chunk[:figure]
caption = chunk[:fig_cap]
width = chunk[: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
#Add new supported formats here
const formats = @compat Dict{String, Any}("tex" => tex,
"texminted" => texminted,
"pandoc" => pandoc,
"github" => github,
"rst" => rst
)

View File

@ -1,51 +1,56 @@
module GadflyPlots
using Gadfly
using ..Weave, ..Gadfly
Gadfly.set_default_plot_format(:png)
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
function Base.display(report::Weave.Report, m::MIME"image/svg+xml", p::Gadfly.Plot)
#Captures figures
function Base.display(report::Report, m::MIME"image/png", p::Plot)
chunk = report.cur_chunk
w = chunk.options[:fig_width] * Gadfly.inch
h = chunk.options[:fig_height] * Gadfly.inch
format = chunk.options[:fig_ext]
dpi = chunk.options[:dpi]
#if chunk[:fig_ext] != ".png"
# chunk[:fig_ext]
# warn("Saving figures as .png with Gadfly")
#end
full_name, rel_name = Weave.get_figname(report, chunk, ext = format)
full_name, rel_name = get_figname(report, chunk)
docformat = formats[report.formatdict[:doctype]]
#Add to results for term chunks and store otherwise
if chunk[:term]
chunk[:figure] = [rel_name]
if report.term_state == :text
report.cur_result *= "\n" * report.formatdict[:codeend] * "\n"
end
report.cur_result *= formatfigures(chunk, docformat)
report.term_state = :fig
chunk[:figure] = String[]
else
push!(report.figures, rel_name)
end
push!(report.figures, rel_name)
report.fignum += 1
if format == ".svg"
Gadfly.draw(Gadfly.SVG(full_name, w, h), p)
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)
#TODO other formats
#Can't specify dpi in Gadfly? Opened Gadfly issue #504
w = chunk[:fig_width]inch
h = chunk[:fig_height]inch
format = chunk[:fig_ext]
#This is probably not the correct way to handle different formats, but it works.
if format == ".png"
draw(PNG(full_name, w, h), p)
elseif format == ".pdf"
Gadfly.draw(Gadfly.PDF(full_name, w, h), p)
draw(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)
else
@warn("Can't save figure. Unsupported format, $format")
draw(PS(full_name, w, h), p)
elseif format == ".svg"
draw(SVG(full_name, w, h), p)
elseif format == ".js.svg"
draw(SVGJS(full_name, w, h), p)
else:
warn("Can't save figure. Unsupported format")
end
end
end

View File

@ -1,112 +0,0 @@
module WeavePlots
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_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
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
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)
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)
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
end
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)
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)
add_plots_figure(report, plot, ".pdf")
end
function Base.display(report::Weave.Report, m::MIME"image/png", plot::Plots.Plot)
add_plots_figure(report, plot, ".png")
end
function Base.display(report::Weave.Report, m::MIME"image/svg+xml", plot::Plots.Plot)
add_plots_figure(report, plot, ".svg")
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
report.rich_output *= "\n" * res * "\n"
end
end

View File

@ -1,95 +0,0 @@
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

View File

@ -1,23 +0,0 @@
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

View File

@ -1,128 +0,0 @@
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")

View File

@ -1,67 +0,0 @@
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

84
src/readers.jl Normal file
View File

@ -0,0 +1,84 @@
pushopt(options::Dict,expr::Expr) = Base.Meta.isexpr(expr,:(=)) && (options[expr.args[1]] = expr.args[2])
const input_formats = @compat Dict{String, Any}(
"noweb" => Dict{Symbol, Any}(
:codestart => r"^<<(.*?)>>=\s*$",
:codeend => r"^@\s*$"
),
"markdown" => Dict{Symbol, Any}(
:codestart => r"(?:^(?:`|~){3,}\s*(?:\{|\{\.|)julia(?:;|\s)(.*)\}\s*$)|(?:^(?:`|~){3,}\s*julia\s*$)",
:codeend => r"^`|~{3,}\s*$"
)
)
function read_document(document, format)
#doctext = readall(open(document))
lines = split(bytestring(open(document) do io
mmap_array(Uint8,(filesize(document),),io)
end), "\n")
codestart = input_formats[format][:codestart]
codeend = input_formats[format][:codeend]
state = "doc"
docno = 1
codeno = 1
content = ""
start_line = 0
options = Dict()
optionstring = ""
parsed = Dict[]
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
#@show optionstring
options = Dict{Symbol,Any}()
if length(optionstring) > 0
expr = 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)
#@show options
chunk = @compat Dict{Symbol,Any}(:type => "doc", :content => content,
:number => docno,:start_line => start_line)
docno += 1
start_line = lineno
push!(parsed, chunk)
content = ""
continue
end
if ismatch(codeend, line) && state=="code"
chunk = @compat Dict{Symbol,Any}(:type => "code", :content => content,
:number => codeno, :options => options,
:optionstring => optionstring,
:start_line => start_line)
codeno+=1
start_line = lineno
content = ""
state = "doc"
push!(parsed, chunk)
continue
end
content *= "\n" * line
end
#Remember the last chunk
if content != ""
chunk = @compat Dict{Symbol,Any}(:type => "doc", :content => content,
:number => docno, :start_line => start_line)
push!(parsed, chunk)
end
return parsed
end

View File

@ -1,162 +0,0 @@
# 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

@ -1,24 +0,0 @@
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

@ -1,146 +0,0 @@
# 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

@ -1,224 +0,0 @@
# 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

@ -1,70 +0,0 @@
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

@ -1,31 +0,0 @@
# 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")

View File

@ -1,264 +0,0 @@
# 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,451 +0,0 @@
using Base64
const PROGRESS_ID = "weave_progress"
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
doc.doctype = isnothing(doctype) ? (doctype = detect_doctype(doc.source)) : doctype
doc.format = deepcopy(get_format(doctype))
cwd = doc.cwd = get_cwd(doc, out_path)
mkpath(cwd)
# TODO: provide a way not to create `fig_path` ?
if isnothing(fig_path)
fig_path = if (endswith(doctype, "2pdf") && cache === :off) || endswith(doctype, "2html")
basename(mktempdir(abspath(cwd)))
else
DEFAULT_FIG_PATH
end
end
mkpath(normpath(cwd, fig_path))
# This is needed for latex and should work on all output formats
@static Sys.iswindows() && (fig_path = replace(fig_path, "\\" => "/"))
set_rc_params(doc, fig_path, fig_ext)
cache === :off || @eval import Serialization # XXX: evaluate in a more sensible module
# 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)))
mimetypes = doc.format.mimetypes
report = Report(cwd, doc.basename, doc.format, mimetypes)
cd_back = let d = pwd(); () -> cd(d); end
cd(cwd)
pushdisplay(report)
try
if cache !== :off && cache !== :refresh
cached = read_cache(doc, cache_path)
isnothing(cached) && @info "No cached results found, running code"
else
cached = nothing
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)
@info "Weaving chunk $(chunk.number) from line $(chunk.start_line)" progress=(i)/n _id=PROGRESS_ID
i+=1
end
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
replace_header_inline!(doc, report, mod) # evaluate and replace inline code in header
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
run_doc(doc::WeaveDoc, doctype::Union{Nothing,AbstractString}; kwargs...) =
run_doc(doc; doctype = doctype, kwargs...)
"""
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 get_cwd(doc, out_path)
return if out_path === :doc
dirname(doc.path)
elseif out_path === :pwd
pwd()
else
path, ext = splitext(out_path)
if isempty(ext) # directory given
path
else # file given
dirname(path)
end
end |> abspath
end
function run_chunk(chunk::CodeChunk, doc, report, mod)
result = eval_chunk(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")
raw = read(f)
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, report, mod)
chunk.content = [run_inline(c, doc, report, mod) for c in chunk.content]
return chunk
end
run_inline(inline::InlineText, ::WeaveDoc, ::Report, ::Module) = inline
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(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])
inline.output = output
inline.rich_output = chunks[1].rich_output
inline.figures = chunks[1].figures
return inline
end
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 split_code(code)
res = String[]
e = 1
ex = :init
while true
s = e
ex, e = Meta.parse(code, s)
isnothing(ex) && break
push!(res, strip(code[s:e-1]))
end
return res
end
function capture_output(code, mod, path, error, report)
reset_report!(report)
old = stdout
rw, wr = redirect_stdout()
reader = @async read(rw, String)
local out = nothing
task_local_storage(:SOURCE_PATH, path) do
try
obj = include_string(mod, code, path) # TODO: fix line number
!isnothing(obj) && !REPL.ends_with_semicolon(code) && display(obj)
catch _err
err = unwrap_load_err(_err)
error || throw(err)
display(err)
@warn "ERROR: $(typeof(err)) occurred, including output in Weaved document"
finally
redirect_stdout(old)
close(wr)
out = fetch(reader)
close(rw)
end
end
return ChunkOutput(code, remove_ansi_control_chars(out), report.rich_output, report.figures)
end
function reset_report!(report)
report.rich_output = ""
report.figures = String[]
end
unwrap_load_err(err) = return err
unwrap_load_err(err::LoadError) = return err.error
# https://stackoverflow.com/a/33925425/12113178
remove_ansi_control_chars(s) = replace(s, r"(\x9B|\x1B\[)[0-?]*[ -\/]*[@-~]" => "")
function eval_chunk(doc::WeaveDoc, chunk::CodeChunk, report::Report, mod::Module)
if !chunk.options[:eval]
chunk.output = ""
chunk.options[:fig] = false
return chunk
end
execute_prehooks!(chunk)
report.fignum = 1
report.cur_chunk = chunk
if hasproperty(report.format, :out_width) && isnothing(chunk.options[:out_width])
chunk.options[:out_width] = report.format.out_width
end
chunk.result = run_code(doc, chunk, report, mod)
execute_posthooks!(chunk)
return chunk.options[:term] ? collect_term_results(chunk) :
chunk.options[:hold] ? collect_hold_results(chunk) :
collect_results(chunk)
end
# Hooks to run before and after chunks, this is form IJulia,
const preexecution_hooks = Function[]
push_preexecution_hook!(f::Function) = push!(preexecution_hooks, f)
function pop_preexecution_hook!(f::Function)
i = findfirst(x -> x == f, preexecution_hooks)
isnothing(i) && error("this function has not been registered in the pre-execution hook yet")
return splice!(preexecution_hooks, i)
end
function execute_prehooks!(chunk::CodeChunk)
for prehook in preexecution_hooks
Base.invokelatest(prehook, chunk)
end
end
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
"""
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)
isnothing(ext) && (ext = chunk.options[:fig_ext])
isnothing(fignum) && (fignum = report.fignum)
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 set_rc_params(doc::WeaveDoc, fig_path, fig_ext)
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)
content = ""
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 !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_term_results(chunk::CodeChunk)
output = ""
prompt = chunk.options[:prompt]
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.output = output
output = ""
rchunk.figures = r.figures
push!(result_chunks, rchunk)
end
end
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 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

View File

@ -1,72 +0,0 @@
# 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[])

35
src/winston.jl Normal file
View File

@ -0,0 +1,35 @@
import Winston
function Base.display(report::Report, m::MIME"image/png", data)
chunk = report.cur_chunk
full_name, rel_name = get_figname(report, chunk)
docformat = formats[report.formatdict[:doctype]]
#Add to results for term chunks and store otherwise
if chunk[:term]
chunk[:figure] = [rel_name]
if report.term_state == :text
report.cur_result *= "\n" * report.formatdict[:codeend] * "\n"
end
report.cur_result *= formatfigures(chunk, docformat)
report.term_state = :fig
chunk[:figure] = String[]
else
push!(report.figures, rel_name)
end
vector_fmts = [".pdf", ".svg"]
#Don't use dpi for vector formats
if chunk[:fig_ext] in vector_fmts
Winston.savefig(data, full_name, width=chunk[:fig_width]*100, height=chunk[:fig_height]*100)
else
Winston.savefig(data, full_name, width=chunk[:fig_width]*chunk[:dpi], height=chunk[:fig_height]*chunk[:dpi])
end
report.fignum += 1
end

View File

@ -1,19 +0,0 @@
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

View File

@ -1,76 +0,0 @@
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

View File

@ -1,11 +0,0 @@
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,550 +0,0 @@
<style type="text/css">
@font-face {
font-style: normal;
font-weight: 300;
}
@font-face {
font-style: normal;
font-weight: 400;
}
@font-face {
font-style: normal;
font-weight: 600;
}
html {
font-family: sans-serif; /* 1 */
-ms-text-size-adjust: 100%; /* 2 */
-webkit-text-size-adjust: 100%; /* 2 */
}
body {
margin: 0;
}
article,
aside,
details,
figcaption,
figure,
footer,
header,
hgroup,
main,
menu,
nav,
section,
summary {
display: block;
}
audio,
canvas,
progress,
video {
display: inline-block; /* 1 */
vertical-align: baseline; /* 2 */
}
audio:not([controls]) {
display: none;
height: 0;
}
[hidden],
template {
display: none;
}
a:active,
a:hover {
outline: 0;
}
abbr[title] {
border-bottom: 1px dotted;
}
b,
strong {
font-weight: bold;
}
dfn {
font-style: italic;
}
h1 {
font-size: 2em;
margin: 0.67em 0;
}
mark {
background: #ff0;
color: #000;
}
small {
font-size: 80%;
}
sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sup {
top: -0.5em;
}
sub {
bottom: -0.25em;
}
img {
border: 0;
}
svg:not(:root) {
overflow: hidden;
}
figure {
margin: 1em 40px;
}
hr {
-moz-box-sizing: content-box;
box-sizing: content-box;
height: 0;
}
pre {
overflow: auto;
}
code,
kbd,
pre,
samp {
font-family: monospace, monospace;
font-size: 1em;
}
button,
input,
optgroup,
select,
textarea {
color: inherit; /* 1 */
font: inherit; /* 2 */
margin: 0; /* 3 */
}
button {
overflow: visible;
}
button,
select {
text-transform: none;
}
button,
html input[type="button"], /* 1 */
input[type="reset"],
input[type="submit"] {
-webkit-appearance: button; /* 2 */
cursor: pointer; /* 3 */
}
button[disabled],
html input[disabled] {
cursor: default;
}
button::-moz-focus-inner,
input::-moz-focus-inner {
border: 0;
padding: 0;
}
input {
line-height: normal;
}
input[type="checkbox"],
input[type="radio"] {
box-sizing: border-box; /* 1 */
padding: 0; /* 2 */
}
input[type="number"]::-webkit-inner-spin-button,
input[type="number"]::-webkit-outer-spin-button {
height: auto;
}
input[type="search"] {
-webkit-appearance: textfield; /* 1 */
-moz-box-sizing: content-box;
-webkit-box-sizing: content-box; /* 2 */
box-sizing: content-box;
}
input[type="search"]::-webkit-search-cancel-button,
input[type="search"]::-webkit-search-decoration {
-webkit-appearance: none;
}
fieldset {
border: 1px solid #c0c0c0;
margin: 0 2px;
padding: 0.35em 0.625em 0.75em;
}
legend {
border: 0; /* 1 */
padding: 0; /* 2 */
}
textarea {
overflow: auto;
}
optgroup {
font-weight: bold;
}
table {
font-family: monospace, monospace;
font-size : 0.8em;
border-collapse: collapse;
border-spacing: 0;
}
td,
th {
padding: 0;
}
thead th {
border-bottom: 1px solid black;
background-color: white;
}
tr:nth-child(odd){
background-color: rgb(248,248,248);
}
/*
* Skeleton V2.0.4
* Copyright 2014, Dave Gamache
* www.getskeleton.com
* Free to use under the MIT license.
* http://www.opensource.org/licenses/mit-license.php
* 12/29/2014
*/
.container {
position: relative;
width: 100%;
max-width: 960px;
margin: 0 auto;
padding: 0 20px;
box-sizing: border-box; }
.column,
.columns {
width: 100%;
float: left;
box-sizing: border-box; }
@media (min-width: 400px) {
.container {
width: 85%;
padding: 0; }
}
@media (min-width: 550px) {
.container {
width: 80%; }
.column,
.columns {
margin-left: 4%; }
.column:first-child,
.columns:first-child {
margin-left: 0; }
.one.column,
.one.columns { width: 4.66666666667%; }
.two.columns { width: 13.3333333333%; }
.three.columns { width: 22%; }
.four.columns { width: 30.6666666667%; }
.five.columns { width: 39.3333333333%; }
.six.columns { width: 48%; }
.seven.columns { width: 56.6666666667%; }
.eight.columns { width: 65.3333333333%; }
.nine.columns { width: 74.0%; }
.ten.columns { width: 82.6666666667%; }
.eleven.columns { width: 91.3333333333%; }
.twelve.columns { width: 100%; margin-left: 0; }
.one-third.column { width: 30.6666666667%; }
.two-thirds.column { width: 65.3333333333%; }
.one-half.column { width: 48%; }
/* Offsets */
.offset-by-one.column,
.offset-by-one.columns { margin-left: 8.66666666667%; }
.offset-by-two.column,
.offset-by-two.columns { margin-left: 17.3333333333%; }
.offset-by-three.column,
.offset-by-three.columns { margin-left: 26%; }
.offset-by-four.column,
.offset-by-four.columns { margin-left: 34.6666666667%; }
.offset-by-five.column,
.offset-by-five.columns { margin-left: 43.3333333333%; }
.offset-by-six.column,
.offset-by-six.columns { margin-left: 52%; }
.offset-by-seven.column,
.offset-by-seven.columns { margin-left: 60.6666666667%; }
.offset-by-eight.column,
.offset-by-eight.columns { margin-left: 69.3333333333%; }
.offset-by-nine.column,
.offset-by-nine.columns { margin-left: 78.0%; }
.offset-by-ten.column,
.offset-by-ten.columns { margin-left: 86.6666666667%; }
.offset-by-eleven.column,
.offset-by-eleven.columns { margin-left: 95.3333333333%; }
.offset-by-one-third.column,
.offset-by-one-third.columns { margin-left: 34.6666666667%; }
.offset-by-two-thirds.column,
.offset-by-two-thirds.columns { margin-left: 69.3333333333%; }
.offset-by-one-half.column,
.offset-by-one-half.columns { margin-left: 52%; }
}
html {
font-size: 62.5%; }
body {
font-size: 1.5em; /* currently ems cause chrome bug misinterpreting rems on body element */
line-height: 1.6;
font-weight: 400;
font-family: "Raleway", "HelveticaNeue", "Helvetica Neue", Helvetica, Arial, sans-serif;
color: #222; }
h1, h2, h3, h4, h5, h6 {
margin-top: 0;
margin-bottom: 2rem;
font-weight: 300; }
h1 { font-size: 3.6rem; line-height: 1.2; letter-spacing: -.1rem;}
h2 { font-size: 3.4rem; line-height: 1.25; letter-spacing: -.1rem; }
h3 { font-size: 3.2rem; line-height: 1.3; letter-spacing: -.1rem; }
h4 { font-size: 2.8rem; line-height: 1.35; letter-spacing: -.08rem; }
h5 { font-size: 2.4rem; line-height: 1.5; letter-spacing: -.05rem; }
h6 { font-size: 1.5rem; line-height: 1.6; letter-spacing: 0; }
p {
margin-top: 0; }
a {
color: #1EAEDB; }
a:hover {
color: #0FA0CE; }
.button,
button,
input[type="submit"],
input[type="reset"],
input[type="button"] {
display: inline-block;
height: 38px;
padding: 0 30px;
color: #555;
text-align: center;
font-size: 11px;
font-weight: 600;
line-height: 38px;
letter-spacing: .1rem;
text-transform: uppercase;
text-decoration: none;
white-space: nowrap;
background-color: transparent;
border-radius: 4px;
border: 1px solid #bbb;
cursor: pointer;
box-sizing: border-box; }
.button:hover,
button:hover,
input[type="submit"]:hover,
input[type="reset"]:hover,
input[type="button"]:hover,
.button:focus,
button:focus,
input[type="submit"]:focus,
input[type="reset"]:focus,
input[type="button"]:focus {
color: #333;
border-color: #888;
outline: 0; }
.button.button-primary,
button.button-primary,
input[type="submit"].button-primary,
input[type="reset"].button-primary,
input[type="button"].button-primary {
color: #FFF;
background-color: #33C3F0;
border-color: #33C3F0; }
.button.button-primary:hover,
button.button-primary:hover,
input[type="submit"].button-primary:hover,
input[type="reset"].button-primary:hover,
input[type="button"].button-primary:hover,
.button.button-primary:focus,
button.button-primary:focus,
input[type="submit"].button-primary:focus,
input[type="reset"].button-primary:focus,
input[type="button"].button-primary:focus {
color: #FFF;
background-color: #1EAEDB;
border-color: #1EAEDB; }
input[type="email"],
input[type="number"],
input[type="search"],
input[type="text"],
input[type="tel"],
input[type="url"],
input[type="password"],
textarea,
select {
height: 38px;
padding: 6px 10px; /* The 6px vertically centers text on FF, ignored by Webkit */
background-color: #fff;
border: 1px solid #D1D1D1;
border-radius: 4px;
box-shadow: none;
box-sizing: border-box; }
/* Removes awkward default styles on some inputs for iOS */
input[type="email"],
input[type="number"],
input[type="search"],
input[type="text"],
input[type="tel"],
input[type="url"],
input[type="password"],
textarea {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none; }
textarea {
min-height: 65px;
padding-top: 6px;
padding-bottom: 6px; }
input[type="email"]:focus,
input[type="number"]:focus,
input[type="search"]:focus,
input[type="text"]:focus,
input[type="tel"]:focus,
input[type="url"]:focus,
input[type="password"]:focus,
textarea:focus,
select:focus {
border: 1px solid #33C3F0;
outline: 0; }
label,
legend {
display: block;
margin-bottom: .5rem;
font-weight: 600; }
fieldset {
padding: 0;
border-width: 0; }
input[type="checkbox"],
input[type="radio"] {
display: inline; }
label > .label-body {
display: inline-block;
margin-left: .5rem;
font-weight: normal; }
ul {
list-style: circle inside; }
ol {
list-style: decimal inside; }
ol, ul {
padding-left: 0;
margin-top: 0; }
ul ul,
ul ol,
ol ol,
ol ul {
margin: 1.5rem 0 1.5rem 3rem;
font-size: 90%; }
li {
margin-bottom: 1rem; }
th,
td {
padding: 12px 15px;
text-align: left;
border-bottom: 1px solid #E1E1E1; }
th:first-child,
td:first-child {
padding-left: 0; }
th:last-child,
td:last-child {
padding-right: 0; }
button,
.button {
margin-bottom: 1rem; }
input,
textarea,
select,
fieldset {
margin-bottom: 1.5rem; }
pre,
blockquote,
dl,
figure,
table,
p,
ul,
ol,
form {
margin-bottom: 2.5rem; }
.u-full-width {
width: 100%;
box-sizing: border-box; }
.u-max-full-width {
max-width: 100%;
box-sizing: border-box; }
.u-pull-right {
float: right; }
.u-pull-left {
float: left; }
hr {
margin-top: 3rem;
margin-bottom: 3.5rem;
border-width: 0;
border-top: 1px solid #E1E1E1; }
.container:after,
.row:after,
.u-cf {
content: "";
display: table;
clear: both; }
pre {
display: block;
padding: 9.5px;
margin: 0 0 10px;
font-size: 13px;
line-height: 1.42857143;
color: #333;
word-break: break-all;
word-wrap: break-word;
background-color: #ffffff;
border: 1px solid #ccc;
border-radius: 4px;
}
pre.sourceCode.julia {
display: block;
padding: 9.5px;
margin: 0 0 10px;
font-size: 12px;
line-height: 1.42857143;
color: #333;
word-break: break-all;
word-wrap: break-word;
background-color: #f5f5f5;
border: 1px solid #ccc;
border-radius: 4px;
}
pre.julia-error {
color : red
}
code,
kbd,
pre,
samp {
font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
}
code {
background-color: #ffffff;
border-radius: 4px;
}
code.sourceCode.julia {
background-color: #f5f5f5;
border-radius: 4px;
}
@media (min-width: 400px) {}
@media (min-width: 550px) {}
@media (min-width: 750px) {}
@media (min-width: 1000px) {}
@media (min-width: 1200px) {}
h1.title {margin-top : 20px}
img {max-width : 100%}
</style>

View File

@ -1,538 +0,0 @@
@font-face {
font-style: normal;
font-weight: 300;
}
@font-face {
font-style: normal;
font-weight: 400;
}
@font-face {
font-style: normal;
font-weight: 600;
}
html {
font-family: sans-serif; /* 1 */
-ms-text-size-adjust: 100%; /* 2 */
-webkit-text-size-adjust: 100%; /* 2 */
}
body {
margin: 0;
}
article,
aside,
details,
figcaption,
figure,
footer,
header,
hgroup,
main,
menu,
nav,
section,
summary {
display: block;
}
audio,
canvas,
progress,
video {
display: inline-block; /* 1 */
vertical-align: baseline; /* 2 */
}
audio:not([controls]) {
display: none;
height: 0;
}
[hidden],
template {
display: none;
}
a:active,
a:hover {
outline: 0;
}
abbr[title] {
border-bottom: 1px dotted;
}
b,
strong {
font-weight: bold;
}
dfn {
font-style: italic;
}
h1 {
font-size: 2em;
margin: 0.67em 0;
}
mark {
background: #ff0;
color: #000;
}
small {
font-size: 80%;
}
sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sup {
top: -0.5em;
}
sub {
bottom: -0.25em;
}
img {
border: 0;
}
svg:not(:root) {
overflow: hidden;
}
figure {
margin: 1em 40px;
}
hr {
-moz-box-sizing: content-box;
box-sizing: content-box;
height: 0;
}
pre {
overflow: auto;
}
code,
kbd,
pre,
samp {
font-family: monospace, monospace;
font-size: 1em;
}
button,
input,
optgroup,
select,
textarea {
color: inherit; /* 1 */
font: inherit; /* 2 */
margin: 0; /* 3 */
}
button {
overflow: visible;
}
button,
select {
text-transform: none;
}
button,
html input[type="button"], /* 1 */
input[type="reset"],
input[type="submit"] {
-webkit-appearance: button; /* 2 */
cursor: pointer; /* 3 */
}
button[disabled],
html input[disabled] {
cursor: default;
}
button::-moz-focus-inner,
input::-moz-focus-inner {
border: 0;
padding: 0;
}
input {
line-height: normal;
}
input[type="checkbox"],
input[type="radio"] {
box-sizing: border-box; /* 1 */
padding: 0; /* 2 */
}
input[type="number"]::-webkit-inner-spin-button,
input[type="number"]::-webkit-outer-spin-button {
height: auto;
}
input[type="search"] {
-webkit-appearance: textfield; /* 1 */
-moz-box-sizing: content-box;
-webkit-box-sizing: content-box; /* 2 */
box-sizing: content-box;
}
input[type="search"]::-webkit-search-cancel-button,
input[type="search"]::-webkit-search-decoration {
-webkit-appearance: none;
}
fieldset {
border: 1px solid #c0c0c0;
margin: 0 2px;
padding: 0.35em 0.625em 0.75em;
}
legend {
border: 0; /* 1 */
padding: 0; /* 2 */
}
textarea {
overflow: auto;
}
optgroup {
font-weight: bold;
}
table {
font-family: monospace, monospace;
font-size : 0.8em;
border-collapse: collapse;
border-spacing: 0;
}
td,
th {
padding: 0;
}
thead th {
border-bottom: 1px solid black;
background-color: white;
}
tr:nth-child(odd){
background-color: rgb(248,248,248);
}
/*
* Skeleton V2.0.4
* Copyright 2014, Dave Gamache
* www.getskeleton.com
* Free to use under the MIT license.
* http://www.opensource.org/licenses/mit-license.php
* 12/29/2014
*/
.container {
position: relative;
width: 100%;
max-width: 960px;
margin: 0 auto;
padding: 0 20px;
box-sizing: border-box; }
.column,
.columns {
width: 100%;
float: left;
box-sizing: border-box; }
@media (min-width: 400px) {
.container {
width: 85%;
padding: 0; }
}
@media (min-width: 550px) {
.container {
width: 80%; }
.column,
.columns {
margin-left: 4%; }
.column:first-child,
.columns:first-child {
margin-left: 0; }
.one.column,
.one.columns { width: 4.66666666667%; }
.two.columns { width: 13.3333333333%; }
.three.columns { width: 22%; }
.four.columns { width: 30.6666666667%; }
.five.columns { width: 39.3333333333%; }
.six.columns { width: 48%; }
.seven.columns { width: 56.6666666667%; }
.eight.columns { width: 65.3333333333%; }
.nine.columns { width: 74.0%; }
.ten.columns { width: 82.6666666667%; }
.eleven.columns { width: 91.3333333333%; }
.twelve.columns { width: 100%; margin-left: 0; }
.one-third.column { width: 30.6666666667%; }
.two-thirds.column { width: 65.3333333333%; }
.one-half.column { width: 48%; }
/* Offsets */
.offset-by-one.column,
.offset-by-one.columns { margin-left: 8.66666666667%; }
.offset-by-two.column,
.offset-by-two.columns { margin-left: 17.3333333333%; }
.offset-by-three.column,
.offset-by-three.columns { margin-left: 26%; }
.offset-by-four.column,
.offset-by-four.columns { margin-left: 34.6666666667%; }
.offset-by-five.column,
.offset-by-five.columns { margin-left: 43.3333333333%; }
.offset-by-six.column,
.offset-by-six.columns { margin-left: 52%; }
.offset-by-seven.column,
.offset-by-seven.columns { margin-left: 60.6666666667%; }
.offset-by-eight.column,
.offset-by-eight.columns { margin-left: 69.3333333333%; }
.offset-by-nine.column,
.offset-by-nine.columns { margin-left: 78.0%; }
.offset-by-ten.column,
.offset-by-ten.columns { margin-left: 86.6666666667%; }
.offset-by-eleven.column,
.offset-by-eleven.columns { margin-left: 95.3333333333%; }
.offset-by-one-third.column,
.offset-by-one-third.columns { margin-left: 34.6666666667%; }
.offset-by-two-thirds.column,
.offset-by-two-thirds.columns { margin-left: 69.3333333333%; }
.offset-by-one-half.column,
.offset-by-one-half.columns { margin-left: 52%; }
}
html {
font-size: 62.5%; }
body {
font-size: 1.5em; /* currently ems cause chrome bug misinterpreting rems on body element */
line-height: 1.6;
font-weight: 400;
font-family: "Raleway", "HelveticaNeue", "Helvetica Neue", Helvetica, Arial, sans-serif;
color: #222; }
h1, h2, h3, h4, h5, h6 {
margin-top: 0;
margin-bottom: 2rem;
font-weight: 300; }
h1 { font-size: 3.6rem; line-height: 1.2; letter-spacing: -.1rem;}
h2 { font-size: 3.4rem; line-height: 1.25; letter-spacing: -.1rem; }
h3 { font-size: 3.2rem; line-height: 1.3; letter-spacing: -.1rem; }
h4 { font-size: 2.8rem; line-height: 1.35; letter-spacing: -.08rem; }
h5 { font-size: 2.4rem; line-height: 1.5; letter-spacing: -.05rem; }
h6 { font-size: 1.5rem; line-height: 1.6; letter-spacing: 0; }
p {
margin-top: 0; }
a {
color: #1EAEDB; }
a:hover {
color: #0FA0CE; }
.button,
button,
input[type="submit"],
input[type="reset"],
input[type="button"] {
display: inline-block;
height: 38px;
padding: 0 30px;
color: #555;
text-align: center;
font-size: 11px;
font-weight: 600;
line-height: 38px;
letter-spacing: .1rem;
text-transform: uppercase;
text-decoration: none;
white-space: nowrap;
background-color: transparent;
border-radius: 4px;
border: 1px solid #bbb;
cursor: pointer;
box-sizing: border-box; }
.button:hover,
button:hover,
input[type="submit"]:hover,
input[type="reset"]:hover,
input[type="button"]:hover,
.button:focus,
button:focus,
input[type="submit"]:focus,
input[type="reset"]:focus,
input[type="button"]:focus {
color: #333;
border-color: #888;
outline: 0; }
.button.button-primary,
button.button-primary,
input[type="submit"].button-primary,
input[type="reset"].button-primary,
input[type="button"].button-primary {
color: #FFF;
background-color: #33C3F0;
border-color: #33C3F0; }
.button.button-primary:hover,
button.button-primary:hover,
input[type="submit"].button-primary:hover,
input[type="reset"].button-primary:hover,
input[type="button"].button-primary:hover,
.button.button-primary:focus,
button.button-primary:focus,
input[type="submit"].button-primary:focus,
input[type="reset"].button-primary:focus,
input[type="button"].button-primary:focus {
color: #FFF;
background-color: #1EAEDB;
border-color: #1EAEDB; }
input[type="email"],
input[type="number"],
input[type="search"],
input[type="text"],
input[type="tel"],
input[type="url"],
input[type="password"],
textarea,
select {
height: 38px;
padding: 6px 10px; /* The 6px vertically centers text on FF, ignored by Webkit */
background-color: #fff;
border: 1px solid #D1D1D1;
border-radius: 4px;
box-shadow: none;
box-sizing: border-box; }
/* Removes awkward default styles on some inputs for iOS */
input[type="email"],
input[type="number"],
input[type="search"],
input[type="text"],
input[type="tel"],
input[type="url"],
input[type="password"],
textarea {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none; }
textarea {
min-height: 65px;
padding-top: 6px;
padding-bottom: 6px; }
input[type="email"]:focus,
input[type="number"]:focus,
input[type="search"]:focus,
input[type="text"]:focus,
input[type="tel"]:focus,
input[type="url"]:focus,
input[type="password"]:focus,
textarea:focus,
select:focus {
border: 1px solid #33C3F0;
outline: 0; }
label,
legend {
display: block;
margin-bottom: .5rem;
font-weight: 600; }
fieldset {
padding: 0;
border-width: 0; }
input[type="checkbox"],
input[type="radio"] {
display: inline; }
label > .label-body {
display: inline-block;
margin-left: .5rem;
font-weight: normal; }
ul {
list-style: circle; }
ol {
list-style: decimal; }
ul ul,
ul ol,
ol ol,
ol ul {
margin: 1.5rem 0 1.5rem 3rem;
font-size: 90%; }
li > p {margin : 0;}
th,
td {
padding: 12px 15px;
text-align: left;
border-bottom: 1px solid #E1E1E1; }
th:first-child,
td:first-child {
padding-left: 0; }
th:last-child,
td:last-child {
padding-right: 0; }
button,
.button {
margin-bottom: 1rem; }
input,
textarea,
select,
fieldset {
margin-bottom: 1.5rem; }
pre,
blockquote,
dl,
figure,
table,
p,
ul,
ol,
form {
margin-bottom: 1.0rem; }
.u-full-width {
width: 100%;
box-sizing: border-box; }
.u-max-full-width {
max-width: 100%;
box-sizing: border-box; }
.u-pull-right {
float: right; }
.u-pull-left {
float: left; }
hr {
margin-top: 3rem;
margin-bottom: 3.5rem;
border-width: 0;
border-top: 1px solid #E1E1E1; }
.container:after,
.row:after,
.u-cf {
content: "";
display: table;
clear: both; }
pre {
display: block;
padding: 9.5px;
margin: 0 0 10px;
font-size: 13px;
line-height: 1.42857143;
word-break: break-all;
word-wrap: break-word;
border: 1px solid #ccc;
border-radius: 4px;
}
pre.hljl {
margin: 0 0 10px;
display: block;
background: #f5f5f5;
border-radius: 4px;
padding : 5px;
}
pre.output {
background: #ffffff;
}
pre.code {
background: #ffffff;
}
pre.julia-error {
color : red
}
code,
kbd,
pre,
samp {
font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
font-size: 0.9em;
}
@media (min-width: 400px) {}
@media (min-width: 550px) {}
@media (min-width: 750px) {}
@media (min-width: 1000px) {}
@media (min-width: 1200px) {}
h1.title {margin-top : 20px}
img {max-width : 100%}
div.title {text-align: center;}

View File

@ -1,50 +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>
{{{ :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

@ -1,45 +0,0 @@
\documentclass[12pt,a4paper]{article}
\usepackage[a4paper,text={16.5cm,25.2cm},centering]{geometry}
\usepackage{lmodern}
\usepackage{amssymb,amsmath}
\usepackage{bm}
\usepackage{graphicx}
\usepackage{microtype}
\usepackage{hyperref}
{{#:tex_deps}}
{{{ :tex_deps }}}
{{/:tex_deps}}
\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}}\maketitle{{/:title}}
{{{ :body }}}
\end{document}

View File

@ -1,96 +0,0 @@
<!DOCTYPE html>
<html$if(lang)$ lang="$lang$"$endif$$if(dir)$ dir="$dir$"$endif$>
<head>
<meta charset="utf-8">
<meta name="generator" content="pandoc">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
$for(author-meta)$
<meta name="author" content="$author-meta$">
$endfor$
$if(date-meta)$
<meta name="dcterms.date" content="$date-meta$">
$endif$
$if(keywords)$
<meta name="keywords" content="$for(keywords)$$keywords$$sep$, $endfor$">
$endif$
<title>$if(title-prefix)$$title-prefix$ $endif$$pagetitle$</title>
<!-- TODO check if math works with plotly -->
<!-- Need to load plotly before Mathjax or pandoc equations don't work -->
$headerscript$
$if(math)$
<script type="text/javascript">
var fileref=document.createElement('script')
fileref.setAttribute("type","text/javascript")
fileref.setAttribute("src", "http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML")
document.getElementsByTagName("head")[0].appendChild(fileref)
</script>
$endif$
$for(header-includes)$
$header-includes$
$endfor$
$highlight_stylesheet$
$if(highlighting-css)$
<style type="text/css">
$highlighting-css$
</style>
$endif$
$for(css)$
<link rel="stylesheet" href="$css$">
$endfor$
</head>
<body>
<div class ="container">
<div class = "row">
<div class = "col-md-12 twelve columns">
$for(include-before)$
$include-before$
$endfor$
$if(title)$
<h1 class="title">$title$</h1>
$if(subtitle)$
<h1 class="subtitle">$subtitle$</h1>
$endif$
<p><strong>Author:</strong>
$for(author)$
$author$
$endfor$
<br/>
$if(date)$
<strong>Date: </strong>$date$
$endif$
</p>
$endif$
$if(toc)$
<nav id="$idprefix$TOC">
$toc$
</nav>
$endif$
$body$
$for(include-after)$
$include-after$
$endfor$
<HR/>
<div class="footer"><p>
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>
</div>
</div>
</body>
</html>

View File

@ -1,3 +0,0 @@
\usepackage[a4paper,text={16.5cm,25.2cm},centering]{geometry}

View File

@ -1,28 +0,0 @@
# 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)
rm("documents/chunk_options.md")
weave("documents/chunk_options.noweb", cache=:all)
cached_result = read("documents/chunk_options.md", String)
@test result == cached_result
# cache = :user
isdir("documents/cache") && rm("documents/cache", recursive = true)
out = "documents/chunk_cache.md"
Weave.weave("documents/chunk_cache.noweb", cache=:user);
result = read(out, String)
rm(out)
Weave.weave("documents/chunk_cache.noweb", cache=:user);
cached_result = read(out, String)
@test result == cached_result
# cache = :all
isdir("documents/cache") && rm("documents/cache", recursive = true)
out = "documents/chunk_cache.md"
Weave.weave("documents/chunk_cache.noweb", cache=:all);
result = read(out, String)
rm(out)
Weave.weave("documents/chunk_cache.noweb", cache=:all);
cached_result = read(out, String)
@test result == cached_result

23
test/chunk_options.jl Normal file
View File

@ -0,0 +1,23 @@
using Weave
using Base.Test
#Test chunk options and output formats
weave("documents/chunk_options.noweb", plotlib=nothing)
result = readall(open("documents/chunk_options.md"))
ref = readall(open("documents/chunk_options_ref.md"))
@test result == ref
weave("documents/chunk_options.noweb", doctype="tex", plotlib=nothing)
result = readall(open("documents/chunk_options.tex"))
ref = readall(open("documents/chunk_options_ref.tex"))
@test result == ref
weave("documents/chunk_options.noweb", doctype="texminted", plotlib=nothing)
result = readall(open("documents/chunk_options.tex"))
ref = readall(open("documents/chunk_options_ref.texminted"))
@test result == ref
weave("documents/chunk_options.noweb", doctype="rst", plotlib=nothing)
result = readall(open("documents/chunk_options.rst"))
ref = readall(open("documents/chunk_options_ref.rst"))
@test result == ref

View File

@ -1,37 +0,0 @@
<<term=true>>=
y= [2, 5, 12]
@
Some text `j print(10)` and continues with another inline code `j y`.
<<term=true; cache=true>>=
y= [2, 5, 12]
@
<<>>=
x = [12, 10]
println(y)
println(x)
@
<<cache=true>>=
x = [12, 10]
println(y)
println(x)
@
<<>>=
y = 1:5
println(y)
@
`j y`
<<cache=true>>=
y = 1:5
println(y)
@
Some text in the end

View File

@ -1,179 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"source": [
""
],
"metadata": {}
},
{
"outputs": [],
"cell_type": "code",
"source": [
"y= [2, 5, 12]"
],
"metadata": {},
"execution_count": null
},
{
"cell_type": "markdown",
"source": [
""
],
"metadata": {}
},
{
"outputs": [],
"cell_type": "code",
"source": [
"x = [12, 10]\nprintln(y)\nprintln(x)"
],
"metadata": {},
"execution_count": null
},
{
"cell_type": "markdown",
"source": [
""
],
"metadata": {}
},
{
"outputs": [],
"cell_type": "code",
"source": [
"println(\"Results without code\")\nprintln(x)"
],
"metadata": {},
"execution_count": null
},
{
"cell_type": "markdown",
"source": [
""
],
"metadata": {}
},
{
"outputs": [],
"cell_type": "code",
"source": [
"y = randn(5)\nprintln(\"Don't eval, but show code\")"
],
"metadata": {},
"execution_count": null
},
{
"cell_type": "markdown",
"source": [
""
],
"metadata": {}
},
{
"outputs": [],
"cell_type": "code",
"source": [
"y = 1:5\nprintln(y)"
],
"metadata": {},
"execution_count": null
},
{
"cell_type": "markdown",
"source": [
""
],
"metadata": {}
},
{
"outputs": [],
"cell_type": "code",
"source": [
"a = \"Don't print me\"\nprintln(a)"
],
"metadata": {},
"execution_count": null
},
{
"cell_type": "markdown",
"source": [
""
],
"metadata": {}
},
{
"outputs": [],
"cell_type": "code",
"source": [
"println(\"No markup for results.\")"
],
"metadata": {},
"execution_count": null
},
{
"cell_type": "markdown",
"source": [
"Test wrapping:"
],
"metadata": {}
},
{
"outputs": [],
"cell_type": "code",
"source": [
"println(collect(0:10:1000))"
],
"metadata": {},
"execution_count": null
},
{
"cell_type": "markdown",
"source": [
""
],
"metadata": {}
},
{
"outputs": [],
"cell_type": "code",
"source": [
"println(collect(0:10:1000))"
],
"metadata": {},
"execution_count": null
},
{
"cell_type": "markdown",
"source": [
""
],
"metadata": {}
},
{
"outputs": [],
"cell_type": "code",
"source": [
"println(collect(0:10:1000))"
],
"metadata": {},
"execution_count": null
}
],
"nbformat_minor": 2,
"metadata": {
"language_info": {
"file_extension": ".jl",
"mimetype": "application/julia",
"name": "julia",
"version": "0.5.0"
},
"kernelspec": {
"name": "julia-0.5",
"display_name": "Julia 0.5.0",
"language": "julia"
}
},
"nbformat": 4
}

View File

@ -1,66 +0,0 @@
#+ term=true
y= [2, 5, 12]
#+ term=true
x = 1:10
d = Dict("Weave" => "testing")
y = [2, 4 ,8]
#+
x = [12, 10]
println(y)
println(x)
#+ echo=false
println("Results without code")
println(x)
#+ eval=false; tangle=false
y = randn(5)
println("Don't eval, but show code")
#+
y = 1:5
println(y)
#+ results="hidden"
a = "Don't print me"
println(a)
#+ results="as_is"
println("No markup for results.")
#'
#'
#' Test wrapping:
#'
#+
println(collect(0:10:1000))
#+ wrap=false
println(collect(0:10:1000))
#+ line_width=60
println(collect(0:10:1000))

View File

@ -3,12 +3,6 @@
y= [2, 5, 12]
@
<<term=true>>=
x = 1:10
d = Dict("Weave" => "testing")
y = [2, 4 ,8]
@
<<>>=
x = [12, 10]
println(y)
@ -22,7 +16,7 @@ println(x)
@
<<eval=false; tangle=false>>=
<<eval=false>>=
y = randn(5)
println("Don't eval, but show code")
@
@ -41,17 +35,3 @@ println(a)
<<results="as_is">>=
println("No markup for results.")
@
Test wrapping:
<<>>=
println(collect(0:10:1000))
@
<<wrap=false>>=
println(collect(0:10:1000))
@
<<line_width=60>>=
println(collect(0:10:1000))
@

View File

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

View File

@ -1,3 +1,5 @@
~~~~{.julia}
julia> y= [2, 5, 12]
3-element Array{Int64,1}:
@ -9,75 +11,55 @@ julia> y= [2, 5, 12]
~~~~{.julia}
julia> x = 1:10
1:10
julia> d = Dict("Weave" => "testing")
Dict{String,String} with 1 entry:
"Weave" => "testing"
julia> y = [2, 4 ,8]
3-element Array{Int64,1}:
2
4
8
~~~~~~~~~~~~~
~~~~{.julia}
x = [12, 10]
println(y)
~~~~~~~~~~~~~
~~~~
[2, 4, 8]
~~~~
~~~~{.julia}
println(x)
~~~~~~~~~~~~~
~~~~
[12, 10]
~~~~
~~~~{.julia}
[2,5,12]
[12,10]
~~~~~~~~~~~~~
~~~~
Results without code
~~~~
~~~~
[12, 10]
~~~~
~~~~{.julia}
Results without code
[12,10]
~~~~~~~~~~~~~
~~~~{.julia}
y = randn(5)
println("Don't eval, but show code")
~~~~~~~~~~~~~
~~~~{.julia}
y = 1:5
println(y)
~~~~~~~~~~~~~
~~~~
~~~~{.julia}
1:5
~~~~
~~~~~~~~~~~~~
@ -88,61 +70,13 @@ println(a)
~~~~{.julia}
println("No markup for results.")
~~~~~~~~~~~~~
No markup for results.
Test wrapping:
~~~~{.julia}
println(collect(0:10:1000))
~~~~~~~~~~~~~
~~~~
[0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160,
170, 180, 190, 200, 210, 220, 230, 240, 250, 260, 270, 280, 290, 300, 310,
320, 330, 340, 350, 360, 370, 380, 390, 400, 410, 420, 430, 440, 450, 460,
470, 480, 490, 500, 510, 520, 530, 540, 550, 560, 570, 580, 590, 600, 610,
620, 630, 640, 650, 660, 670, 680, 690, 700, 710, 720, 730, 740, 750, 760,
770, 780, 790, 800, 810, 820, 830, 840, 850, 860, 870, 880, 890, 900, 910,
920, 930, 940, 950, 960, 970, 980, 990, 1000]
~~~~
~~~~{.julia}
println(collect(0:10:1000))
~~~~~~~~~~~~~
~~~~
[0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160, 170, 180, 190, 200, 210, 220, 230, 240, 250, 260, 270, 280, 290, 300, 310, 320, 330, 340, 350, 360, 370, 380, 390, 400, 410, 420, 430, 440, 450, 460, 470, 480, 490, 500, 510, 520, 530, 540, 550, 560, 570, 580, 590, 600, 610, 620, 630, 640, 650, 660, 670, 680, 690, 700, 710, 720, 730, 740, 750, 760, 770, 780, 790, 800, 810, 820, 830, 840, 850, 860, 870, 880, 890, 900, 910, 920, 930, 940, 950, 960, 970, 980, 990, 1000]
~~~~
~~~~{.julia}
println(collect(0:10:1000))
~~~~~~~~~~~~~
~~~~
[0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130,
140, 150, 160, 170, 180, 190, 200, 210, 220, 230, 240, 250,
260, 270, 280, 290, 300, 310, 320, 330, 340, 350, 360, 370,
380, 390, 400, 410, 420, 430, 440, 450, 460, 470, 480, 490,
500, 510, 520, 530, 540, 550, 560, 570, 580, 590, 600, 610,
620, 630, 640, 650, 660, 670, 680, 690, 700, 710, 720, 730,
740, 750, 760, 770, 780, 790, 800, 810, 820, 830, 840, 850,
860, 870, 880, 890, 900, 910, 920, 930, 940, 950, 960, 970,
980, 990, 1000]
~~~~

View File

@ -1,11 +1,13 @@
.. code-block:: julia
julia> y= [2, 5, 12]
3-element Array{Int64,1}:
2
5
12
julia> y= [2, 5, 12]
3-element Array{Int64,1}:
2
5
12
@ -16,25 +18,13 @@ julia> y= [2, 5, 12]
x = [12, 10]
println(y)
::
[2,5,12]
.. code-block:: julia
println(x)
::
[2,5,12]
[12,10]
@ -46,12 +36,6 @@ julia> y= [2, 5, 12]
::
Results without code
::
[12,10]
@ -102,63 +86,6 @@ julia> y= [2, 5, 12]
No markup for results.
Test wrapping:
.. code-block:: julia
println(collect(0:10:1000))
::
[0,10,20,30,40,50,60,70,80,90,100,110,120,130,140,150,160,170,180,190,200,2
10,220,230,240,250,260,270,280,290,300,310,320,330,340,350,360,370,380,390,
400,410,420,430,440,450,460,470,480,490,500,510,520,530,540,550,560,570,580
,590,600,610,620,630,640,650,660,670,680,690,700,710,720,730,740,750,760,77
0,780,790,800,810,820,830,840,850,860,870,880,890,900,910,920,930,940,950,9
60,970,980,990,1000]
.. code-block:: julia
println(collect(0:10:1000))
::
[0,10,20,30,40,50,60,70,80,90,100,110,120,130,140,150,160,170,180,190,200,210,220,230,240,250,260,270,280,290,300,310,320,330,340,350,360,370,380,390,400,410,420,430,440,450,460,470,480,490,500,510,520,530,540,550,560,570,580,590,600,610,620,630,640,650,660,670,680,690,700,710,720,730,740,750,760,770,780,790,800,810,820,830,840,850,860,870,880,890,900,910,920,930,940,950,960,970,980,990,1000]
.. code-block:: julia
println(collect(0:10:1000))
::
[0,10,20,30,40,50,60,70,80,90,100,110,120,130,140,150,160,17
0,180,190,200,210,220,230,240,250,260,270,280,290,300,310,32
0,330,340,350,360,370,380,390,400,410,420,430,440,450,460,47
0,480,490,500,510,520,530,540,550,560,570,580,590,600,610,62
0,630,640,650,660,670,680,690,700,710,720,730,740,750,760,77
0,780,790,800,810,820,830,840,850,860,870,880,890,900,910,92
0,930,940,950,960,970,980,990,1000]

View File

@ -1,10 +1,12 @@
\begin{juliaterm}
julia> y= [2, 5, 12]
3-element Array{Int64,1}:
2
5
12
\end{juliaterm}
@ -12,16 +14,10 @@ julia> y= [2, 5, 12]
\begin{juliacode}
x = [12, 10]
println(y)
\end{juliacode}
\begin{juliaout}
[2,5,12]
\end{juliaout}
\begin{juliacode}
println(x)
\end{juliacode}
\begin{juliaout}
[2,5,12]
[12,10]
\end{juliaout}
@ -30,9 +26,6 @@ println(x)
\begin{juliaout}
Results without code
\end{juliaout}
\begin{juliaout}
[12,10]
\end{juliaout}
@ -66,45 +59,6 @@ println(a)
\begin{juliacode}
println("No markup for results.")
\end{juliacode}
No markup for results.
Test wrapping:
\begin{juliacode}
println(collect(0:10:1000))
\end{juliacode}
\begin{juliaout}
[0,10,20,30,40,50,60,70,80,90,100,110,120,130,140,150,160,170,180,190,200,2
10,220,230,240,250,260,270,280,290,300,310,320,330,340,350,360,370,380,390,
400,410,420,430,440,450,460,470,480,490,500,510,520,530,540,550,560,570,580
,590,600,610,620,630,640,650,660,670,680,690,700,710,720,730,740,750,760,77
0,780,790,800,810,820,830,840,850,860,870,880,890,900,910,920,930,940,950,9
60,970,980,990,1000]
\end{juliaout}
\begin{juliacode}
println(collect(0:10:1000))
\end{juliacode}
\begin{juliaout}[0,10,20,30,40,50,60,70,80,90,100,110,120,130,140,150,160,170,180,190,200,210,220,230,240,250,260,270,280,290,300,310,320,330,340,350,360,370,380,390,400,410,420,430,440,450,460,470,480,490,500,510,520,530,540,550,560,570,580,590,600,610,620,630,640,650,660,670,680,690,700,710,720,730,740,750,760,770,780,790,800,810,820,830,840,850,860,870,880,890,900,910,920,930,940,950,960,970,980,990,1000]
\end{juliaout}
\begin{juliacode}
println(collect(0:10:1000))
\end{juliacode}
\begin{juliaout}
[0,10,20,30,40,50,60,70,80,90,100,110,120,130,140,150,160,17
0,180,190,200,210,220,230,240,250,260,270,280,290,300,310,32
0,330,340,350,360,370,380,390,400,410,420,430,440,450,460,47
0,480,490,500,510,520,530,540,550,560,570,580,590,600,610,62
0,630,640,650,660,670,680,690,700,710,720,730,740,750,760,77
0,780,790,800,810,820,830,840,850,860,870,880,890,900,910,92
0,930,940,950,960,970,980,990,1000]
\end{juliaout}

View File

@ -1,10 +1,12 @@
\begin{minted}[fontsize=\footnotesize, xleftmargin=0.5em, mathescape]{julia}
julia> y= [2, 5, 12]
3-element Array{Int64,1}:
2
5
12
\end{minted}
@ -12,16 +14,10 @@ julia> y= [2, 5, 12]
\begin{minted}[mathescape, fontsize=\small, xleftmargin=0.5em]{julia}
x = [12, 10]
println(y)
\end{minted}
\begin{minted}[fontsize=\small, xleftmargin=0.5em, mathescape, frame = leftline]{text}
[2,5,12]
\end{minted}
\begin{minted}[mathescape, fontsize=\small, xleftmargin=0.5em]{julia}
println(x)
\end{minted}
\begin{minted}[fontsize=\small, xleftmargin=0.5em, mathescape, frame = leftline]{text}
[2,5,12]
[12,10]
\end{minted}
@ -30,9 +26,6 @@ println(x)
\begin{minted}[fontsize=\small, xleftmargin=0.5em, mathescape, frame = leftline]{text}
Results without code
\end{minted}
\begin{minted}[fontsize=\small, xleftmargin=0.5em, mathescape, frame = leftline]{text}
[12,10]
\end{minted}
@ -66,45 +59,6 @@ println(a)
\begin{minted}[mathescape, fontsize=\small, xleftmargin=0.5em]{julia}
println("No markup for results.")
\end{minted}
No markup for results.
Test wrapping:
\begin{minted}[mathescape, fontsize=\small, xleftmargin=0.5em]{julia}
println(collect(0:10:1000))
\end{minted}
\begin{minted}[fontsize=\small, xleftmargin=0.5em, mathescape, frame = leftline]{text}
[0,10,20,30,40,50,60,70,80,90,100,110,120,130,140,150,160,170,180,190,200,2
10,220,230,240,250,260,270,280,290,300,310,320,330,340,350,360,370,380,390,
400,410,420,430,440,450,460,470,480,490,500,510,520,530,540,550,560,570,580
,590,600,610,620,630,640,650,660,670,680,690,700,710,720,730,740,750,760,77
0,780,790,800,810,820,830,840,850,860,870,880,890,900,910,920,930,940,950,9
60,970,980,990,1000]
\end{minted}
\begin{minted}[mathescape, fontsize=\small, xleftmargin=0.5em]{julia}
println(collect(0:10:1000))
\end{minted}
\begin{minted}[fontsize=\small, xleftmargin=0.5em, mathescape, frame = leftline]{text}[0,10,20,30,40,50,60,70,80,90,100,110,120,130,140,150,160,170,180,190,200,210,220,230,240,250,260,270,280,290,300,310,320,330,340,350,360,370,380,390,400,410,420,430,440,450,460,470,480,490,500,510,520,530,540,550,560,570,580,590,600,610,620,630,640,650,660,670,680,690,700,710,720,730,740,750,760,770,780,790,800,810,820,830,840,850,860,870,880,890,900,910,920,930,940,950,960,970,980,990,1000]
\end{minted}
\begin{minted}[mathescape, fontsize=\small, xleftmargin=0.5em]{julia}
println(collect(0:10:1000))
\end{minted}
\begin{minted}[fontsize=\small, xleftmargin=0.5em, mathescape, frame = leftline]{text}
[0,10,20,30,40,50,60,70,80,90,100,110,120,130,140,150,160,17
0,180,190,200,210,220,230,240,250,260,270,280,290,300,310,32
0,330,340,350,360,370,380,390,400,410,420,430,440,450,460,47
0,480,490,500,510,520,530,540,550,560,570,580,590,600,610,62
0,630,640,650,660,670,680,690,700,710,720,730,740,750,760,77
0,780,790,800,810,820,830,840,850,860,870,880,890,900,910,92
0,930,940,950,960,970,980,990,1000]
\end{minted}

View File

@ -1,125 +0,0 @@
{
"cells": [
{
"outputs": [],
"cell_type": "code",
"source": [
"y= [2, 5, 12]"
],
"metadata": {},
"execution_count": null
},
{
"outputs": [],
"cell_type": "code",
"source": [
"x = 1:10\nd = Dict(\"Weave\" => \"testing\")\ny = [2, 4 ,8]"
],
"metadata": {},
"execution_count": null
},
{
"outputs": [],
"cell_type": "code",
"source": [
"x = [12, 10]\nprintln(y)\nprintln(x)"
],
"metadata": {},
"execution_count": null
},
{
"outputs": [],
"cell_type": "code",
"source": [
"println(\"Results without code\")\nprintln(x)"
],
"metadata": {},
"execution_count": null
},
{
"outputs": [],
"cell_type": "code",
"source": [
"y = randn(5)\nprintln(\"Don't eval, but show code\")"
],
"metadata": {},
"execution_count": null
},
{
"outputs": [],
"cell_type": "code",
"source": [
"y = 1:5\nprintln(y)"
],
"metadata": {},
"execution_count": null
},
{
"outputs": [],
"cell_type": "code",
"source": [
"a = \"Don't print me\"\nprintln(a)"
],
"metadata": {},
"execution_count": null
},
{
"outputs": [],
"cell_type": "code",
"source": [
"println(\"No markup for results.\")"
],
"metadata": {},
"execution_count": null
},
{
"cell_type": "markdown",
"source": [
"Test wrapping:"
],
"metadata": {}
},
{
"outputs": [],
"cell_type": "code",
"source": [
"println(collect(0:10:1000))"
],
"metadata": {},
"execution_count": null
},
{
"outputs": [],
"cell_type": "code",
"source": [
"println(collect(0:10:1000))"
],
"metadata": {},
"execution_count": null
},
{
"outputs": [],
"cell_type": "code",
"source": [
"println(collect(0:10:1000))"
],
"metadata": {},
"execution_count": null
}
],
"nbformat_minor": 2,
"metadata": {
"language_info": {
"file_extension": ".jl",
"mimetype": "application/julia",
"name": "julia",
"version": "0.5.0"
},
"kernelspec": {
"name": "julia-0.5",
"display_name": "Julia 0.5.0",
"language": "julia"
}
},
"nbformat": 4
}

View File

@ -1,66 +0,0 @@
#+ term=true
y= [2, 5, 12]
#+ term=true
x = 1:10
d = Dict("Weave" => "testing")
y = [2, 4 ,8]
#+
x = [12, 10]
println(y)
println(x)
#+ echo=false
println("Results without code")
println(x)
#+ eval=false; tangle=false
y = randn(5)
println("Don't eval, but show code")
#+
y = 1:5
println(y)
#+ results="hidden"
a = "Don't print me"
println(a)
#+ results="as_is"
println("No markup for results.")
#'
#'
#' Test wrapping:
#'
#+
println(collect(0:10:1000))
#+ wrap=false
println(collect(0:10:1000))
#+ line_width=60
println(collect(0:10:1000))

View File

@ -1,55 +0,0 @@
```julia;term=true
y= [2, 5, 12]
```
```julia;term=true
x = 1:10
d = Dict("Weave" => "testing")
y = [2, 4 ,8]
```
```julia
x = [12, 10]
println(y)
println(x)
```
```julia;echo=false
println("Results without code")
println(x)
```
```julia;eval=false; tangle=false
y = randn(5)
println("Don't eval, but show code")
```
```julia
y = 1:5
println(y)
```
```julia;results="hidden"
a = "Don't print me"
println(a)
```
```julia;results="as_is"
println("No markup for results.")
```
Test wrapping:
```julia
println(collect(0:10:1000))
```
```julia;wrap=false
println(collect(0:10:1000))
```
```julia;line_width=60
println(collect(0:10:1000))
```

View File

@ -1,55 +0,0 @@
<<term=true>>=
y= [2, 5, 12]
@
<<term=true>>=
x = 1:10
d = Dict("Weave" => "testing")
y = [2, 4 ,8]
@
<<>>=
x = [12, 10]
println(y)
println(x)
@
<<echo=false>>=
println("Results without code")
println(x)
@
<<eval=false; tangle=false>>=
y = randn(5)
println("Don't eval, but show code")
@
<<>>=
y = 1:5
println(y)
@
<<results="hidden">>=
a = "Don't print me"
println(a)
@
<<results="as_is">>=
println("No markup for results.")
@
Test wrapping:
<<>>=
println(collect(0:10:1000))
@
<<wrap=false>>=
println(collect(0:10:1000))
@
<<line_width=60>>=
println(collect(0:10:1000))
@

View File

@ -1,66 +0,0 @@
<<>>=
y= [2, 5, 12]
@
<<>>=
x = [12, 10]
println(y)
println(x)
@
<<>>=
println("Results without code")
println(x)
@
<<>>=
y = randn(5)
println("Don't eval, but show code")
@
<<>>=
y = 1:5
println(y)
@
<<>>=
a = "Don't print me"
println(a)
@
<<>>=
println("No markup for results.")
@
Test wrapping:
<<>>=
println(collect(0:10:1000))
@
<<>>=
println(collect(0:10:1000))
@
<<>>=
println(collect(0:10:1000))
@

View File

@ -0,0 +1,29 @@
<<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.">>=
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

@ -0,0 +1,80 @@
````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.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 = linspace(0, 2π, 200)
200-element Array{Float64,1}:
0.0
0.0315738
0.0631476
0.0947214
0.126295
0.157869
0.189443
0.221017
0.25259
0.284164
6.03059
6.06217
6.09374
6.12532
6.15689
6.18846
6.22004
6.25161
6.28319
julia> plot(x=x, y = sin(x), Geom.line)
````
![](figures/gadfly_formats_test_4_1.js.svg)
````julia
julia> y = 20
20
julia> plot(x=x, y = cos(x), Geom.line)
````
![](figures/gadfly_formats_test_4_2.js.svg)
````julia
x = linspace(0, 2π, 200)
plot(x=x, y = sin(x), Geom.line)
y = 20
plot(x=x, y = cos(x), Geom.line)
````
![](figures/gadfly_formats_test_5_1.js.svg)
![](figures/gadfly_formats_test_5_2.js.svg)

View File

@ -0,0 +1,80 @@
~~~~{.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 Array{Float64,1}:
0.0
0.0315738
0.0631476
0.0947214
0.126295
0.157869
0.189443
0.221017
0.25259
0.284164
6.03059
6.06217
6.09374
6.12532
6.15689
6.18846
6.22004
6.25161
6.28319
julia> plot(x=x, y = sin(x), Geom.line)
~~~~~~~~~~~~~
![](figures/gadfly_formats_test_4_1.png)
~~~~{.julia}
julia> y = 20
20
julia> plot(x=x, y = cos(x), Geom.line)
~~~~~~~~~~~~~
![](figures/gadfly_formats_test_4_2.png)
~~~~{.julia}
x = linspace(0, 2π, 200)
plot(x=x, y = sin(x), Geom.line)
y = 20
plot(x=x, y = cos(x), Geom.line)
~~~~~~~~~~~~~
![](figures/gadfly_formats_test_5_1.png)
![](figures/gadfly_formats_test_5_2.png)

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