mirror of https://github.com/mpastell/Weave.jl
Merge pull request #319 from JunoLab/avi/weavedoc
remove weird default constructor for `WeaveDoc`pull/313/head
commit
a526cb8f15
|
@ -3,6 +3,9 @@ import Highlights
|
||||||
using Mustache
|
using Mustache
|
||||||
using Requires
|
using Requires
|
||||||
|
|
||||||
|
|
||||||
|
const WEAVE_OPTION_NAME = "options" # TODO: rename to "weave_options"
|
||||||
|
|
||||||
function __init__()
|
function __init__()
|
||||||
@require Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" Base.include(
|
@require Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" Base.include(
|
||||||
Main,
|
Main,
|
||||||
|
@ -123,7 +126,7 @@ function weave(
|
||||||
doc.doctype = doctype
|
doc.doctype = doctype
|
||||||
|
|
||||||
# Read args from document header, overrides command line args
|
# Read args from document header, overrides command line args
|
||||||
if haskey(doc.header, "options")
|
if haskey(doc.header, WEAVE_OPTION_NAME)
|
||||||
(
|
(
|
||||||
doctype,
|
doctype,
|
||||||
informat,
|
informat,
|
||||||
|
@ -248,7 +251,7 @@ function notebook(
|
||||||
end
|
end
|
||||||
|
|
||||||
@info "Running nbconvert"
|
@info "Running nbconvert"
|
||||||
out = read(
|
return out = read(
|
||||||
`$jupyter_path nbconvert --ExecutePreprocessor.timeout=$timeout --to notebook --execute $outfile $nbconvert_options --output $outfile`,
|
`$jupyter_path nbconvert --ExecutePreprocessor.timeout=$timeout --to notebook --execute $outfile $nbconvert_options --output $outfile`,
|
||||||
String,
|
String,
|
||||||
)
|
)
|
||||||
|
|
|
@ -107,7 +107,7 @@ function header_args(
|
||||||
pandoc_options,
|
pandoc_options,
|
||||||
latex_cmd,
|
latex_cmd,
|
||||||
)
|
)
|
||||||
args = get(doc.header, "options", Dict())
|
args = get(doc.header, WEAVE_OPTION_NAME, Dict())
|
||||||
doctype = get(args, "doctype", doc.doctype)
|
doctype = get(args, "doctype", doc.doctype)
|
||||||
args = combine_args(args, doctype)
|
args = combine_args(args, doctype)
|
||||||
informat = get(args, "informat", :auto)
|
informat = get(args, "informat", :auto)
|
||||||
|
@ -145,16 +145,3 @@ function header_args(
|
||||||
latex_cmd,
|
latex_cmd,
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
"""
|
|
||||||
header_chunk_defaults!(doc::WeaveDoc)
|
|
||||||
|
|
||||||
Get chunk defaults from header and update.
|
|
||||||
"""
|
|
||||||
function header_chunk_defaults!(doc::WeaveDoc)
|
|
||||||
for key in keys(doc.chunk_defaults)
|
|
||||||
if (val = get(doc.header["options"], string(key), nothing)) !== nothing
|
|
||||||
doc.chunk_defaults[key] = val
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
|
@ -131,7 +131,7 @@ function strip_header!(docchunk::DocChunk, doctype)
|
||||||
else
|
else
|
||||||
# only strips Weave headers
|
# only strips Weave headers
|
||||||
header = YAML.load(m[:header])
|
header = YAML.load(m[:header])
|
||||||
delete!(header, "options")
|
delete!(header, WEAVE_OPTION_NAME)
|
||||||
if isempty(header)
|
if isempty(header)
|
||||||
lstrip(replace(content, HEADER_REGEX => ""))
|
lstrip(replace(content, HEADER_REGEX => ""))
|
||||||
else
|
else
|
||||||
|
|
|
@ -2,20 +2,48 @@ using JSON, YAML
|
||||||
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
read_doc(source::AbstractString, format = :auto) -> WeaveDoc
|
read_doc(source, format = :auto)
|
||||||
|
|
||||||
Read the input document from `source` and parse it into [`WeaveDoc`](@ref).
|
Read the input document from `source` and parse it into [`WeaveDoc`](@ref).
|
||||||
"""
|
"""
|
||||||
function read_doc(source::AbstractString, format = :auto)
|
function read_doc(source, format = :auto)
|
||||||
document = replace(read(source, String), "\r\n" => "\n") # fix line ending
|
document = replace(read(source, String), "\r\n" => "\n") # fix line ending
|
||||||
|
|
||||||
format === :auto && (format = detect_informat(source))
|
format === :auto && (format = detect_informat(source))
|
||||||
chunks = parse_doc(document, format)
|
chunks = parse_doc(document, format)
|
||||||
header = parse_header(first(chunks))
|
return WeaveDoc(source, chunks)
|
||||||
doc = WeaveDoc(source, chunks, header)
|
end
|
||||||
haskey(header, "options") && header_chunk_defaults!(doc) # TODO: rename `options` => `weave_options`
|
|
||||||
|
|
||||||
return doc
|
function WeaveDoc(source, chunks)
|
||||||
|
path, fname = splitdir(abspath(source))
|
||||||
|
basename = splitext(fname)[1]
|
||||||
|
|
||||||
|
header = parse_header(first(chunks))
|
||||||
|
# get chunk defaults from header and update
|
||||||
|
chunk_defaults = deepcopy(rcParams[:chunk_defaults])
|
||||||
|
if haskey(header, WEAVE_OPTION_NAME)
|
||||||
|
for key in keys(chunk_defaults)
|
||||||
|
if (val = get(header[WEAVE_OPTION_NAME], string(key), nothing)) !== nothing
|
||||||
|
chunk_defaults[key] = val
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return WeaveDoc(
|
||||||
|
source,
|
||||||
|
basename,
|
||||||
|
path,
|
||||||
|
chunks,
|
||||||
|
"",
|
||||||
|
nothing,
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
header,
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
Highlights.Themes.DefaultTheme,
|
||||||
|
"",
|
||||||
|
chunk_defaults,
|
||||||
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
@ -32,7 +60,7 @@ function detect_informat(source::AbstractString)
|
||||||
return "noweb"
|
return "noweb"
|
||||||
end
|
end
|
||||||
|
|
||||||
function parse_doc(document, format)
|
function parse_doc(document, format)::Vector{WeaveChunk}
|
||||||
return if format == "markdown"
|
return if format == "markdown"
|
||||||
parse_markdown(document)
|
parse_markdown(document)
|
||||||
elseif format == "noweb"
|
elseif format == "noweb"
|
||||||
|
|
20
src/types.jl
20
src/types.jl
|
@ -17,26 +17,6 @@ mutable struct WeaveDoc
|
||||||
highlight_theme::Type{<:Highlights.AbstractTheme}
|
highlight_theme::Type{<:Highlights.AbstractTheme}
|
||||||
fig_path::AbstractString
|
fig_path::AbstractString
|
||||||
chunk_defaults::Dict{Symbol,Any}
|
chunk_defaults::Dict{Symbol,Any}
|
||||||
function WeaveDoc(source, chunks, header)
|
|
||||||
path, fname = splitdir(abspath(source))
|
|
||||||
basename = splitext(fname)[1]
|
|
||||||
new(
|
|
||||||
source,
|
|
||||||
basename,
|
|
||||||
path,
|
|
||||||
chunks,
|
|
||||||
"",
|
|
||||||
nothing,
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
header,
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
Highlights.Themes.DefaultTheme,
|
|
||||||
"",
|
|
||||||
deepcopy(rcParams[:chunk_defaults]),
|
|
||||||
)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
struct ChunkOutput
|
struct ChunkOutput
|
||||||
|
|
|
@ -1,35 +0,0 @@
|
||||||
s1= """
|
|
||||||
|
|
||||||
```julia
|
|
||||||
using NonExisting
|
|
||||||
```
|
|
||||||
|
|
||||||
```julia
|
|
||||||
x =
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
```julia;term=true
|
|
||||||
plot(x)
|
|
||||||
y = 10
|
|
||||||
print(y
|
|
||||||
```
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
p1 = Weave.parse_markdown(s1)
|
|
||||||
doc = Weave.WeaveDoc("dummy1.jmd", p1, Dict())
|
|
||||||
doc1 = run_doc(doc, doctype = "pandoc")
|
|
||||||
|
|
||||||
@test doc1.chunks[1].output == "Error: ArgumentError: Package NonExisting not found in current path:\n- Run `import Pkg; Pkg.add(\"NonExisting\")` to install the NonExisting package.\n\n"
|
|
||||||
@test doc1.chunks[2].output == "Error: syntax: incomplete: premature end of input\n"
|
|
||||||
@test doc1.chunks[3].output == "\njulia> plot(x)\nError: UndefVarError: plot not defined\n\njulia> y = 10\n10\n\njulia> print(y\nError: syntax: incomplete: premature end of input\n"
|
|
||||||
|
|
||||||
@test_throws ArgumentError run_doc(doc, doctype = "pandoc", throw_errors = true)
|
|
||||||
|
|
||||||
doc = Weave.WeaveDoc("dummy1.jmd", p1, Dict())
|
|
||||||
doc3 = run_doc(doc, doctype = "md2html")
|
|
||||||
@test doc3.chunks[1].rich_output == "<pre class=\"julia-error\">\nERROR: ArgumentError: Package NonExisting not found in current path:\n- Run `import Pkg; Pkg.add("NonExisting")` to install the NonExisting package.\n\n</pre>\n"
|
|
||||||
@test doc3.chunks[2].rich_output == "<pre class=\"julia-error\">\nERROR: syntax: incomplete: premature end of input\n</pre>\n"
|
|
||||||
@test doc3.chunks[3].output == "\njulia> plot(x)\nError: UndefVarError: plot not defined\n\njulia> y = 10\n10\n\njulia> print(y\nError: syntax: incomplete: premature end of input\n"
|
|
||||||
@test doc3.chunks[3].rich_output == ""
|
|
|
@ -127,24 +127,21 @@ pformat.formatdict[:keep_unicode] = true
|
||||||
f = Weave.format_chunk(dchunk, pformat.formatdict, pformat)
|
f = Weave.format_chunk(dchunk, pformat.formatdict, pformat)
|
||||||
@test f == "\\section{Test chunk}\nα\n\n"
|
@test f == "\\section{Test chunk}\nα\n\n"
|
||||||
|
|
||||||
function doc_from_string(str)
|
|
||||||
parsed = Weave.parse_markdown(str)
|
|
||||||
header = Weave.parse_header(parsed[1])
|
|
||||||
Weave.WeaveDoc("",parsed,header)
|
|
||||||
end
|
|
||||||
|
|
||||||
doc_content = """
|
str = """
|
||||||
```julia
|
```julia
|
||||||
α = 10
|
α = 10
|
||||||
```
|
```
|
||||||
"""
|
"""
|
||||||
|
|
||||||
parsed = doc_from_string(doc_content)
|
let
|
||||||
ldoc = run_doc(parsed, doctype = "md2tex")
|
doc = run_doc(mock_doc(str), doctype = "md2tex")
|
||||||
@test occursin(Weave.uc2tex("α"),Weave.format(ldoc))
|
@test occursin(Weave.uc2tex("α"), Weave.format(doc))
|
||||||
@test !occursin("α",Weave.format(ldoc))
|
@test !occursin("α", Weave.format(doc))
|
||||||
|
end
|
||||||
|
|
||||||
parsed = doc_from_string(doc_content)
|
let
|
||||||
ldoc = run_doc(parsed, doctype = "md2tex",latex_keep_unicode=true)
|
doc = run_doc(mock_doc(str), doctype = "md2tex",latex_keep_unicode = true)
|
||||||
@test occursin("α",Weave.format(ldoc))
|
@test occursin("α", Weave.format(doc))
|
||||||
@test !occursin(Weave.uc2tex("α"),Weave.format(ldoc))
|
@test !occursin(Weave.uc2tex("α"), Weave.format(doc))
|
||||||
|
end
|
||||||
|
|
|
@ -6,16 +6,15 @@ using Test
|
||||||
# TODO: add test for header processsing
|
# TODO: add test for header processsing
|
||||||
# TODO: add test for `include_weave`
|
# TODO: add test for `include_weave`
|
||||||
|
|
||||||
|
# constructs `WeaveDoc` from `String`
|
||||||
|
mock_doc(str, chunk_parser = Weave.parse_markdown) = Weave.WeaveDoc("dummy", chunk_parser(str))
|
||||||
|
|
||||||
|
|
||||||
@testset "Weave" begin
|
@testset "Weave" begin
|
||||||
@testset "Chunk options" begin
|
@testset "Chunk options" begin
|
||||||
include("chunk_options.jl")
|
include("chunk_options.jl")
|
||||||
end
|
end
|
||||||
|
|
||||||
@testset "Error handling " begin
|
|
||||||
include("errors_test.jl")
|
|
||||||
end
|
|
||||||
|
|
||||||
@testset "module evaluation" begin
|
@testset "module evaluation" begin
|
||||||
include("test_module_evaluation.jl")
|
include("test_module_evaluation.jl")
|
||||||
end
|
end
|
||||||
|
@ -24,6 +23,10 @@ using Test
|
||||||
include("test_header.jl")
|
include("test_header.jl")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@testset "error rendering" begin
|
||||||
|
include("test_error_rendering.jl")
|
||||||
|
end
|
||||||
|
|
||||||
@testset "Conversions" begin
|
@testset "Conversions" begin
|
||||||
include("convert_test.jl")
|
include("convert_test.jl")
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
function get_err_str(ex)
|
||||||
|
try
|
||||||
|
eval(ex)
|
||||||
|
catch err
|
||||||
|
return sprint(showerror, err)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
get_err_str(str::AbstractString) = get_err_str(Meta.parse(str; raise = false))
|
||||||
|
|
||||||
|
err_stmt1 = "using NonExisting"
|
||||||
|
err_stmt2 = "x = "
|
||||||
|
err_stmt3 = """
|
||||||
|
plot(x)
|
||||||
|
y = 10
|
||||||
|
f(y
|
||||||
|
"""
|
||||||
|
|
||||||
|
str = """
|
||||||
|
```julia
|
||||||
|
$err_stmt1
|
||||||
|
```
|
||||||
|
|
||||||
|
```julia
|
||||||
|
$err_stmt2
|
||||||
|
```
|
||||||
|
|
||||||
|
```julia; term=true
|
||||||
|
$err_stmt3
|
||||||
|
```
|
||||||
|
"""
|
||||||
|
|
||||||
|
err_str1 = get_err_str(err_stmt1)
|
||||||
|
err_str2 = get_err_str(err_stmt2)
|
||||||
|
err_str3_1 = get_err_str("plot(x)")
|
||||||
|
err_str3_2 = get_err_str("f(y")
|
||||||
|
|
||||||
|
|
||||||
|
let doc = run_doc(mock_doc(str), doctype = "pandoc")
|
||||||
|
get_output(i) = doc.chunks[i].output
|
||||||
|
|
||||||
|
@test occursin(err_str1, get_output(1))
|
||||||
|
@test occursin(err_str2, get_output(2))
|
||||||
|
@test occursin(err_str3_1, get_output(3))
|
||||||
|
@test occursin(err_str3_2, get_output(3))
|
||||||
|
end
|
||||||
|
|
||||||
|
@test_throws ArgumentError run_doc(mock_doc(str), doctype = "pandoc", throw_errors = true)
|
||||||
|
|
||||||
|
# TODO: test error rendering in `rich_output`
|
|
@ -1,4 +1,4 @@
|
||||||
using YAML
|
using Weave.YAML
|
||||||
|
|
||||||
# TODO:
|
# TODO:
|
||||||
# - header stripping
|
# - header stripping
|
||||||
|
@ -19,7 +19,7 @@ options:
|
||||||
---
|
---
|
||||||
""")
|
""")
|
||||||
|
|
||||||
let args = header["options"]
|
let args = header[Weave.WEAVE_OPTION_NAME]
|
||||||
@test Weave.combine_args(args, "md2html") == Dict("fig_ext" => ".png", "out_path" => "html/")
|
@test Weave.combine_args(args, "md2html") == Dict("fig_ext" => ".png", "out_path" => "html/")
|
||||||
@test Weave.combine_args(args, "github") == Dict("fig_ext" => ".png", "out_path" => "md/")
|
@test Weave.combine_args(args, "github") == Dict("fig_ext" => ".png", "out_path" => "md/")
|
||||||
@test Weave.combine_args(args, "pandoc") == Dict("fig_ext" => ".png", "out_path" => "reports")
|
@test Weave.combine_args(args, "pandoc") == Dict("fig_ext" => ".png", "out_path" => "reports")
|
||||||
|
|
|
@ -1,23 +1,20 @@
|
||||||
@testset "evaluation module" begin
|
@testset "evaluation module" begin
|
||||||
function mock_output(document, mod = nothing)
|
function mock_output(str, mod = nothing)
|
||||||
parsed = Weave.parse_markdown(document)
|
result_doc = run_doc(mock_doc(str), mod = mod)
|
||||||
doc = Weave.WeaveDoc("dummy.jmd", parsed, Dict())
|
|
||||||
result_doc = run_doc(doc, mod = mod)
|
|
||||||
@test isdefined(result_doc.chunks[1], :output)
|
|
||||||
return result_doc.chunks[1].output
|
return result_doc.chunks[1].output
|
||||||
end
|
end
|
||||||
|
|
||||||
document = """
|
str = """
|
||||||
```julia
|
```julia
|
||||||
@__MODULE__
|
@__MODULE__
|
||||||
```
|
```
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# in sandbox
|
# in sandbox
|
||||||
@test occursin(r"\#+WeaveSandBox[\#\d]+", mock_output(document))
|
@test occursin(r"\#+WeaveSandBox[\#\d]+", mock_output(str))
|
||||||
|
|
||||||
# in Main
|
# in Main
|
||||||
@test strip(mock_output(document, Main)) == "Main"
|
@test strip(mock_output(str, Main)) == "Main"
|
||||||
end
|
end
|
||||||
|
|
||||||
@testset "clear_module!" begin
|
@testset "clear_module!" begin
|
||||||
|
|
Loading…
Reference in New Issue