mirror of https://github.com/mpastell/Weave.jl
Merge branch 'master' into exportaswrapper
commit
955675d89a
|
@ -15,7 +15,7 @@ jobs:
|
|||
fail-fast: false # don't stop CI even when one of them fails
|
||||
matrix:
|
||||
version:
|
||||
- '1.4'
|
||||
- '1.5'
|
||||
os:
|
||||
- ubuntu-latest
|
||||
- macOS-latest
|
||||
|
|
|
@ -3,7 +3,7 @@ language: julia
|
|||
jobs:
|
||||
include:
|
||||
- stage: "Documentation"
|
||||
julia: 1
|
||||
julia: 1.5
|
||||
os: linux
|
||||
script:
|
||||
- julia --project=doc/ -e 'using Pkg; Pkg.develop(PackageSpec(path=pwd())); Pkg.instantiate()'
|
||||
|
|
15
NEWS.md
15
NEWS.md
|
@ -1,6 +1,19 @@
|
|||
## Release notes for Weave.jl
|
||||
|
||||
### v0.10 - 2020/05/18
|
||||
### v0.10.6 – 2020/10/03
|
||||
|
||||
improvements:
|
||||
- cleaned up chunk rendering (removed unnecessary extra newlines): #401
|
||||
- `WEAVE_ARGS` now can take arbitrary objects: https://github.com/JunoLab/Weave.jl/commit/c24a2621359b5d0af1bb6825f488e58cc11b8a9e
|
||||
- improved docs: #397 by @baggepinnen
|
||||
|
||||
bug fixes
|
||||
- fixed #398: #399
|
||||
- removed unnecessary quote for markdown output: https://github.com/JunoLab/Weave.jl/commit/a1830e05029f33195627ec5dedbacb30af23947e
|
||||
- fixed #386: #396 by @torfjelde
|
||||
|
||||
|
||||
### v0.10 – 2020/05/18
|
||||
|
||||
improvements:
|
||||
- `weave` is now integrated with Juno's progress bar; just call `weave` function inside Juno or use `julia-client: weave-to-html(pdf)` command (#331)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
name = "Weave"
|
||||
uuid = "44d3d7a6-8a23-5bf8-98c5-b353f8df5ec9"
|
||||
version = "0.10.2"
|
||||
version = "0.10.6"
|
||||
|
||||
[deps]
|
||||
Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"
|
||||
|
|
|
@ -39,11 +39,11 @@ Note that `Date` is available since the chunk is evaluated first.
|
|||
---
|
||||
title : Header Example
|
||||
author : Shuhei Kadowaki
|
||||
date: `j Date(now())`
|
||||
date: `j import Dates; Dates.Date(Dates.now())`
|
||||
---
|
||||
|
||||
```julia; echo = false
|
||||
using Datas
|
||||
using Dates
|
||||
```
|
||||
```
|
||||
|
||||
|
|
|
@ -165,29 +165,12 @@ See [Header Configuration](@ref) section for more details.
|
|||
|
||||
## Passing Runtime Arguments to Documents
|
||||
|
||||
You can pass arguments as `Dict` to the weaved document using the `args` argument
|
||||
to `weave`. The arguments will be available as `WEAVE_ARGS` variable in the document.
|
||||
You can pass arbitrary object to the weaved document using [`weave`](@ref)'s optional argument `args`.
|
||||
It will be available as `WEAVE_ARGS` variable in the `weave`d document.
|
||||
|
||||
This makes it possible to create the same report easily for e.g. different
|
||||
date ranges of input data from a database or from files with similar format giving the
|
||||
filename as input.
|
||||
This makes it possible to create the same report easily for e.g. different date ranges of input data from a database or from files with similar format giving the filename as input.
|
||||
|
||||
In order to pass a filename to a document you need call `weave` using:
|
||||
|
||||
```julia
|
||||
weave("mydoc.jmd", args = Dict("filename" => "somedata.h5"))
|
||||
```
|
||||
|
||||
and you can access the filename from document as follows:
|
||||
|
||||
```
|
||||
```julia
|
||||
print(WEAVE_ARGS["filename"])
|
||||
```
|
||||
```
|
||||
|
||||
You can use the `out_path` argument to control the name of the
|
||||
output document.
|
||||
E.g. if you call `weave("weavefile.jmd", args = (datalocation = "somedata.h5",))`, and then you can retrieve the `datalocation` in `weavefile.jmd` as follows: `WEAVE_ARGS.datalocation`
|
||||
|
||||
|
||||
## `include_weave`
|
||||
|
|
|
@ -102,7 +102,7 @@ Weave an input document to output file.
|
|||
* `:doc`: Path of the source document (default)
|
||||
* `:pwd`: Julia working directory
|
||||
* `"somepath"`: `String` of output directory e.g. `"~/outdir"`, or of filename e.g. `"~/outdir/outfile.tex"`
|
||||
- `args::Dict = Dict()`: Arguments to be passed to the weaved document; will be available as `WEAVE_ARGS` in the document
|
||||
- `args::Any = Dict()`: A runtime object that is available as `WEAVE_ARGS` while `weave`ing
|
||||
- `mod::Union{Module,Nothing} = nothing`: Module where Weave `eval`s code. You can pass a `Module` object, otherwise create an new sandbox module.
|
||||
- `fig_path::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`
|
||||
|
@ -127,7 +127,7 @@ function weave(
|
|||
doctype::Union{Nothing,AbstractString} = nothing,
|
||||
informat::Union{Nothing,AbstractString} = nothing,
|
||||
out_path::Union{Symbol,AbstractString} = :doc,
|
||||
args::Dict = Dict(),
|
||||
args::Any = Dict(),
|
||||
mod::Union{Module,Nothing} = nothing,
|
||||
fig_path::Union{Nothing,AbstractString} = nothing,
|
||||
fig_ext::Union{Nothing,AbstractString} = nothing,
|
||||
|
|
|
@ -5,23 +5,15 @@ using ..Weave: isnothing, take2string!
|
|||
using Markdown
|
||||
import Markdown: @trigger, @breaking, Code, MD, withstream, startswith, LaTeX
|
||||
|
||||
|
||||
function __init__()
|
||||
# NOTE:
|
||||
# overwriting `Markdown.latex` function should be done here in order to allow
|
||||
# incremental precompilations
|
||||
Markdown.eval(
|
||||
quote
|
||||
function latex(io::IO, tex::Markdown.LaTeX)
|
||||
math_envs = ["align", "equation", "eqnarray"]
|
||||
use_dollars =
|
||||
!any([occursin("\\begin{$me", tex.formula) for me in math_envs])
|
||||
use_dollars && write(io, "\\[")
|
||||
write(io, string("\n", tex.formula, "\n"))
|
||||
use_dollars && write(io, "\\]\n")
|
||||
end
|
||||
end,
|
||||
)
|
||||
# Note that this definition causes a "Method overwritten" warning,
|
||||
# but defining this function in __init__() is not legal in julia v1.5
|
||||
function Markdown.latex(io::IO, tex::Markdown.LaTeX)
|
||||
math_envs = ["align", "equation", "eqnarray"]
|
||||
use_dollars =
|
||||
!any([occursin("\\begin{$me", tex.formula) for me in math_envs])
|
||||
use_dollars && write(io, "\\[")
|
||||
write(io, string("\n", tex.formula, "\n"))
|
||||
use_dollars && write(io, "\\]\n")
|
||||
end
|
||||
|
||||
mutable struct Comment
|
||||
|
|
|
@ -17,7 +17,7 @@ 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")
|
||||
|
@ -39,7 +39,7 @@ function Base.display(
|
|||
report::Weave.Report,
|
||||
m::MIME"image/png",
|
||||
data::Plots.Plot{Plots.PlotlyBackend},
|
||||
)#
|
||||
)
|
||||
display(report, MIME("image/svg+xml"), data)
|
||||
end
|
||||
|
||||
|
|
|
@ -44,18 +44,14 @@ function render_chunk(docformat::WeaveFormat, chunk::CodeChunk)
|
|||
|
||||
chunk.content = render_code(docformat, chunk.content)
|
||||
|
||||
if !chunk.options[:eval]
|
||||
return if chunk.options[:echo]
|
||||
string(docformat.codestart, '\n', chunk.content, docformat.codeend)
|
||||
else
|
||||
""
|
||||
end
|
||||
end
|
||||
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 chunk.options[:echo]
|
||||
result = if echo
|
||||
# Convert to output format and highlight (html, tex...) if needed
|
||||
string(docformat.codestart, chunk.content, docformat.codeend, '\n')
|
||||
else
|
||||
|
@ -126,7 +122,7 @@ render_output(docformat::WeaveFormat, output) = output
|
|||
|
||||
function render_termchunk(docformat::WeaveFormat, chunk)
|
||||
return if should_render(chunk)
|
||||
string(docformat.termstart, chunk.output, '\n', docformat.termend, '\n')
|
||||
string(docformat.termstart, chunk.output, docformat.termend)
|
||||
else
|
||||
""
|
||||
end
|
||||
|
|
|
@ -15,8 +15,8 @@ render_termchunk(docformat::HTMLFormat, chunk) =
|
|||
Base.@kwdef mutable struct WeaveHTML <: HTMLFormat
|
||||
description = "Weave-style HTML"
|
||||
extension = "html"
|
||||
codestart = "\n"
|
||||
codeend = "\n"
|
||||
codestart = '\n'
|
||||
codeend = '\n'
|
||||
termstart = codestart
|
||||
termend = codeend
|
||||
outputstart = "<pre class=\"output\">"
|
||||
|
|
|
@ -4,12 +4,12 @@
|
|||
Base.@kwdef mutable struct GitHubMarkdown <: WeaveFormat
|
||||
description = "GitHub Markdown"
|
||||
extension = "md"
|
||||
codestart = "````julia"
|
||||
codeend = "````\n\n"
|
||||
codestart = "```julia"
|
||||
codeend = "```\n"
|
||||
termstart = codestart
|
||||
termend = codeend
|
||||
outputstart = "````"
|
||||
outputend = "````\n\n"
|
||||
outputstart = "```"
|
||||
outputend = "```\n\n"
|
||||
fig_ext = ".png"
|
||||
mimetypes = ["image/png", "image/svg+xml", "image/jpg",
|
||||
"text/markdown", "text/plain"]
|
||||
|
@ -50,12 +50,12 @@ end
|
|||
Base.@kwdef mutable struct Hugo <: WeaveFormat
|
||||
description = "Hugo Markdown (using shortcodes)"
|
||||
extension = "md"
|
||||
codestart = "````julia"
|
||||
codeend = "````\n\n"
|
||||
codestart = "```julia"
|
||||
codeend = "```\n"
|
||||
termstart = codestart
|
||||
termend = codeend
|
||||
outputstart = "````"
|
||||
outputend = "````\n\n"
|
||||
outputstart = "```"
|
||||
outputend = "```\n\n"
|
||||
mimetypes = default_mime_types
|
||||
fig_ext = ".png"
|
||||
out_width = nothing
|
||||
|
@ -88,12 +88,12 @@ end
|
|||
Base.@kwdef mutable struct MultiMarkdown <: WeaveFormat
|
||||
description = "MultiMarkdown"
|
||||
extension = "md"
|
||||
codestart = "````julia"
|
||||
codeend = "````\n\n"
|
||||
codestart = "```julia"
|
||||
codeend = "```\n"
|
||||
termstart = codestart
|
||||
termend = codeend
|
||||
outputstart = "````"
|
||||
outputend = "````\n\n"
|
||||
outputstart = "```"
|
||||
outputend = "```\n\n"
|
||||
mimetypes = default_mime_types
|
||||
fig_ext = ".png"
|
||||
out_width = nothing
|
||||
|
@ -143,7 +143,7 @@ Base.@kwdef mutable struct Rest <: WeaveFormat
|
|||
description = "reStructuredText and Sphinx"
|
||||
extension = "rst"
|
||||
codestart = ".. code-block:: julia\n"
|
||||
codeend = "\n\n"
|
||||
codeend = "\n"
|
||||
termstart = codestart
|
||||
termend = codeend
|
||||
outputstart = "::\n"
|
||||
|
@ -190,7 +190,7 @@ Base.@kwdef mutable struct AsciiDoc <: WeaveFormat
|
|||
description = "AsciiDoc"
|
||||
extension = "txt"
|
||||
codestart = "[source,julia]\n--------------------------------------"
|
||||
codeend = "--------------------------------------\n\n"
|
||||
codeend = "--------------------------------------\n"
|
||||
termstart = codestart
|
||||
termend = codeend
|
||||
outputstart = "--------------------------------------"
|
||||
|
|
|
@ -37,7 +37,7 @@ Base.@kwdef mutable struct Pandoc <: PandocFormat
|
|||
description = "Pandoc Markdown"
|
||||
extension = "md"
|
||||
codestart = "~~~~{.julia}"
|
||||
codeend = "~~~~~~~~~~~~~\n\n"
|
||||
codeend = "~~~~~~~~~~~~~\n"
|
||||
termstart = codestart
|
||||
termend = codeend
|
||||
outputstart = "~~~~"
|
||||
|
|
72
src/run.jl
72
src/run.jl
|
@ -7,7 +7,7 @@ function run_doc(
|
|||
doc::WeaveDoc;
|
||||
doctype::Union{Nothing,AbstractString} = nothing,
|
||||
out_path::Union{Symbol,AbstractString} = :doc,
|
||||
args::Dict = Dict(),
|
||||
args::Any = Dict(),
|
||||
mod::Union{Module,Nothing} = nothing,
|
||||
fig_path::Union{Nothing,AbstractString} = nothing,
|
||||
fig_ext::Union{Nothing,AbstractString} = nothing,
|
||||
|
@ -20,8 +20,9 @@ function run_doc(
|
|||
doc.format = deepcopy(get_format(doctype))
|
||||
|
||||
cwd = doc.cwd = get_cwd(doc, out_path)
|
||||
isdir(cwd) || mkdir(cwd)
|
||||
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)))
|
||||
|
@ -29,7 +30,7 @@ function run_doc(
|
|||
DEFAULT_FIG_PATH
|
||||
end
|
||||
end
|
||||
let d = normpath(cwd, fig_path); isdir(d) || mkdir(d); 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)
|
||||
|
@ -38,7 +39,7 @@ function run_doc(
|
|||
|
||||
# New sandbox for each document with args exposed
|
||||
isnothing(mod) && (mod = sandbox = Core.eval(Main, :(module $(gensym(:WeaveSandBox)) end))::Module)
|
||||
@eval mod WEAVE_ARGS = $args
|
||||
Core.eval(mod, :(WEAVE_ARGS = $(args)))
|
||||
|
||||
mimetypes = doc.format.mimetypes
|
||||
|
||||
|
@ -139,27 +140,17 @@ function embed_figures!(chunk::CodeChunk, cwd)
|
|||
chunk.figures[i] = img2base64(fig, cwd)
|
||||
end
|
||||
end
|
||||
|
||||
function embed_figures!(chunks::Vector{CodeChunk}, cwd)
|
||||
for chunk in chunks
|
||||
embed_figures!(chunk, cwd)
|
||||
end
|
||||
end
|
||||
embed_figures!(chunks, cwd) = embed_figures!.(chunks, Ref(cwd))
|
||||
|
||||
function img2base64(fig, cwd)
|
||||
ext = splitext(fig)[2]
|
||||
f = open(joinpath(cwd, fig), "r")
|
||||
raw = read(f)
|
||||
close(f)
|
||||
if ext == ".png"
|
||||
return "data:image/png;base64," * stringmime(MIME("image/png"), raw)
|
||||
elseif ext == ".svg"
|
||||
return "data:image/svg+xml;base64," * stringmime(MIME("image/svg"), raw)
|
||||
elseif ext == ".gif"
|
||||
return "data:image/gif;base64," * stringmime(MIME("image/gif"), raw)
|
||||
else
|
||||
return (fig)
|
||||
end
|
||||
return ext == ".png" ? "data:image/png;base64," * stringmime(MIME("image/png"), raw) :
|
||||
ext == ".svg" ? "data:image/svg+xml;base64," * stringmime(MIME("image/svg"), raw) :
|
||||
ext == ".gif" ? "data:image/gif;base64," * stringmime(MIME("image/gif"), raw) :
|
||||
fig
|
||||
end
|
||||
|
||||
function run_chunk(chunk::DocChunk, doc, report, mod)
|
||||
|
@ -225,7 +216,7 @@ function capture_output(code, mod, path, error, report)
|
|||
task_local_storage(:SOURCE_PATH, path) do
|
||||
try
|
||||
obj = include_string(mod, code, path) # TODO: fix line number
|
||||
!isnothing(obj) && display(obj)
|
||||
!isnothing(obj) && !REPL.ends_with_semicolon(code) && display(obj)
|
||||
catch _err
|
||||
err = unwrap_load_err(_err)
|
||||
error || throw(err)
|
||||
|
@ -273,15 +264,9 @@ function eval_chunk(doc::WeaveDoc, chunk::CodeChunk, report::Report, mod::Module
|
|||
|
||||
execute_posthooks!(chunk)
|
||||
|
||||
chunks = if chunk.options[:term]
|
||||
collect_term_results(chunk)
|
||||
elseif chunk.options[:hold]
|
||||
collect_hold_results(chunk)
|
||||
else
|
||||
collect_results(chunk)
|
||||
end
|
||||
|
||||
return chunks
|
||||
return chunk.options[:term] ? collect_term_results(chunk) :
|
||||
chunk.options[:hold] ? collect_hold_results(chunk) :
|
||||
collect_results(chunk)
|
||||
end
|
||||
|
||||
# Hooks to run before and after chunks, this is form IJulia,
|
||||
|
@ -292,7 +277,11 @@ function pop_preexecution_hook!(f::Function)
|
|||
isnothing(i) && error("this function has not been registered in the pre-execution hook yet")
|
||||
return splice!(preexecution_hooks, i)
|
||||
end
|
||||
execute_prehooks!(chunk::CodeChunk) = for prehook in preexecution_hooks; Base.invokelatest(prehook, chunk); 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)
|
||||
|
@ -301,7 +290,11 @@ function pop_postexecution_hook!(f::Function)
|
|||
isnothing(i) && error("this function has not been registered in the post-execution hook yet")
|
||||
return splice!(postexecution_hooks, i)
|
||||
end
|
||||
execute_posthooks!(chunk::CodeChunk) = for posthook in postexecution_hooks; Base.invokelatest(posthook, chunk); end
|
||||
function execute_posthooks!(chunk::CodeChunk)
|
||||
for posthook in postexecution_hooks
|
||||
Base.invokelatest(posthook, chunk)
|
||||
end
|
||||
end
|
||||
|
||||
"""
|
||||
clear_module!(mod::Module)
|
||||
|
@ -340,11 +333,7 @@ function get_figname(report::Report, chunk; fignum = nothing, ext = nothing)
|
|||
end
|
||||
|
||||
function set_rc_params(doc::WeaveDoc, fig_path, fig_ext)
|
||||
if isnothing(fig_ext)
|
||||
doc.chunk_defaults[:fig_ext] = doc.format.fig_ext
|
||||
else
|
||||
doc.chunk_defaults[:fig_ext] = fig_ext
|
||||
end
|
||||
doc.chunk_defaults[:fig_ext] = isnothing(fig_ext) ? doc.format.fig_ext : fig_ext
|
||||
doc.chunk_defaults[:fig_path] = fig_path
|
||||
end
|
||||
|
||||
|
@ -352,11 +341,9 @@ 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 strip(r.stdout) == "" && isempty(r.figures) && strip(r.rich_output) == ""
|
||||
content *= r.code
|
||||
else
|
||||
content = "\n" * content * r.code
|
||||
if any(!isempty ∘ strip, (r.stdout, r.rich_output)) || !isempty(r.figures)
|
||||
rchunk = CodeChunk(
|
||||
content,
|
||||
chunk.number,
|
||||
|
@ -364,15 +351,14 @@ function collect_results(chunk::CodeChunk)
|
|||
chunk.optionstring,
|
||||
copy(chunk.options),
|
||||
)
|
||||
content = ""
|
||||
rchunk.figures = r.figures
|
||||
rchunk.output = r.stdout
|
||||
rchunk.rich_output = r.rich_output
|
||||
rchunk.figures = r.figures
|
||||
push!(result_chunks, rchunk)
|
||||
content = ""
|
||||
end
|
||||
end
|
||||
if !isempty(content)
|
||||
startswith(content, "\n") || (content = "\n" * content)
|
||||
rchunk = CodeChunk(
|
||||
content,
|
||||
chunk.number,
|
||||
|
|
Loading…
Reference in New Issue