mirror of https://github.com/mpastell/Weave.jl
commit
0c59e92fd7
115
src/Weave.jl
115
src/Weave.jl
|
@ -4,8 +4,14 @@ using Mustache
|
|||
using Requires
|
||||
|
||||
function __init__()
|
||||
@require Plots="91a5bcdd-55d7-5caf-9e0b-520d859cae80" Base.include(Main, joinpath(@__DIR__, "plots.jl"))
|
||||
@require Gadfly="c91e804a-d5a3-530f-b6f0-dfbca275c004" Base.include(Main, joinpath(@__DIR__, "gadfly.jl"))
|
||||
@require Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" Base.include(
|
||||
Main,
|
||||
joinpath(@__DIR__, "plots.jl"),
|
||||
)
|
||||
@require Gadfly = "c91e804a-d5a3-530f-b6f0-dfbca275c004" Base.include(
|
||||
Main,
|
||||
joinpath(@__DIR__, "gadfly.jl"),
|
||||
)
|
||||
end
|
||||
|
||||
"""
|
||||
|
@ -14,12 +20,11 @@ end
|
|||
List supported output formats
|
||||
"""
|
||||
function list_out_formats()
|
||||
for format = keys(formats)
|
||||
println(string(format,": ", formats[format].description))
|
||||
for format in keys(formats)
|
||||
println(string(format, ": ", formats[format].description))
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
"""
|
||||
tangle(source::AbstractString; kwargs...)
|
||||
|
||||
|
@ -36,8 +41,8 @@ Tangle source code from input document to .jl file.
|
|||
function tangle(
|
||||
source::AbstractString;
|
||||
out_path::Union{Symbol,AbstractString} = :doc,
|
||||
informat::Union{Symbol,AbstractString} = :auto
|
||||
)
|
||||
informat::Union{Symbol,AbstractString} = :auto,
|
||||
)
|
||||
doc = read_doc(source, informat)
|
||||
doc.cwd = get_cwd(doc, out_path)
|
||||
|
||||
|
@ -47,15 +52,14 @@ function tangle(
|
|||
for chunk in doc.chunks
|
||||
if typeof(chunk) == CodeChunk
|
||||
options = merge(doc.chunk_defaults, chunk.options)
|
||||
options[:tangle] && write(io, chunk.content*"\n")
|
||||
options[:tangle] && write(io, chunk.content * "\n")
|
||||
end
|
||||
end
|
||||
end
|
||||
doc.cwd == pwd() && (outname = basename(outname))
|
||||
doc.cwd == pwd() && (outname = basename(outname))
|
||||
@info("Writing to file $outname")
|
||||
end
|
||||
|
||||
|
||||
"""
|
||||
weave(source::AbstractString; kwargs...)
|
||||
|
||||
|
@ -107,7 +111,7 @@ function weave(
|
|||
css::Union{Nothing,AbstractString} = nothing,
|
||||
pandoc_options::Vector{<:AbstractString} = String[],
|
||||
latex_cmd::AbstractString = "xelatex",
|
||||
latex_keep_unicode::Bool = false
|
||||
latex_keep_unicode::Bool = false,
|
||||
)
|
||||
doc = read_doc(source, informat)
|
||||
doctype == :auto && (doctype = detect_doctype(doc.source))
|
||||
|
@ -115,25 +119,57 @@ function weave(
|
|||
|
||||
# Read args from document header, overrides command line args
|
||||
if haskey(doc.header, "options")
|
||||
(doctype, informat, out_path, args, mod, fig_path, fig_ext,
|
||||
cache_path, cache, throw_errors, template, highlight_theme, css,
|
||||
pandoc_options, latex_cmd) = header_args(doc, out_path, mod,
|
||||
fig_ext, fig_path,
|
||||
cache_path, cache, throw_errors,
|
||||
template, highlight_theme, css,
|
||||
pandoc_options, latex_cmd)
|
||||
(
|
||||
doctype,
|
||||
informat,
|
||||
out_path,
|
||||
args,
|
||||
mod,
|
||||
fig_path,
|
||||
fig_ext,
|
||||
cache_path,
|
||||
cache,
|
||||
throw_errors,
|
||||
template,
|
||||
highlight_theme,
|
||||
css,
|
||||
pandoc_options,
|
||||
latex_cmd,
|
||||
) = header_args(
|
||||
doc,
|
||||
out_path,
|
||||
mod,
|
||||
fig_ext,
|
||||
fig_path,
|
||||
cache_path,
|
||||
cache,
|
||||
throw_errors,
|
||||
template,
|
||||
highlight_theme,
|
||||
css,
|
||||
pandoc_options,
|
||||
latex_cmd,
|
||||
)
|
||||
end
|
||||
|
||||
template != nothing && (doc.template = template)
|
||||
highlight_theme != nothing && (doc.highlight_theme = highlight_theme)
|
||||
#theme != nothing && (doc.theme = theme) #Reserved for themes
|
||||
# theme != nothing && (doc.theme = theme) # Reserved for themes
|
||||
css != nothing && (doc.css = css)
|
||||
|
||||
doc = run(doc, doctype = doctype,
|
||||
mod = mod,
|
||||
out_path=out_path, args = args,
|
||||
fig_path = fig_path, fig_ext = fig_ext, cache_path = cache_path, cache=cache,
|
||||
throw_errors = throw_errors,latex_keep_unicode=latex_keep_unicode)
|
||||
doc = run(
|
||||
doc,
|
||||
doctype = doctype,
|
||||
mod = mod,
|
||||
out_path = out_path,
|
||||
args = args,
|
||||
fig_path = fig_path,
|
||||
fig_ext = fig_ext,
|
||||
cache_path = cache_path,
|
||||
cache = cache,
|
||||
throw_errors = throw_errors,
|
||||
latex_keep_unicode = latex_keep_unicode,
|
||||
)
|
||||
formatted = format(doc)
|
||||
|
||||
outname = get_outname(out_path, doc)
|
||||
|
@ -142,7 +178,7 @@ function weave(
|
|||
write(io, formatted)
|
||||
end
|
||||
|
||||
#Special for that need external programs
|
||||
# Special for that need external programs
|
||||
if doc.doctype == "pandoc2html"
|
||||
mdname = outname
|
||||
outname = get_outname(out_path, doc, ext = "html")
|
||||
|
@ -231,7 +267,10 @@ function include_weave(
|
|||
doc = read_doc(source, informat)
|
||||
cd(doc.path)
|
||||
try
|
||||
code = join([x.content for x in filter(x -> isa(x, Weave.CodeChunk), doc.chunks)], "\n")
|
||||
code = join(
|
||||
[x.content for x in filter(x -> isa(x, Weave.CodeChunk), doc.chunks)],
|
||||
"\n",
|
||||
)
|
||||
include_string(m, code)
|
||||
catch e
|
||||
throw(e)
|
||||
|
@ -240,17 +279,19 @@ function include_weave(
|
|||
end
|
||||
end
|
||||
|
||||
include_weave(source, informat=:auto) = include_weave(Main, source, informat)
|
||||
include_weave(source, informat = :auto) = include_weave(Main, source, informat)
|
||||
|
||||
#Hooks to run before and after chunks, this is form IJulia,
|
||||
#but note that Weave hooks take the chunk as input
|
||||
# Hooks to run before and after chunks, this is form IJulia,
|
||||
# but note that Weave hooks take the chunk as input
|
||||
const preexecute_hooks = Function[]
|
||||
push_preexecute_hook(f::Function) = push!(preexecute_hooks, f)
|
||||
pop_preexecute_hook(f::Function) = splice!(preexecute_hooks, findfirst(x -> x == f, preexecute_hooks))
|
||||
pop_preexecute_hook(f::Function) =
|
||||
splice!(preexecute_hooks, findfirst(x -> x == f, preexecute_hooks))
|
||||
|
||||
const postexecute_hooks = Function[]
|
||||
push_postexecute_hook(f::Function) = push!(postexecute_hooks, f)
|
||||
pop_postexecute_hook(f::Function) = splice!(postexecute_hooks, findfirst(x -> x == f, postexecute_hooks))
|
||||
pop_postexecute_hook(f::Function) =
|
||||
splice!(postexecute_hooks, findfirst(x -> x == f, postexecute_hooks))
|
||||
|
||||
include("chunks.jl")
|
||||
include("config.jl")
|
||||
|
@ -264,8 +305,14 @@ include("format.jl")
|
|||
include("pandoc.jl")
|
||||
include("writers.jl")
|
||||
|
||||
export weave,
|
||||
list_out_formats,
|
||||
tangle,
|
||||
convert_doc,
|
||||
notebook,
|
||||
set_chunk_defaults,
|
||||
get_chunk_defaults,
|
||||
restore_chunk_defaults,
|
||||
include_weave
|
||||
|
||||
export weave, list_out_formats, tangle, convert_doc, notebook,
|
||||
set_chunk_defaults, get_chunk_defaults, restore_chunk_defaults,
|
||||
include_weave
|
||||
end
|
||||
|
|
|
@ -1,8 +1,23 @@
|
|||
#module Markdown2HTML
|
||||
# module Markdown2HTML
|
||||
# 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
|
||||
using Markdown:
|
||||
MD,
|
||||
Header,
|
||||
Code,
|
||||
Paragraph,
|
||||
BlockQuote,
|
||||
Footnote,
|
||||
Table,
|
||||
Admonition,
|
||||
List,
|
||||
HorizontalRule,
|
||||
Bold,
|
||||
Italic,
|
||||
Image,
|
||||
Link,
|
||||
LineBreak,
|
||||
LaTeX,
|
||||
isordered
|
||||
|
||||
function tohtml(io::IO, m::MIME"text/html", x)
|
||||
show(io, m, x)
|
||||
|
@ -22,8 +37,6 @@ function tohtml(m::MIME"image/svg+xml", img)
|
|||
show(io, m, img)
|
||||
end
|
||||
|
||||
|
||||
|
||||
# AbstractDisplay infrastructure
|
||||
|
||||
function bestmime(val)
|
||||
|
@ -35,7 +48,6 @@ end
|
|||
|
||||
tohtml(io::IO, x) = tohtml(io, bestmime(x), x)
|
||||
|
||||
|
||||
# Utils
|
||||
|
||||
function withtag(f, io::IO, tag, attrs...)
|
||||
|
@ -56,10 +68,13 @@ end
|
|||
|
||||
tag(io::IO, tag, attrs...) = withtag(nothing, io, tag, attrs...)
|
||||
|
||||
const _htmlescape_chars = Dict('<'=>"<", '>'=>">",
|
||||
'"'=>""", '&'=>"&",
|
||||
# ' '=>" ",
|
||||
)
|
||||
const _htmlescape_chars = Dict(
|
||||
'<' => "<",
|
||||
'>' => ">",
|
||||
'"' => """,
|
||||
'&' => "&",
|
||||
# ' '=>" ",
|
||||
)
|
||||
for ch in "'`!\$%()=+{}[]"
|
||||
_htmlescape_chars[ch] = "&#$(Int(ch));"
|
||||
end
|
||||
|
@ -93,7 +108,7 @@ end
|
|||
|
||||
html(io::IO, md::MD) = html(io, md.content)
|
||||
|
||||
function html(io::IO, header::Header{l}) where l
|
||||
function html(io::IO, header::Header{l}) where {l}
|
||||
withtag(io, "h$l") do
|
||||
htmlinline(io, header.text)
|
||||
end
|
||||
|
@ -141,7 +156,7 @@ function html(io::IO, md::Admonition)
|
|||
end
|
||||
|
||||
function html(io::IO, md::List)
|
||||
maybe_attr = md.ordered > 1 ? Any[:start => string(md.ordered)] : []
|
||||
maybe_attr = md.ordered > 1 ? Any[:start=>string(md.ordered)] : []
|
||||
withtag(io, isordered(md) ? :ol : :ul, maybe_attr...) do
|
||||
for item in md.items
|
||||
println(io)
|
||||
|
@ -220,10 +235,9 @@ function htmlinline(io::IO, md::Italic)
|
|||
end
|
||||
|
||||
function htmlinline(io::IO, md::Image)
|
||||
tag(io, :img, :src=>md.url, :alt=>md.alt)
|
||||
tag(io, :img, :src => md.url, :alt => md.alt)
|
||||
end
|
||||
|
||||
|
||||
function htmlinline(io::IO, f::Footnote)
|
||||
withtag(io, :a, :href => "#footnote-$(f.id)", :class => "footnote") do
|
||||
print(io, "[", f.id, "]")
|
||||
|
@ -231,7 +245,7 @@ function htmlinline(io::IO, f::Footnote)
|
|||
end
|
||||
|
||||
function htmlinline(io::IO, link::Link)
|
||||
withtag(io, :a, :href=>link.url) do
|
||||
withtag(io, :a, :href => link.url) do
|
||||
htmlinline(io, link.text)
|
||||
end
|
||||
end
|
||||
|
@ -250,4 +264,4 @@ htmlinline(io::IO, x) = tohtml(io, x)
|
|||
|
||||
html(md) = sprint(html, md)
|
||||
|
||||
#end
|
||||
# end
|
||||
|
|
|
@ -7,23 +7,25 @@ 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)
|
||||
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,
|
||||
)
|
||||
end
|
||||
|
||||
mutable struct Comment
|
||||
text::String
|
||||
end
|
||||
|
||||
@breaking true ->
|
||||
function dollarmath(stream::IO, block::MD)
|
||||
@breaking true -> function dollarmath(stream::IO, block::MD)
|
||||
withstream(stream) do
|
||||
str = Markdown.startswith(stream, r"^\$\$$"m)
|
||||
isempty(str) && return false
|
||||
|
@ -41,20 +43,19 @@ function dollarmath(stream::IO, block::MD)
|
|||
else
|
||||
seek(stream, line_start)
|
||||
end
|
||||
write(buffer, readline(stream, keep=true))
|
||||
write(buffer, readline(stream, keep = true))
|
||||
end
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
@breaking true ->
|
||||
function topcomment(stream::IO, block::MD)
|
||||
@breaking true -> function topcomment(stream::IO, block::MD)
|
||||
buffer = IOBuffer()
|
||||
withstream(stream) do
|
||||
str = Markdown.startswith(stream, r"^<!--")
|
||||
isempty(str) && return false
|
||||
while !eof(stream)
|
||||
line = readline(stream, keep=true)
|
||||
line = readline(stream, keep = true)
|
||||
write(buffer, line)
|
||||
if occursin(r"-->$", line)
|
||||
s = replace(String(take!(buffer)) |> chomp, r"-->$" => "")
|
||||
|
@ -66,8 +67,7 @@ function topcomment(stream::IO, block::MD)
|
|||
end
|
||||
end
|
||||
|
||||
@trigger '<' ->
|
||||
function comment(stream::IO, md::MD)
|
||||
@trigger '<' -> function comment(stream::IO, md::MD)
|
||||
withstream(stream) do
|
||||
Markdown.startswith(stream, "<!--") || return
|
||||
text = Markdown.readuntil(stream, "-->")
|
||||
|
|
47
src/cache.jl
47
src/cache.jl
|
@ -1,9 +1,9 @@
|
|||
#Serialization is imported only if cache is used
|
||||
# Serialization is imported only if cache is used
|
||||
|
||||
function write_cache(doc::WeaveDoc, cache_path)
|
||||
cache_dir = joinpath(doc.cwd, cache_path)
|
||||
isdir(cache_dir) || mkpath(cache_dir)
|
||||
open(joinpath(cache_dir, doc.basename * ".cache"),"w") do io
|
||||
isdir(cache_dir) || mkpath(cache_dir)
|
||||
open(joinpath(cache_dir, doc.basename * ".cache"), "w") do io
|
||||
Serialization.serialize(io, doc)
|
||||
end
|
||||
return nothing
|
||||
|
@ -11,47 +11,48 @@ end
|
|||
|
||||
function read_cache(doc::WeaveDoc, cache_path)
|
||||
name = joinpath(doc.cwd, cache_path, doc.basename * ".cache")
|
||||
isfile(name) || return nothing
|
||||
open(name,"r") do io
|
||||
isfile(name) || return nothing
|
||||
open(name, "r") do io
|
||||
doc = Serialization.deserialize(io)
|
||||
end
|
||||
return doc
|
||||
end
|
||||
|
||||
function restore_chunk(chunk::CodeChunk, cached)
|
||||
chunks = filter(x -> x.number == chunk.number &&
|
||||
string(typeof(x)) == "Weave.CodeChunk", cached.chunks)
|
||||
chunks = filter(
|
||||
x -> x.number == chunk.number && string(typeof(x)) == "Weave.CodeChunk",
|
||||
cached.chunks,
|
||||
)
|
||||
|
||||
#Chunk types, don't match after loading. Fix by constructing chunks
|
||||
#from loaded content
|
||||
# Chunk types, don't match after loading. Fix by constructing chunks
|
||||
# from loaded content
|
||||
new_chunks = Any[]
|
||||
for c in chunks
|
||||
newc = CodeChunk(c.content, c.number, c.start_line, c.optionstring, c.options)
|
||||
newc.result_no = c.result_no
|
||||
newc.figures = c.figures
|
||||
newc.result = c.result
|
||||
newc.output = c.output
|
||||
newc.rich_output = c.rich_output
|
||||
push!(new_chunks, newc)
|
||||
newc = CodeChunk(c.content, c.number, c.start_line, c.optionstring, c.options)
|
||||
newc.result_no = c.result_no
|
||||
newc.figures = c.figures
|
||||
newc.result = c.result
|
||||
newc.output = c.output
|
||||
newc.rich_output = c.rich_output
|
||||
push!(new_chunks, newc)
|
||||
end
|
||||
return new_chunks
|
||||
end
|
||||
|
||||
#Restore inline code
|
||||
# Restore inline code
|
||||
function restore_chunk(chunk::DocChunk, cached::WeaveDoc)
|
||||
#Get chunk from cached doc
|
||||
c_chunk = filter(x -> x.number == chunk.number &&
|
||||
isa(x, DocChunk), cached.chunks)
|
||||
# Get chunk from cached doc
|
||||
c_chunk = filter(x -> x.number == chunk.number && isa(x, DocChunk), cached.chunks)
|
||||
isempty(c_chunk) && return chunk
|
||||
c_chunk = c_chunk[1]
|
||||
|
||||
#Collect cached code
|
||||
# Collect cached code
|
||||
c_inline = filter(x -> isa(x, InlineCode), c_chunk.content)
|
||||
isempty(c_inline) && return chunk
|
||||
|
||||
#Restore cached results for Inline code
|
||||
# Restore cached results for Inline code
|
||||
n = length(chunk.content)
|
||||
for i in 1:n
|
||||
for i = 1:n
|
||||
if isa(chunk.content[i], InlineCode)
|
||||
ci = filter(x -> x.number == chunk.content[i].number, c_inline)
|
||||
isempty(ci) && continue
|
||||
|
|
|
@ -9,11 +9,11 @@ mutable struct WeaveDoc
|
|||
path::AbstractString
|
||||
chunks::Array{WeaveChunk}
|
||||
cwd::AbstractString
|
||||
format
|
||||
format::Any
|
||||
doctype::AbstractString
|
||||
header_script::String
|
||||
header::Dict
|
||||
template::Union{AbstractString, Mustache.MustacheTokens}
|
||||
template::Union{AbstractString,Mustache.MustacheTokens}
|
||||
css::AbstractString
|
||||
highlight_theme::Type{<:Highlights.AbstractTheme}
|
||||
fig_path::AbstractString
|
||||
|
@ -21,8 +21,22 @@ mutable struct WeaveDoc
|
|||
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]))
|
||||
new(
|
||||
source,
|
||||
basename,
|
||||
path,
|
||||
chunks,
|
||||
"",
|
||||
nothing,
|
||||
"",
|
||||
"",
|
||||
header,
|
||||
"",
|
||||
"",
|
||||
Highlights.Themes.DefaultTheme,
|
||||
"",
|
||||
deepcopy(rcParams[:chunk_defaults]),
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -40,13 +54,24 @@ mutable struct CodeChunk <: WeaveChunk
|
|||
result_no::Int
|
||||
start_line::Int
|
||||
optionstring::AbstractString
|
||||
options::Dict{Symbol, Any}
|
||||
options::Dict{Symbol,Any}
|
||||
output::AbstractString
|
||||
rich_output::AbstractString
|
||||
figures::Array{AbstractString}
|
||||
result::Array{ChunkOutput}
|
||||
function CodeChunk(content, number, start_line, optionstring, options)
|
||||
new(rstrip(content) * "\n", number, 0, start_line, optionstring, options, "","", AbstractString[], ChunkOutput[])
|
||||
new(
|
||||
rstrip(content) * "\n",
|
||||
number,
|
||||
0,
|
||||
start_line,
|
||||
optionstring,
|
||||
options,
|
||||
"",
|
||||
"",
|
||||
AbstractString[],
|
||||
ChunkOutput[],
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -54,7 +79,12 @@ mutable struct DocChunk <: WeaveChunk
|
|||
content::Array{Inline}
|
||||
number::Int
|
||||
start_line::Int
|
||||
function DocChunk(text::AbstractString, number::Int, start_line::Int, inline_regex = nothing)
|
||||
function DocChunk(
|
||||
text::AbstractString,
|
||||
number::Int,
|
||||
start_line::Int,
|
||||
inline_regex = nothing,
|
||||
)
|
||||
chunks = parse_inline(text, inline_regex)
|
||||
new(chunks, number, start_line)
|
||||
end
|
||||
|
|
130
src/config.jl
130
src/config.jl
|
@ -1,43 +1,42 @@
|
|||
import Mustache
|
||||
|
||||
#Default options
|
||||
const defaultParams =
|
||||
Dict{Symbol,Any}(:storeresults => false,
|
||||
:doc_number => 0,
|
||||
:chunk_defaults =>
|
||||
Dict{Symbol,Any}(
|
||||
:echo=> true,
|
||||
:results=> "markup",
|
||||
:hold => false,
|
||||
:fig=> true,
|
||||
:include=> true,
|
||||
:eval => true,
|
||||
:tangle => true,
|
||||
:cache => false,
|
||||
:fig_cap=> nothing,
|
||||
#Size in inches
|
||||
:fig_width => 6,
|
||||
:fig_height => 4,
|
||||
:fig_path=> "figures",
|
||||
:dpi => 96,
|
||||
:term=> false,
|
||||
:display => false,
|
||||
:prompt => "\njulia> ",
|
||||
:label=> nothing,
|
||||
:wrap=> true,
|
||||
:line_width => 75,
|
||||
:engine=> "julia",
|
||||
#:option_AbstractString=> "",
|
||||
#Defined in formats
|
||||
:fig_ext => nothing,
|
||||
:fig_pos=> nothing,
|
||||
:fig_env=> nothing,
|
||||
:out_width=> nothing,
|
||||
:out_height=> nothing,
|
||||
:skip=>false
|
||||
)
|
||||
)
|
||||
#This one can be changed at runtime, initially a copy of defaults
|
||||
# Default options
|
||||
const defaultParams = Dict{Symbol,Any}(
|
||||
:storeresults => false,
|
||||
:doc_number => 0,
|
||||
:chunk_defaults => Dict{Symbol,Any}(
|
||||
:echo => true,
|
||||
:results => "markup",
|
||||
:hold => false,
|
||||
:fig => true,
|
||||
:include => true,
|
||||
:eval => true,
|
||||
:tangle => true,
|
||||
:cache => false,
|
||||
:fig_cap => nothing,
|
||||
# Size in inches
|
||||
:fig_width => 6,
|
||||
:fig_height => 4,
|
||||
:fig_path => "figures",
|
||||
:dpi => 96,
|
||||
:term => false,
|
||||
:display => false,
|
||||
:prompt => "\njulia> ",
|
||||
:label => nothing,
|
||||
:wrap => true,
|
||||
:line_width => 75,
|
||||
:engine => "julia",
|
||||
# :option_AbstractString=> "",
|
||||
# Defined in formats
|
||||
:fig_ext => nothing,
|
||||
:fig_pos => nothing,
|
||||
:fig_env => nothing,
|
||||
:out_width => nothing,
|
||||
:out_height => nothing,
|
||||
:skip => false,
|
||||
),
|
||||
)
|
||||
# This one can be changed at runtime, initially a copy of defaults
|
||||
const rcParams = deepcopy(defaultParams)
|
||||
|
||||
"""
|
||||
|
@ -51,9 +50,9 @@ E.g.: set default `dpi` to `200` and `fig_width` to `8`
|
|||
julia> set_chunk_defaults(Dict{Symbol, Any}(:dpi => 200, fig_width => 8))
|
||||
```
|
||||
"""
|
||||
function set_chunk_defaults(opts::Dict{Symbol, Any})
|
||||
merge!(rcParams[:chunk_defaults], opts)
|
||||
return nothing
|
||||
function set_chunk_defaults(opts::Dict{Symbol,Any})
|
||||
merge!(rcParams[:chunk_defaults], opts)
|
||||
return nothing
|
||||
end
|
||||
|
||||
"""
|
||||
|
@ -62,7 +61,7 @@ end
|
|||
Get default options used for code chunks.
|
||||
"""
|
||||
function get_chunk_defaults()
|
||||
return(rcParams[:chunk_defaults])
|
||||
return (rcParams[:chunk_defaults])
|
||||
end
|
||||
|
||||
"""
|
||||
|
@ -71,8 +70,8 @@ end
|
|||
Restore Weave.jl default chunk options.
|
||||
"""
|
||||
function restore_chunk_defaults()
|
||||
rcParams[:chunk_defaults] = defaultParams[:chunk_defaults]
|
||||
return nothing
|
||||
rcParams[:chunk_defaults] = defaultParams[:chunk_defaults]
|
||||
return nothing
|
||||
end
|
||||
|
||||
"""Combine format specific and common options from document header"""
|
||||
|
@ -90,17 +89,28 @@ function combine_args(args, doctype)
|
|||
common
|
||||
end
|
||||
|
||||
getvalue(d::Dict, key , default) = haskey(d, key) ? d[key] : default
|
||||
getvalue(d::Dict, key, default) = haskey(d, key) ? d[key] : default
|
||||
|
||||
"""
|
||||
header_args(doc::WeaveDoc)
|
||||
|
||||
Get weave arguments from document header.
|
||||
"""
|
||||
function header_args(doc::WeaveDoc, out_path, mod, fig_ext, fig_path,
|
||||
cache_path, cache, throw_errors,template,
|
||||
highlight_theme, css,
|
||||
pandoc_options, latex_cmd)
|
||||
function header_args(
|
||||
doc::WeaveDoc,
|
||||
out_path,
|
||||
mod,
|
||||
fig_ext,
|
||||
fig_path,
|
||||
cache_path,
|
||||
cache,
|
||||
throw_errors,
|
||||
template,
|
||||
highlight_theme,
|
||||
css,
|
||||
pandoc_options,
|
||||
latex_cmd,
|
||||
)
|
||||
args = getvalue(doc.header, "options", Dict())
|
||||
doctype = getvalue(args, "doctype", doc.doctype)
|
||||
args = combine_args(args, doctype)
|
||||
|
@ -123,9 +133,23 @@ function header_args(doc::WeaveDoc, out_path, mod, fig_ext, fig_path,
|
|||
pandoc_options = getvalue(args, "pandoc_options", pandoc_options)
|
||||
latex_cmd = getvalue(args, "latex_cmd", latex_cmd)
|
||||
|
||||
return (doctype, informat, out_path, args, mod, fig_path, fig_ext,
|
||||
cache_path, cache, throw_errors, template, highlight_theme, css,
|
||||
pandoc_options, latex_cmd)
|
||||
return (
|
||||
doctype,
|
||||
informat,
|
||||
out_path,
|
||||
args,
|
||||
mod,
|
||||
fig_path,
|
||||
fig_ext,
|
||||
cache_path,
|
||||
cache,
|
||||
throw_errors,
|
||||
template,
|
||||
highlight_theme,
|
||||
css,
|
||||
pandoc_options,
|
||||
latex_cmd,
|
||||
)
|
||||
end
|
||||
|
||||
"""
|
||||
|
@ -136,7 +160,7 @@ Get chunk defaults from header and update.
|
|||
function header_chunk_defaults!(doc::WeaveDoc)
|
||||
for key in keys(doc.chunk_defaults)
|
||||
if haskey(doc.header["options"], String(key))
|
||||
doc.chunk_defaults[key] = doc.header["options"][String(key)]
|
||||
doc.chunk_defaults[key] = doc.header["options"][String(key)]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,51 +1,64 @@
|
|||
using Markdown
|
||||
import .WeaveMarkdown
|
||||
|
||||
#Contains report global properties
|
||||
# Contains report global properties
|
||||
mutable struct Report <: AbstractDisplay
|
||||
cwd::AbstractString
|
||||
basename::AbstractString
|
||||
formatdict::Dict{Symbol,Any}
|
||||
pending_code::AbstractString
|
||||
cur_result::AbstractString
|
||||
rich_output::AbstractString
|
||||
fignum::Int
|
||||
figures::Array{AbstractString}
|
||||
term_state::Symbol
|
||||
cur_chunk
|
||||
mimetypes::Array{AbstractString}
|
||||
first_plot::Bool
|
||||
header_script::String
|
||||
throw_errors::Bool
|
||||
cwd::AbstractString
|
||||
basename::AbstractString
|
||||
formatdict::Dict{Symbol,Any}
|
||||
pending_code::AbstractString
|
||||
cur_result::AbstractString
|
||||
rich_output::AbstractString
|
||||
fignum::Int
|
||||
figures::Array{AbstractString}
|
||||
term_state::Symbol
|
||||
cur_chunk::Any
|
||||
mimetypes::Array{AbstractString}
|
||||
first_plot::Bool
|
||||
header_script::String
|
||||
throw_errors::Bool
|
||||
end
|
||||
|
||||
function Report(cwd, basename, formatdict, mimetypes, throw_errors)
|
||||
Report(cwd, basename, formatdict, "", "", "", 1, AbstractString[], :text, nothing,
|
||||
mimetypes, true, "", throw_errors)
|
||||
Report(
|
||||
cwd,
|
||||
basename,
|
||||
formatdict,
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
1,
|
||||
AbstractString[],
|
||||
:text,
|
||||
nothing,
|
||||
mimetypes,
|
||||
true,
|
||||
"",
|
||||
throw_errors,
|
||||
)
|
||||
end
|
||||
|
||||
|
||||
#Default mimetypes in order, can be overridden for some inside `run method` formats
|
||||
# Default mimetypes in order, can be overridden for some inside `run method` formats
|
||||
const default_mime_types = ["image/svg+xml", "image/png", "text/html", "text/plain"]
|
||||
#const default_mime_types = ["image/png", "image/svg+xml", "text/html", "text/plain"]
|
||||
#From IJulia as a reminder
|
||||
#const supported_mime_types = [ "text/html", "text/latex", "image/svg+xml", "image/png", "image/jpeg", "text/plain", "text/markdown" ]
|
||||
# const default_mime_types = ["image/png", "image/svg+xml", "text/html", "text/plain"]
|
||||
# From IJulia as a reminder
|
||||
# const supported_mime_types = [ "text/html", "text/latex", "image/svg+xml", "image/png", "image/jpeg", "text/plain", "text/markdown" ]
|
||||
|
||||
const mimetype_ext =
|
||||
Dict(".png" => "image/png",
|
||||
".jpg" => "image/jpeg",
|
||||
".jpeg" => "image/jpeg",
|
||||
".svg" => "image/svg+xml",
|
||||
".js.svg" => "image/svg+xml",
|
||||
".pdf" => "application/pdf",
|
||||
".ps" => "application/postscript",
|
||||
".tex" => "text/latex"
|
||||
)
|
||||
const mimetype_ext = Dict(
|
||||
".png" => "image/png",
|
||||
".jpg" => "image/jpeg",
|
||||
".jpeg" => "image/jpeg",
|
||||
".svg" => "image/svg+xml",
|
||||
".js.svg" => "image/svg+xml",
|
||||
".pdf" => "application/pdf",
|
||||
".ps" => "application/postscript",
|
||||
".tex" => "text/latex",
|
||||
)
|
||||
|
||||
function Base.display(report::Report, data)
|
||||
#Set preferred mimetypes for report based on format
|
||||
# Set preferred mimetypes for report based on format
|
||||
fig_ext = report.cur_chunk.options[:fig_ext]
|
||||
for m in unique([mimetype_ext[fig_ext] ; report.mimetypes])
|
||||
for m in unique([mimetype_ext[fig_ext]; report.mimetypes])
|
||||
if Base.invokelatest(showable, m, data)
|
||||
try
|
||||
if !istextmime(m)
|
||||
|
@ -96,9 +109,9 @@ function Base.display(report::Report, m::MIME"text/html", data::Exception)
|
|||
end
|
||||
|
||||
function Base.show(io, m::MIME"text/html", data::Exception)
|
||||
println(io ,"<pre class=\"julia-error\">")
|
||||
println(io, "<pre class=\"julia-error\">")
|
||||
println(io, Markdown.htmlesc("ERROR: " * sprint(showerror, data)))
|
||||
println(io ,"</pre>")
|
||||
println(io, "</pre>")
|
||||
end
|
||||
|
||||
#Catch "rich_output"
|
||||
|
@ -113,7 +126,7 @@ function Base.display(report::Report, m::MIME"text/markdown", data)
|
|||
# Convert to "richer" type of possible
|
||||
for m in report.mimetypes
|
||||
if m == "text/html" || m == "text/latex"
|
||||
display(Markdown.parse(s, flavor=WeaveMarkdown.weavemd))
|
||||
display(Markdown.parse(s, flavor = WeaveMarkdown.weavemd))
|
||||
break
|
||||
elseif m == "text/markdown"
|
||||
report.rich_output *= "\n" * s
|
||||
|
@ -129,18 +142,18 @@ end
|
|||
|
||||
"""Add saved figure name to results and return the name"""
|
||||
function add_figure(report::Report, data, m, ext)
|
||||
chunk = report.cur_chunk
|
||||
full_name, rel_name = get_figname(report, chunk, ext = ext)
|
||||
chunk = report.cur_chunk
|
||||
full_name, rel_name = get_figname(report, chunk, ext = ext)
|
||||
|
||||
open(full_name, "w") do io
|
||||
if ext == ".pdf"
|
||||
write(io, repr(m, data))
|
||||
else
|
||||
show(io, m, data)
|
||||
end
|
||||
end
|
||||
open(full_name, "w") do io
|
||||
if ext == ".pdf"
|
||||
write(io, repr(m, data))
|
||||
else
|
||||
show(io, m, data)
|
||||
end
|
||||
end
|
||||
|
||||
push!(report.figures, rel_name)
|
||||
report.fignum += 1
|
||||
return full_name
|
||||
push!(report.figures, rel_name)
|
||||
report.fignum += 1
|
||||
return full_name
|
||||
end
|
||||
|
|
271
src/format.jl
271
src/format.jl
|
@ -4,12 +4,11 @@ using Dates
|
|||
using Markdown
|
||||
using REPL.REPLCompletions: latex_symbols
|
||||
|
||||
|
||||
function format(doc::WeaveDoc)
|
||||
formatted = AbstractString[]
|
||||
docformat = doc.format
|
||||
|
||||
#Complete format dictionaries with defaults
|
||||
# Complete format dictionaries with defaults
|
||||
formatdict = docformat.formatdict
|
||||
get!(formatdict, :termstart, formatdict[:codestart])
|
||||
get!(formatdict, :termend, formatdict[:codeend])
|
||||
|
@ -18,7 +17,7 @@ function format(doc::WeaveDoc)
|
|||
get!(formatdict, :fig_pos, nothing)
|
||||
get!(formatdict, :fig_env, nothing)
|
||||
|
||||
docformat.formatdict[:cwd] = doc.cwd #pass wd to figure formatters
|
||||
docformat.formatdict[:cwd] = doc.cwd # pass wd to figure formatters
|
||||
docformat.formatdict[:theme] = doc.highlight_theme
|
||||
|
||||
strip_header!(doc)
|
||||
|
@ -41,64 +40,84 @@ end
|
|||
Render formatted document to a template
|
||||
"""
|
||||
function render_doc(formatted, doc::WeaveDoc, format)
|
||||
return formatted
|
||||
return formatted
|
||||
end
|
||||
|
||||
function highlight(mime::MIME, source::AbstractString, lexer, theme=Highlights.Themes.DefaultTheme)
|
||||
return sprint( (io, x) -> Highlights.highlight(io, mime, x, lexer, theme), source)
|
||||
function highlight(
|
||||
mime::MIME,
|
||||
source::AbstractString,
|
||||
lexer,
|
||||
theme = Highlights.Themes.DefaultTheme,
|
||||
)
|
||||
return sprint((io, x) -> Highlights.highlight(io, mime, x, lexer, theme), source)
|
||||
end
|
||||
|
||||
function stylesheet(m::MIME, theme)
|
||||
return sprint( (io, x) -> Highlights.stylesheet(io, m, x), theme)
|
||||
return sprint((io, x) -> Highlights.stylesheet(io, m, x), theme)
|
||||
end
|
||||
|
||||
function render_doc(formatted, doc::WeaveDoc, format::JMarkdown2HTML)
|
||||
css = stylesheet(MIME("text/html"), doc.highlight_theme)
|
||||
path, wsource = splitdir(abspath(doc.source))
|
||||
#wversion = string(Pkg.installed("Weave"))
|
||||
wversion = ""
|
||||
wtime = string(Date(now()))
|
||||
css = stylesheet(MIME("text/html"), doc.highlight_theme)
|
||||
path, wsource = splitdir(abspath(doc.source))
|
||||
# wversion = string(Pkg.installed("Weave"))
|
||||
wversion = ""
|
||||
wtime = string(Date(now()))
|
||||
|
||||
if isempty(doc.css)
|
||||
theme_css = read(joinpath(dirname(@__FILE__), "../templates/skeleton_css.css"), String)
|
||||
else
|
||||
theme_css = read(doc.css, String)
|
||||
end
|
||||
if isempty(doc.css)
|
||||
theme_css =
|
||||
read(joinpath(dirname(@__FILE__), "../templates/skeleton_css.css"), String)
|
||||
else
|
||||
theme_css = read(doc.css, String)
|
||||
end
|
||||
|
||||
if isa(doc.template, Mustache.MustacheTokens)
|
||||
template = doc.template
|
||||
elseif isempty(doc.template)
|
||||
template = Mustache.template_from_file(joinpath(dirname(@__FILE__), "../templates/julia_html.tpl"))
|
||||
else
|
||||
template = Mustache.template_from_file(doc.template)
|
||||
end
|
||||
if isa(doc.template, Mustache.MustacheTokens)
|
||||
template = doc.template
|
||||
elseif isempty(doc.template)
|
||||
template = Mustache.template_from_file(joinpath(
|
||||
dirname(@__FILE__),
|
||||
"../templates/julia_html.tpl",
|
||||
))
|
||||
else
|
||||
template = Mustache.template_from_file(doc.template)
|
||||
end
|
||||
|
||||
return Mustache.render(template; themecss = theme_css,
|
||||
highlightcss = css, body = formatted, header_script = doc.header_script,
|
||||
source = wsource, wtime = wtime, wversion = wversion,
|
||||
[Pair(Symbol(k), v) for (k,v) in doc.header]...)
|
||||
return Mustache.render(
|
||||
template;
|
||||
themecss = theme_css,
|
||||
highlightcss = css,
|
||||
body = formatted,
|
||||
header_script = doc.header_script,
|
||||
source = wsource,
|
||||
wtime = wtime,
|
||||
wversion = wversion,
|
||||
[Pair(Symbol(k), v) for (k, v) in doc.header]...,
|
||||
)
|
||||
end
|
||||
|
||||
function render_doc(formatted, doc::WeaveDoc, format::JMarkdown2tex)
|
||||
highlight = stylesheet(MIME("text/latex"), doc.highlight_theme)
|
||||
path, wsource = splitdir(abspath(doc.source))
|
||||
#wversion = string(Pkg.installed("Weave"))
|
||||
wversion = ""
|
||||
wtime = string(Date(now()))
|
||||
highlight = stylesheet(MIME("text/latex"), doc.highlight_theme)
|
||||
path, wsource = splitdir(abspath(doc.source))
|
||||
# wversion = string(Pkg.installed("Weave"))
|
||||
wversion = ""
|
||||
wtime = string(Date(now()))
|
||||
|
||||
if isa(doc.template, Mustache.MustacheTokens)
|
||||
template = doc.template
|
||||
elseif isempty(doc.template)
|
||||
template = Mustache.template_from_file(joinpath(
|
||||
dirname(@__FILE__),
|
||||
"../templates/julia_tex.tpl",
|
||||
))
|
||||
else
|
||||
template = Mustache.template_from_file(doc.template)
|
||||
end
|
||||
|
||||
|
||||
if isa(doc.template, Mustache.MustacheTokens)
|
||||
template = doc.template
|
||||
elseif isempty(doc.template)
|
||||
template = Mustache.template_from_file(joinpath(dirname(@__FILE__), "../templates/julia_tex.tpl"))
|
||||
else
|
||||
template = Mustache.template_from_file(doc.template)
|
||||
end
|
||||
|
||||
return Mustache.render(template; body = formatted,
|
||||
highlight = highlight,
|
||||
[Pair(Symbol(k), v) for (k,v) in doc.header]...)
|
||||
return Mustache.render(
|
||||
template;
|
||||
body = formatted,
|
||||
highlight = highlight,
|
||||
[Pair(Symbol(k), v) for (k, v) in doc.header]...,
|
||||
)
|
||||
end
|
||||
|
||||
strip_header!(doc::WeaveDoc) = strip_header!(doc.chunks[1], doc.doctype)
|
||||
|
@ -137,10 +156,10 @@ function format_inline(inline::InlineCode)
|
|||
isempty(inline.output) || return inline.output
|
||||
end
|
||||
|
||||
function ioformat!(io::IOBuffer, out::IOBuffer, fun=WeaveMarkdown.latex)
|
||||
function ioformat!(io::IOBuffer, out::IOBuffer, fun = WeaveMarkdown.latex)
|
||||
text = String(take!(io))
|
||||
if !isempty(text)
|
||||
m = Markdown.parse(text, flavor=WeaveMarkdown.weavemd)
|
||||
m = Markdown.parse(text, flavor = WeaveMarkdown.weavemd)
|
||||
write(out, string(fun(m)))
|
||||
end
|
||||
end
|
||||
|
@ -191,15 +210,14 @@ function format_chunk(chunk::DocChunk, formatdict, docformat::JMarkdown2HTML)
|
|||
end
|
||||
|
||||
function format_chunk(chunk::CodeChunk, formatdict, docformat)
|
||||
#Fill undefined options with format specific defaults
|
||||
# Fill undefined options with format specific defaults
|
||||
chunk.options[:out_width] == nothing &&
|
||||
(chunk.options[:out_width] = formatdict[:out_width])
|
||||
chunk.options[:fig_pos] == nothing &&
|
||||
(chunk.options[:fig_pos] = formatdict[:fig_pos])
|
||||
(chunk.options[:out_width] = formatdict[:out_width])
|
||||
chunk.options[:fig_pos] == nothing && (chunk.options[:fig_pos] = formatdict[:fig_pos])
|
||||
|
||||
#Only use floats if chunk has caption or sets fig_env
|
||||
# Only use floats if chunk has caption or sets fig_env
|
||||
if chunk.options[:fig_cap] != nothing && chunk.options[:fig_env] == nothing
|
||||
(chunk.options[:fig_env] = formatdict[:fig_env])
|
||||
(chunk.options[:fig_env] = formatdict[:fig_env])
|
||||
end
|
||||
|
||||
if haskey(formatdict, :indent)
|
||||
|
@ -222,38 +240,41 @@ function format_chunk(chunk::CodeChunk, formatdict, docformat)
|
|||
result = format_termchunk(chunk, formatdict, docformat)
|
||||
else
|
||||
|
||||
if chunk.options[:echo]
|
||||
#Convert to output format and highlight (html, tex...) if needed
|
||||
result = "$(formatdict[:codestart])$(chunk.content)$(formatdict[:codeend])\n"
|
||||
else
|
||||
result = ""
|
||||
end
|
||||
|
||||
if (strip(chunk.output)!= "" || strip(chunk.rich_output) != "") && (chunk.options[:results] != "hidden")
|
||||
if chunk.options[:results] != "markup" && chunk.options[:results] != "hold"
|
||||
strip(chunk.output) ≠ "" && (result *= "$(chunk.output)\n")
|
||||
strip(chunk.rich_output) ≠ "" && (result *= "$(chunk.rich_output)\n")
|
||||
if chunk.options[:echo]
|
||||
# Convert to output format and highlight (html, tex...) if needed
|
||||
result = "$(formatdict[:codestart])$(chunk.content)$(formatdict[:codeend])\n"
|
||||
else
|
||||
if chunk.options[:wrap]
|
||||
chunk.output = "\n" * wraplines(chunk.output, chunk.options[:line_width])
|
||||
chunk.output = format_output(chunk.output, docformat)
|
||||
else
|
||||
chunk.output = "\n" * rstrip(chunk.output)
|
||||
chunk.output = format_output(chunk.output, docformat)
|
||||
end
|
||||
|
||||
if haskey(formatdict, :indent)
|
||||
chunk.output = indent(chunk.output, formatdict[:indent])
|
||||
end
|
||||
strip(chunk.output) ≠ "" &&
|
||||
(result *= "$(formatdict[:outputstart])$(chunk.output)\n$(formatdict[:outputend])\n")
|
||||
strip(chunk.rich_output) ≠ "" && (result *= chunk.rich_output * "\n")
|
||||
result = ""
|
||||
end
|
||||
|
||||
if (strip(chunk.output) != "" || strip(chunk.rich_output) != "") &&
|
||||
(chunk.options[:results] != "hidden")
|
||||
if chunk.options[:results] != "markup" && chunk.options[:results] != "hold"
|
||||
strip(chunk.output) ≠ "" && (result *= "$(chunk.output)\n")
|
||||
strip(chunk.rich_output) ≠ "" && (result *= "$(chunk.rich_output)\n")
|
||||
else
|
||||
if chunk.options[:wrap]
|
||||
chunk.output =
|
||||
"\n" * wraplines(chunk.output, chunk.options[:line_width])
|
||||
chunk.output = format_output(chunk.output, docformat)
|
||||
else
|
||||
chunk.output = "\n" * rstrip(chunk.output)
|
||||
chunk.output = format_output(chunk.output, docformat)
|
||||
end
|
||||
|
||||
if haskey(formatdict, :indent)
|
||||
chunk.output = indent(chunk.output, formatdict[:indent])
|
||||
end
|
||||
strip(chunk.output) ≠ "" && (
|
||||
result *= "$(formatdict[:outputstart])$(chunk.output)\n$(formatdict[:outputend])\n"
|
||||
)
|
||||
strip(chunk.rich_output) ≠ "" && (result *= chunk.rich_output * "\n")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
#Handle figures
|
||||
# Handle figures
|
||||
if chunk.options[:fig] && length(chunk.figures) > 0
|
||||
if chunk.options[:include]
|
||||
result *= formatfigures(chunk, docformat)
|
||||
|
@ -264,34 +285,42 @@ function format_chunk(chunk::CodeChunk, formatdict, docformat)
|
|||
end
|
||||
|
||||
function format_output(result::AbstractString, docformat)
|
||||
return result
|
||||
return result
|
||||
end
|
||||
|
||||
function format_output(result::AbstractString, docformat::JMarkdown2HTML)
|
||||
return Markdown.htmlesc(result)
|
||||
return Markdown.htmlesc(result)
|
||||
end
|
||||
|
||||
function format_output(result::AbstractString, docformat::JMarkdown2tex)
|
||||
# Highligts has some extra escaping defined, eg of $, ", ...
|
||||
result_escaped = sprint( (io, x) -> Highlights.Format.escape(io, MIME("text/latex"), x, charescape=true), result)
|
||||
docformat.formatdict[:keep_unicode] || return uc2tex(result_escaped, true)
|
||||
return result_escaped
|
||||
# Highligts has some extra escaping defined, eg of $, ", ...
|
||||
result_escaped = sprint(
|
||||
(io, x) ->
|
||||
Highlights.Format.escape(io, MIME("text/latex"), x, charescape = true),
|
||||
result,
|
||||
)
|
||||
docformat.formatdict[:keep_unicode] || return uc2tex(result_escaped, true)
|
||||
return result_escaped
|
||||
end
|
||||
|
||||
function format_code(result::AbstractString, docformat)
|
||||
return result
|
||||
return result
|
||||
end
|
||||
|
||||
function format_code(result::AbstractString, docformat::JMarkdown2tex)
|
||||
highlighted = highlight(MIME("text/latex"), strip(result),
|
||||
Highlights.Lexers.JuliaLexer, docformat.formatdict[:theme])
|
||||
docformat.formatdict[:keep_unicode] || return uc2tex(highlighted)
|
||||
return highlighted
|
||||
#return "\\begin{minted}[mathescape, fontsize=\\small, xleftmargin=0.5em]{julia}\n$result\n\\end{minted}\n"
|
||||
highlighted = highlight(
|
||||
MIME("text/latex"),
|
||||
strip(result),
|
||||
Highlights.Lexers.JuliaLexer,
|
||||
docformat.formatdict[:theme],
|
||||
)
|
||||
docformat.formatdict[:keep_unicode] || return uc2tex(highlighted)
|
||||
return highlighted
|
||||
# return "\\begin{minted}[mathescape, fontsize=\\small, xleftmargin=0.5em]{julia}\n$result\n\\end{minted}\n"
|
||||
end
|
||||
|
||||
#Convert unicode to tex, escape listings if needed
|
||||
function uc2tex(s, escape=false)
|
||||
# Convert unicode to tex, escape listings if needed
|
||||
function uc2tex(s, escape = false)
|
||||
for key in keys(latex_symbols)
|
||||
if escape
|
||||
s = replace(s, latex_symbols[key] => "(*@\\ensuremath{$(texify(key))}@*)")
|
||||
|
@ -320,13 +349,21 @@ function texify(s)
|
|||
end
|
||||
|
||||
function format_code(result::AbstractString, docformat::JMarkdown2HTML)
|
||||
return highlight(MIME("text/html"), strip(result),
|
||||
Highlights.Lexers.JuliaLexer, docformat.formatdict[:theme])
|
||||
return highlight(
|
||||
MIME("text/html"),
|
||||
strip(result),
|
||||
Highlights.Lexers.JuliaLexer,
|
||||
docformat.formatdict[:theme],
|
||||
)
|
||||
end
|
||||
|
||||
function format_code(result::AbstractString, docformat::Pandoc2HTML)
|
||||
return highlight(MIME("text/html"), strip(result),
|
||||
Highlights.Lexers.JuliaLexer, docformat.formatdict[:theme])
|
||||
return highlight(
|
||||
MIME("text/html"),
|
||||
strip(result),
|
||||
Highlights.Lexers.JuliaLexer,
|
||||
docformat.formatdict[:theme],
|
||||
)
|
||||
end
|
||||
|
||||
function format_termchunk(chunk, formatdict, docformat)
|
||||
|
@ -340,8 +377,12 @@ end
|
|||
|
||||
function format_termchunk(chunk, formatdict, docformat::JMarkdown2HTML)
|
||||
if chunk.options[:echo] && chunk.options[:results] != "hidden"
|
||||
result = highlight(MIME("text/html"), strip(chunk.output),
|
||||
Highlights.Lexers.JuliaConsoleLexer, docformat.formatdict[:theme])
|
||||
result = highlight(
|
||||
MIME("text/html"),
|
||||
strip(chunk.output),
|
||||
Highlights.Lexers.JuliaConsoleLexer,
|
||||
docformat.formatdict[:theme],
|
||||
)
|
||||
else
|
||||
result = ""
|
||||
end
|
||||
|
@ -350,8 +391,12 @@ end
|
|||
|
||||
function format_termchunk(chunk, formatdict, docformat::Pandoc2HTML)
|
||||
if chunk.options[:echo] && chunk.options[:results] != "hidden"
|
||||
result = highlight(MIME("text/html"), strip(chunk.output),
|
||||
Highlights.Lexers.JuliaConsoleLexer, docformat.formatdict[:theme])
|
||||
result = highlight(
|
||||
MIME("text/html"),
|
||||
strip(chunk.output),
|
||||
Highlights.Lexers.JuliaConsoleLexer,
|
||||
docformat.formatdict[:theme],
|
||||
)
|
||||
else
|
||||
result = ""
|
||||
end
|
||||
|
@ -360,10 +405,13 @@ end
|
|||
|
||||
function format_termchunk(chunk, formatdict, docformat::JMarkdown2tex)
|
||||
if chunk.options[:echo] && chunk.options[:results] != "hidden"
|
||||
result = highlight(MIME("text/latex"), strip(chunk.output),
|
||||
Highlights.Lexers.JuliaConsoleLexer,
|
||||
docformat.formatdict[:theme])
|
||||
#return "\\begin{minted}[mathescape, fontsize=\\small, xleftmargin=0.5em]{julia}\n$result\n\\end{minted}\n"
|
||||
result = highlight(
|
||||
MIME("text/latex"),
|
||||
strip(chunk.output),
|
||||
Highlights.Lexers.JuliaConsoleLexer,
|
||||
docformat.formatdict[:theme],
|
||||
)
|
||||
# return "\\begin{minted}[mathescape, fontsize=\\small, xleftmargin=0.5em]{julia}\n$result\n\\end{minted}\n"
|
||||
else
|
||||
result = ""
|
||||
end
|
||||
|
@ -371,11 +419,10 @@ function format_termchunk(chunk, formatdict, docformat::JMarkdown2tex)
|
|||
end
|
||||
|
||||
function indent(text, nindent)
|
||||
return join(map(x->
|
||||
string(repeat(" ", nindent), x), split(text, "\n")), "\n")
|
||||
return join(map(x -> string(repeat(" ", nindent), x), split(text, "\n")), "\n")
|
||||
end
|
||||
|
||||
function wraplines(text, line_width=75)
|
||||
function wraplines(text, line_width = 75)
|
||||
result = AbstractString[]
|
||||
lines = split(text, "\n")
|
||||
for line in lines
|
||||
|
@ -389,11 +436,11 @@ function wraplines(text, line_width=75)
|
|||
return strip(join(result, "\n"))
|
||||
end
|
||||
|
||||
function wrapline(text, line_width=75)
|
||||
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)
|
||||
result *= first(text, line_width) * "\n"
|
||||
text = chop(text, head = line_width, tail = 0)
|
||||
end
|
||||
result *= text
|
||||
end
|
||||
|
|
|
@ -5,94 +5,116 @@ struct Tex
|
|||
formatdict::Dict{Symbol,Any}
|
||||
end
|
||||
|
||||
const tex = Tex("Latex with custom code environments",
|
||||
Dict{Symbol,Any}(:codestart => "\\begin{juliacode}",
|
||||
:codeend => "\\end{juliacode}",
|
||||
:outputstart => "\\begin{juliaout}",
|
||||
:outputend => "\\end{juliaout}",
|
||||
:termstart => "\\begin{juliaterm}",
|
||||
:termend => "\\end{juliaterm}",
|
||||
:fig_ext => ".pdf",
|
||||
:extension =>"tex",
|
||||
:out_width=> "\\linewidth",
|
||||
:fig_env=> "figure",
|
||||
:fig_pos => "htpb",
|
||||
:doctype => "tex",
|
||||
:mimetypes => ["application/pdf", "image/png", "text/latex", "text/plain"],
|
||||
:keep_unicode => false,
|
||||
))
|
||||
const tex = Tex(
|
||||
"Latex with custom code environments",
|
||||
Dict{Symbol,Any}(
|
||||
:codestart => "\\begin{juliacode}",
|
||||
:codeend => "\\end{juliacode}",
|
||||
:outputstart => "\\begin{juliaout}",
|
||||
:outputend => "\\end{juliaout}",
|
||||
:termstart => "\\begin{juliaterm}",
|
||||
:termend => "\\end{juliaterm}",
|
||||
:fig_ext => ".pdf",
|
||||
:extension => "tex",
|
||||
:out_width => "\\linewidth",
|
||||
:fig_env => "figure",
|
||||
:fig_pos => "htpb",
|
||||
:doctype => "tex",
|
||||
:mimetypes => ["application/pdf", "image/png", "text/latex", "text/plain"],
|
||||
:keep_unicode => false,
|
||||
),
|
||||
)
|
||||
|
||||
const texminted = Tex("Latex using minted for highlighting",
|
||||
Dict{Symbol,Any}(
|
||||
:codestart => "\\begin{minted}[mathescape, fontsize=\\small, xleftmargin=0.5em]{julia}",
|
||||
:codeend => "\\end{minted}",
|
||||
:outputstart => "\\begin{minted}[fontsize=\\small, xleftmargin=0.5em, mathescape, frame = leftline]{text}",
|
||||
:outputend => "\\end{minted}",
|
||||
:termstart=> "\\begin{minted}[fontsize=\\footnotesize, xleftmargin=0.5em, mathescape]{jlcon}",
|
||||
:termend => "\\end{minted}",
|
||||
:fig_ext => ".pdf",
|
||||
:extension =>"tex",
|
||||
:out_width => "\\linewidth",
|
||||
:fig_env=> "figure",
|
||||
:fig_pos => "htpb",
|
||||
:doctype => "texminted",
|
||||
:mimetypes => ["application/pdf", "image/png", "text/latex", "text/plain"],
|
||||
:keep_unicode => false,
|
||||
))
|
||||
const texminted = Tex(
|
||||
"Latex using minted for highlighting",
|
||||
Dict{Symbol,Any}(
|
||||
:codestart =>
|
||||
"\\begin{minted}[mathescape, fontsize=\\small, xleftmargin=0.5em]{julia}",
|
||||
:codeend => "\\end{minted}",
|
||||
:outputstart =>
|
||||
"\\begin{minted}[fontsize=\\small, xleftmargin=0.5em, mathescape, frame = leftline]{text}",
|
||||
:outputend => "\\end{minted}",
|
||||
:termstart =>
|
||||
"\\begin{minted}[fontsize=\\footnotesize, xleftmargin=0.5em, mathescape]{jlcon}",
|
||||
:termend => "\\end{minted}",
|
||||
:fig_ext => ".pdf",
|
||||
:extension => "tex",
|
||||
:out_width => "\\linewidth",
|
||||
:fig_env => "figure",
|
||||
:fig_pos => "htpb",
|
||||
:doctype => "texminted",
|
||||
:mimetypes => ["application/pdf", "image/png", "text/latex", "text/plain"],
|
||||
:keep_unicode => false,
|
||||
),
|
||||
)
|
||||
|
||||
struct Pandoc
|
||||
description::AbstractString
|
||||
formatdict::Dict{Symbol,Any}
|
||||
description::AbstractString
|
||||
formatdict::Dict{Symbol,Any}
|
||||
end
|
||||
|
||||
|
||||
const pandoc = Pandoc("Pandoc markdown",
|
||||
Dict{Symbol,Any}(
|
||||
:codestart => "~~~~{.julia}",
|
||||
:codeend=>"~~~~~~~~~~~~~\n\n",
|
||||
:outputstart=>"~~~~",
|
||||
:outputend=>"~~~~\n\n",
|
||||
:fig_ext=>".png",
|
||||
:out_width=>nothing,
|
||||
:extension=>"md",
|
||||
#Prefer png figures for markdown conversion, svg doesn't work with latex
|
||||
:mimetypes => ["image/png", "image/jpg", "image/svg+xml", "text/markdown", "text/plain"],
|
||||
:doctype=>"pandoc"
|
||||
))
|
||||
const pandoc = Pandoc(
|
||||
"Pandoc markdown",
|
||||
Dict{Symbol,Any}(
|
||||
:codestart => "~~~~{.julia}",
|
||||
:codeend => "~~~~~~~~~~~~~\n\n",
|
||||
:outputstart => "~~~~",
|
||||
:outputend => "~~~~\n\n",
|
||||
:fig_ext => ".png",
|
||||
:out_width => nothing,
|
||||
:extension => "md",
|
||||
# Prefer png figures for markdown conversion, svg doesn't work with latex
|
||||
:mimetypes =>
|
||||
["image/png", "image/jpg", "image/svg+xml", "text/markdown", "text/plain"],
|
||||
:doctype => "pandoc",
|
||||
),
|
||||
)
|
||||
|
||||
struct Pandoc2HTML
|
||||
description::AbstractString
|
||||
formatdict::Dict{Symbol,Any}
|
||||
end
|
||||
|
||||
const pdoc2html = Pandoc2HTML("Markdown to HTML (requires Pandoc 2)",
|
||||
Dict{Symbol,Any}(
|
||||
:codestart => "\n",
|
||||
:codeend=> "\n",
|
||||
:outputstart=> "\n",
|
||||
:outputend=> "\n",
|
||||
:fig_ext=> ".png",
|
||||
:extension=> "md",
|
||||
:mimetypes => ["image/png", "image/svg+xml", "image/jpg",
|
||||
"text/html", "text/markdown", "text/plain"],
|
||||
:doctype=> "pandoc2html"))
|
||||
const pdoc2html = Pandoc2HTML(
|
||||
"Markdown to HTML (requires Pandoc 2)",
|
||||
Dict{Symbol,Any}(
|
||||
:codestart => "\n",
|
||||
:codeend => "\n",
|
||||
:outputstart => "\n",
|
||||
:outputend => "\n",
|
||||
:fig_ext => ".png",
|
||||
:extension => "md",
|
||||
:mimetypes => [
|
||||
"image/png",
|
||||
"image/svg+xml",
|
||||
"image/jpg",
|
||||
"text/html",
|
||||
"text/markdown",
|
||||
"text/plain",
|
||||
],
|
||||
:doctype => "pandoc2html",
|
||||
),
|
||||
)
|
||||
|
||||
struct GitHubMarkdown
|
||||
description::AbstractString
|
||||
formatdict::Dict{Symbol,Any}
|
||||
description::AbstractString
|
||||
formatdict::Dict{Symbol,Any}
|
||||
end
|
||||
|
||||
const github = GitHubMarkdown("GitHub markdown",
|
||||
Dict{Symbol,Any}(
|
||||
:codestart => "````julia",
|
||||
:codeend=> "````\n\n",
|
||||
:outputstart=> "````",
|
||||
:outputend=> "````\n\n",
|
||||
:fig_ext=> ".png",
|
||||
:extension=> "md",
|
||||
:mimetypes => ["image/png", "image/svg+xml", "image/jpg", "text/markdown", "text/plain"],
|
||||
:doctype=> "github"
|
||||
))
|
||||
const github = GitHubMarkdown(
|
||||
"GitHub markdown",
|
||||
Dict{Symbol,Any}(
|
||||
:codestart => "````julia",
|
||||
:codeend => "````\n\n",
|
||||
:outputstart => "````",
|
||||
:outputend => "````\n\n",
|
||||
:fig_ext => ".png",
|
||||
:extension => "md",
|
||||
:mimetypes =>
|
||||
["image/png", "image/svg+xml", "image/jpg", "text/markdown", "text/plain"],
|
||||
:doctype => "github",
|
||||
),
|
||||
)
|
||||
|
||||
"""
|
||||
Formatter for Hugo: https://gohugo.io/
|
||||
|
@ -105,57 +127,79 @@ struct Hugo
|
|||
uglyURLs::Bool
|
||||
end
|
||||
|
||||
const hugo = Hugo("Hugo markdown (using shortcodes)",
|
||||
Dict{Symbol,Any}(
|
||||
:codestart => "````julia",
|
||||
:codeend => "````\n\n",
|
||||
:outputstart => "````",
|
||||
:outputend => "````\n\n",
|
||||
:fig_ext => ".png",
|
||||
:extension => "md",
|
||||
:doctype => "hugo"),
|
||||
false)
|
||||
const hugo = Hugo(
|
||||
"Hugo markdown (using shortcodes)",
|
||||
Dict{Symbol,Any}(
|
||||
:codestart => "````julia",
|
||||
:codeend => "````\n\n",
|
||||
:outputstart => "````",
|
||||
:outputend => "````\n\n",
|
||||
:fig_ext => ".png",
|
||||
:extension => "md",
|
||||
:doctype => "hugo",
|
||||
),
|
||||
false,
|
||||
)
|
||||
|
||||
#Julia markdown
|
||||
# Julia markdown
|
||||
struct JMarkdown2HTML
|
||||
description::AbstractString
|
||||
formatdict::Dict{Symbol,Any}
|
||||
description::AbstractString
|
||||
formatdict::Dict{Symbol,Any}
|
||||
end
|
||||
|
||||
const md2html = JMarkdown2HTML("Julia markdown to html", Dict{Symbol,Any}(
|
||||
const md2html = JMarkdown2HTML(
|
||||
"Julia markdown to html",
|
||||
Dict{Symbol,Any}(
|
||||
:codestart => "\n",
|
||||
:codeend=> "\n",
|
||||
:outputstart=> "<pre class=\"output\">",
|
||||
:outputend=> "</pre>\n",
|
||||
:fig_ext=> ".png",
|
||||
:mimetypes => ["image/png", "image/jpg", "image/svg+xml",
|
||||
"text/html", "text/markdown", "text/plain"],
|
||||
:extension=> "html",
|
||||
:doctype=> "md2html"))
|
||||
:codeend => "\n",
|
||||
:outputstart => "<pre class=\"output\">",
|
||||
:outputend => "</pre>\n",
|
||||
:fig_ext => ".png",
|
||||
:mimetypes => [
|
||||
"image/png",
|
||||
"image/jpg",
|
||||
"image/svg+xml",
|
||||
"text/html",
|
||||
"text/markdown",
|
||||
"text/plain",
|
||||
],
|
||||
:extension => "html",
|
||||
:doctype => "md2html",
|
||||
),
|
||||
)
|
||||
|
||||
#Julia markdown
|
||||
# Julia markdown
|
||||
struct JMarkdown2tex
|
||||
description::AbstractString
|
||||
formatdict::Dict{Symbol,Any}
|
||||
end
|
||||
|
||||
const md2tex = JMarkdown2tex("Julia markdown to latex", Dict{Symbol,Any}(
|
||||
const md2tex = JMarkdown2tex(
|
||||
"Julia markdown to latex",
|
||||
Dict{Symbol,Any}(
|
||||
:codestart => "",
|
||||
:codeend=> "",
|
||||
:outputstart=> "\\begin{lstlisting}",
|
||||
:outputend=> "\\end{lstlisting}\n",
|
||||
:fig_ext=> ".pdf",
|
||||
:extension=> "tex",
|
||||
:codeend => "",
|
||||
:outputstart => "\\begin{lstlisting}",
|
||||
:outputend => "\\end{lstlisting}\n",
|
||||
:fig_ext => ".pdf",
|
||||
:extension => "tex",
|
||||
:out_width => "\\linewidth",
|
||||
:mimetypes => ["application/pdf", "image/png", "image/jpg", "text/latex",
|
||||
"text/markdown", "text/plain"],
|
||||
:doctype=> "md2tex",
|
||||
:keep_unicode=>false))
|
||||
|
||||
:mimetypes => [
|
||||
"application/pdf",
|
||||
"image/png",
|
||||
"image/jpg",
|
||||
"text/latex",
|
||||
"text/markdown",
|
||||
"text/plain",
|
||||
],
|
||||
:doctype => "md2tex",
|
||||
:keep_unicode => false,
|
||||
),
|
||||
)
|
||||
|
||||
struct MultiMarkdown
|
||||
description::AbstractString
|
||||
formatdict::Dict{Symbol,Any}
|
||||
description::AbstractString
|
||||
formatdict::Dict{Symbol,Any}
|
||||
end
|
||||
|
||||
function formatfigures(chunk, docformat::JMarkdown2HTML)
|
||||
|
@ -168,19 +212,18 @@ function formatfigures(chunk, docformat::JMarkdown2HTML)
|
|||
result = ""
|
||||
figstring = ""
|
||||
|
||||
#Set size
|
||||
# Set size
|
||||
attribs = ""
|
||||
width == nothing || (attribs = "width=\"$width\"")
|
||||
(attribs != "" && height != nothing ) && (attribs *= ",")
|
||||
height == nothing || (attribs *= " height=\"$height\" ")
|
||||
(attribs != "" && height != nothing) && (attribs *= ",")
|
||||
height == nothing || (attribs *= " height=\"$height\" ")
|
||||
|
||||
if caption != nothing
|
||||
result *= """<figure>\n"""
|
||||
end
|
||||
|
||||
for fig = fignames
|
||||
|
||||
figstring *= """<img src="$fig" $attribs />\n"""
|
||||
for fig in fignames
|
||||
figstring *= """<img src="$fig" $attribs />\n"""
|
||||
end
|
||||
|
||||
result *= figstring
|
||||
|
@ -195,47 +238,51 @@ function formatfigures(chunk, docformat::JMarkdown2HTML)
|
|||
result *= "</figure>\n"
|
||||
end
|
||||
|
||||
return result
|
||||
return result
|
||||
end
|
||||
|
||||
const multimarkdown = MultiMarkdown("MultiMarkdown",
|
||||
Dict{Symbol,Any}(
|
||||
:codestart => "````julia",
|
||||
:codeend=> "````\n\n",
|
||||
:outputstart=> "````",
|
||||
:outputend=> "````\n\n",
|
||||
:fig_ext=> ".png",
|
||||
:extension=> "md",
|
||||
:doctype=> "github"
|
||||
))
|
||||
|
||||
const multimarkdown = MultiMarkdown(
|
||||
"MultiMarkdown",
|
||||
Dict{Symbol,Any}(
|
||||
:codestart => "````julia",
|
||||
:codeend => "````\n\n",
|
||||
:outputstart => "````",
|
||||
:outputend => "````\n\n",
|
||||
:fig_ext => ".png",
|
||||
:extension => "md",
|
||||
:doctype => "github",
|
||||
),
|
||||
)
|
||||
|
||||
struct Rest
|
||||
description::AbstractString
|
||||
formatdict::Dict{Symbol,Any}
|
||||
end
|
||||
|
||||
const rst = Rest("reStructuredText and Sphinx",
|
||||
Dict{Symbol,Any}(
|
||||
:codestart => ".. code-block:: julia\n",
|
||||
:codeend => "\n\n",
|
||||
:outputstart => "::\n",
|
||||
:outputend => "\n\n",
|
||||
:indent=> 4,
|
||||
:fig_ext => ".png",
|
||||
:extension => "rst",
|
||||
:out_width => "15 cm",
|
||||
:doctype => "rst"
|
||||
))
|
||||
const rst = Rest(
|
||||
"reStructuredText and Sphinx",
|
||||
Dict{Symbol,Any}(
|
||||
:codestart => ".. code-block:: julia\n",
|
||||
:codeend => "\n\n",
|
||||
:outputstart => "::\n",
|
||||
:outputend => "\n\n",
|
||||
:indent => 4,
|
||||
:fig_ext => ".png",
|
||||
:extension => "rst",
|
||||
:out_width => "15 cm",
|
||||
:doctype => "rst",
|
||||
),
|
||||
)
|
||||
|
||||
struct AsciiDoc
|
||||
description::AbstractString
|
||||
formatdict::Dict{Symbol,Any}
|
||||
end
|
||||
|
||||
#asciidoc -b html5 -a source-highlighter=pygments ...
|
||||
const adoc = AsciiDoc("AsciiDoc",
|
||||
Dict{Symbol,Any}(
|
||||
# asciidoc -b html5 -a source-highlighter=pygments ...
|
||||
const adoc = AsciiDoc(
|
||||
"AsciiDoc",
|
||||
Dict{Symbol,Any}(
|
||||
:codestart => "[source,julia]\n--------------------------------------",
|
||||
:codeend => "--------------------------------------\n\n",
|
||||
:outputstart => "--------------------------------------",
|
||||
|
@ -243,78 +290,76 @@ const adoc = AsciiDoc("AsciiDoc",
|
|||
:fig_ext => ".png",
|
||||
:extension => "txt",
|
||||
:out_width => "600",
|
||||
:doctype => "asciidoc"
|
||||
))
|
||||
:doctype => "asciidoc",
|
||||
),
|
||||
)
|
||||
|
||||
function md_length_to_latex(def,reference)
|
||||
if occursin("%",def)
|
||||
_def = tryparse(Float64,replace(def,"%"=>""))
|
||||
function md_length_to_latex(def, reference)
|
||||
if occursin("%", def)
|
||||
_def = tryparse(Float64, replace(def, "%" => ""))
|
||||
_def == nothing && return def
|
||||
perc = round(_def/100,digits=2)
|
||||
perc = round(_def / 100, digits = 2)
|
||||
return "$perc$reference"
|
||||
end
|
||||
return def
|
||||
end
|
||||
|
||||
function formatfigures(chunk, docformat::Union{Tex,JMarkdown2tex})
|
||||
fignames = chunk.figures
|
||||
caption = chunk.options[:fig_cap]
|
||||
width = chunk.options[:out_width]
|
||||
height = chunk.options[:out_height]
|
||||
f_pos = chunk.options[:fig_pos]
|
||||
f_env = chunk.options[:fig_env]
|
||||
result = ""
|
||||
figstring = ""
|
||||
fignames = chunk.figures
|
||||
caption = chunk.options[:fig_cap]
|
||||
width = chunk.options[:out_width]
|
||||
height = chunk.options[:out_height]
|
||||
f_pos = chunk.options[:fig_pos]
|
||||
f_env = chunk.options[:fig_env]
|
||||
result = ""
|
||||
figstring = ""
|
||||
|
||||
if f_env == nothing && caption != nothing
|
||||
f_env = "figure"
|
||||
end
|
||||
if f_env == nothing && caption != nothing
|
||||
f_env = "figure"
|
||||
end
|
||||
|
||||
(f_pos == nothing) && (f_pos = "!h")
|
||||
#Set size
|
||||
attribs = ""
|
||||
width == nothing || (attribs = "width=$(md_length_to_latex(width,"\\linewidth"))")
|
||||
(attribs != "" && height != nothing ) && (attribs *= ",")
|
||||
height == nothing || (attribs *= "height=$(md_length_to_latex(height,"\\paperheight"))")
|
||||
(f_pos == nothing) && (f_pos = "!h")
|
||||
# Set size
|
||||
attribs = ""
|
||||
width == nothing || (attribs = "width=$(md_length_to_latex(width,"\\linewidth"))")
|
||||
(attribs != "" && height != nothing) && (attribs *= ",")
|
||||
height == nothing || (attribs *= "height=$(md_length_to_latex(height,"\\paperheight"))")
|
||||
|
||||
if f_env != nothing
|
||||
result *= "\\begin{$f_env}"
|
||||
(f_pos != "") && (result *= "[$f_pos]")
|
||||
result *= "\n"
|
||||
end
|
||||
result *= "\\begin{$f_env}"
|
||||
(f_pos != "") && (result *= "[$f_pos]")
|
||||
result *= "\n"
|
||||
end
|
||||
|
||||
for fig = fignames
|
||||
if splitext(fig)[2] == ".tex" #Tikz figures
|
||||
figstring *= "\\resizebox{$width}{!}{\\input{$fig}}\n"
|
||||
else
|
||||
if isempty(attribs)
|
||||
figstring *= "\\includegraphics{$fig}\n"
|
||||
else
|
||||
figstring *= "\\includegraphics[$attribs]{$fig}\n"
|
||||
end
|
||||
end
|
||||
end
|
||||
for fig in fignames
|
||||
if splitext(fig)[2] == ".tex" # Tikz figures
|
||||
figstring *= "\\resizebox{$width}{!}{\\input{$fig}}\n"
|
||||
else
|
||||
if isempty(attribs)
|
||||
figstring *= "\\includegraphics{$fig}\n"
|
||||
else
|
||||
figstring *= "\\includegraphics[$attribs]{$fig}\n"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Figure environment
|
||||
if caption != nothing
|
||||
result *= string("\\center\n",
|
||||
"$figstring",
|
||||
"\\caption{$caption}\n")
|
||||
else
|
||||
result *= figstring
|
||||
end
|
||||
# Figure environment
|
||||
if caption != nothing
|
||||
result *= string("\\center\n", "$figstring", "\\caption{$caption}\n")
|
||||
else
|
||||
result *= figstring
|
||||
end
|
||||
|
||||
if chunk.options[:label] != nothing && f_env !=nothing
|
||||
label = chunk.options[:label]
|
||||
result *= "\\label{fig:$label}\n"
|
||||
end
|
||||
if chunk.options[:label] != nothing && f_env != nothing
|
||||
label = chunk.options[:label]
|
||||
result *= "\\label{fig:$label}\n"
|
||||
end
|
||||
|
||||
if f_env != nothing
|
||||
result *= "\\end{$f_env}\n"
|
||||
end
|
||||
|
||||
if f_env != nothing
|
||||
result *= "\\end{$f_env}\n"
|
||||
end
|
||||
|
||||
return result
|
||||
return result
|
||||
end
|
||||
|
||||
formatfigures(chunk, docformat::Pandoc2HTML) = formatfigures(chunk, pandoc)
|
||||
|
@ -331,16 +376,16 @@ function formatfigures(chunk, docformat::Pandoc)
|
|||
width = chunk.options[:out_width]
|
||||
height = chunk.options[:out_height]
|
||||
|
||||
#Build figure attibutes
|
||||
# Build figure attibutes
|
||||
attribs = String[]
|
||||
width == nothing || push!(attribs, "width=$width")
|
||||
width == nothing || push!(attribs, "width=$width")
|
||||
height == nothing || push!(attribs, "height=$height")
|
||||
label == nothing || push!(attribs, "#fig:$label")
|
||||
label == nothing || push!(attribs, "#fig:$label")
|
||||
attribs = isempty(attribs) ? "" : "{" * join(attribs, " ") * "}"
|
||||
|
||||
if caption != nothing
|
||||
result *= "![$caption]($(fignames[1]))$attribs\n"
|
||||
for fig = fignames[2:end]
|
||||
for fig in fignames[2:end]
|
||||
result *= "![]($fig)$attribs\n"
|
||||
println("Warning, only the first figure gets a caption\n")
|
||||
end
|
||||
|
@ -362,7 +407,7 @@ function formatfigures(chunk, docformat::GitHubMarkdown)
|
|||
|
||||
if caption != nothing
|
||||
result *= "![$caption]($(fignames[1]))\n"
|
||||
for fig = fignames[2:end]
|
||||
for fig in fignames[2:end]
|
||||
result *= "![]($fig)\n"
|
||||
println("Warning, only the first figure gets a caption\n")
|
||||
end
|
||||
|
@ -387,7 +432,7 @@ function formatfigures(chunk, docformat::Hugo)
|
|||
end
|
||||
"{{< figure src=\"$(joinpath(relpath, fig))\" $(title_spec) >}}"
|
||||
end
|
||||
mapreduce(format_shortcode, *, enumerate(chunk.figures), init="")
|
||||
mapreduce(format_shortcode, *, enumerate(chunk.figures), init = "")
|
||||
end
|
||||
|
||||
function formatfigures(chunk, docformat::MultiMarkdown)
|
||||
|
@ -397,25 +442,25 @@ function formatfigures(chunk, docformat::MultiMarkdown)
|
|||
figstring = ""
|
||||
|
||||
if chunk.options[:out_width] == nothing
|
||||
width = ""
|
||||
width = ""
|
||||
else
|
||||
width = "width=$(chunk.options[:out_width])"
|
||||
width = "width=$(chunk.options[:out_width])"
|
||||
end
|
||||
|
||||
length(fignames) > 0 || (return "")
|
||||
|
||||
if caption != nothing
|
||||
result *= "![$caption][$(fignames[1])]\n\n"
|
||||
result *= "[$(fignames[1])]: $(fignames[1]) $width\n"
|
||||
for fig = fignames[2:end]
|
||||
result *= "![][$fig]\n\n"
|
||||
result *= "[$fig]: $fig $width\n"
|
||||
println("Warning, only the first figure gets a caption\n")
|
||||
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"
|
||||
result *= "![][$fig]\n\n"
|
||||
result *= "[$fig]: $fig $width\n"
|
||||
end
|
||||
end
|
||||
return result
|
||||
|
@ -428,14 +473,16 @@ function formatfigures(chunk, docformat::Rest)
|
|||
result = ""
|
||||
figstring = ""
|
||||
|
||||
for fig=fignames
|
||||
for fig in fignames
|
||||
figstring *= @sprintf(".. image:: %s\n :width: %s\n\n", fig, width)
|
||||
end
|
||||
|
||||
if caption != nothing
|
||||
result *= string(".. figure:: $(fignames[1])\n",
|
||||
" :width: $width\n\n",
|
||||
" $caption\n\n")
|
||||
result *= string(
|
||||
".. figure:: $(fignames[1])\n",
|
||||
" :width: $width\n\n",
|
||||
" $caption\n\n",
|
||||
)
|
||||
else
|
||||
result *= figstring
|
||||
return result
|
||||
|
@ -449,34 +496,31 @@ function formatfigures(chunk, docformat::AsciiDoc)
|
|||
result = ""
|
||||
figstring = ""
|
||||
|
||||
|
||||
for fig=fignames
|
||||
for fig in fignames
|
||||
figstring *= @sprintf("image::%s[width=%s]\n", fig, width)
|
||||
end
|
||||
|
||||
|
||||
if caption != nothing
|
||||
result *= string("image::$(fignames[1])",
|
||||
"[width=$width,",
|
||||
"title=\"$caption\"]")
|
||||
result *= string("image::$(fignames[1])", "[width=$width,", "title=\"$caption\"]")
|
||||
else
|
||||
result *= figstring
|
||||
return result
|
||||
end
|
||||
end
|
||||
|
||||
#Add new supported formats here
|
||||
const formats = Dict{AbstractString, Any}("tex" => tex,
|
||||
"texminted" => texminted,
|
||||
"pandoc" => pandoc,
|
||||
"pandoc2html" => pdoc2html,
|
||||
"pandoc2pdf" => pandoc,
|
||||
"md2pdf" => md2tex,
|
||||
"github" => github,
|
||||
"hugo" => hugo,
|
||||
"multimarkdown" => multimarkdown,
|
||||
"rst" => rst,
|
||||
"asciidoc" => adoc,
|
||||
"md2html" => md2html,
|
||||
"md2tex" => md2tex
|
||||
)
|
||||
# Add new supported formats here
|
||||
const formats = Dict{AbstractString,Any}(
|
||||
"tex" => tex,
|
||||
"texminted" => texminted,
|
||||
"pandoc" => pandoc,
|
||||
"pandoc2html" => pdoc2html,
|
||||
"pandoc2pdf" => pandoc,
|
||||
"md2pdf" => md2tex,
|
||||
"github" => github,
|
||||
"hugo" => hugo,
|
||||
"multimarkdown" => multimarkdown,
|
||||
"rst" => rst,
|
||||
"asciidoc" => adoc,
|
||||
"md2html" => md2html,
|
||||
"md2tex" => md2tex,
|
||||
)
|
||||
|
|
|
@ -21,13 +21,13 @@ function Base.display(report::Weave.Report, m::MIME"image/png", p::Gadfly.Plot)
|
|||
display(report, MIME("image/svg+xml"), p)
|
||||
end
|
||||
|
||||
#Gadfly doesn't call the default display methods, this catches
|
||||
#all Gadfly plots
|
||||
# Gadfly doesn't call the default display methods, this catches
|
||||
# all Gadfly plots
|
||||
function Base.display(report::Weave.Report, m::MIME"image/svg+xml", p::Gadfly.Plot)
|
||||
chunk = report.cur_chunk
|
||||
|
||||
w = chunk.options[:fig_width]Gadfly.inch
|
||||
h = chunk.options[:fig_height]Gadfly.inch
|
||||
w = chunk.options[:fig_width] * Gadfly.inch
|
||||
h = chunk.options[:fig_height] * Gadfly.inch
|
||||
format = chunk.options[:fig_ext]
|
||||
dpi = chunk.options[:dpi]
|
||||
|
||||
|
@ -41,13 +41,13 @@ function Base.display(report::Weave.Report, m::MIME"image/svg+xml", p::Gadfly.Pl
|
|||
elseif format == ".js.svg"
|
||||
Gadfly.draw(Gadfly.SVGJS(full_name, w, h), p)
|
||||
elseif format == ".png"
|
||||
Gadfly.draw(Gadfly.PNG(full_name, w, h, dpi=dpi), p)
|
||||
Gadfly.draw(Gadfly.PNG(full_name, w, h, dpi = dpi), p)
|
||||
elseif format == ".pdf"
|
||||
Gadfly.draw(Gadfly.PDF(full_name, w, h), p)
|
||||
elseif format == ".ps"
|
||||
Gadfly.draw(Gadfly.PS(full_name, w, h), p)
|
||||
elseif format == ".tex"
|
||||
Gadfly.draw(Gadfly.PGF(full_name, w, h, true ), p)
|
||||
Gadfly.draw(Gadfly.PGF(full_name, w, h, true), p)
|
||||
else
|
||||
@warn("Can't save figure. Unsupported format, $format")
|
||||
end
|
||||
|
|
213
src/pandoc.jl
213
src/pandoc.jl
|
@ -1,61 +1,65 @@
|
|||
|
||||
|
||||
"""
|
||||
`pandoc2html(formatted::AbstractString, doc::WeaveDoc)`
|
||||
|
||||
Convert output from pandoc markdown to html using Weave.jl template
|
||||
"""
|
||||
function pandoc2html(formatted::AbstractString, doc::WeaveDoc, outname::AbstractString, pandoc_options)
|
||||
weavedir = dirname(@__FILE__)
|
||||
html_template = joinpath(weavedir, "../templates/pandoc_skeleton.html")
|
||||
css_template = joinpath(weavedir, "../templates/pandoc_skeleton.css")
|
||||
css = stylesheet(MIME("text/html"), doc.highlight_theme)
|
||||
function pandoc2html(
|
||||
formatted::AbstractString,
|
||||
doc::WeaveDoc,
|
||||
outname::AbstractString,
|
||||
pandoc_options,
|
||||
)
|
||||
weavedir = dirname(@__FILE__)
|
||||
html_template = joinpath(weavedir, "../templates/pandoc_skeleton.html")
|
||||
css_template = joinpath(weavedir, "../templates/pandoc_skeleton.css")
|
||||
css = stylesheet(MIME("text/html"), doc.highlight_theme)
|
||||
|
||||
path, wsource = splitdir(abspath(doc.source))
|
||||
#wversion = string(Pkg.installed("Weave"))
|
||||
wversion = ""
|
||||
wtime = string(Date(now()))
|
||||
path, wsource = splitdir(abspath(doc.source))
|
||||
# wversion = string(Pkg.installed("Weave"))
|
||||
wversion = ""
|
||||
wtime = string(Date(now()))
|
||||
|
||||
#Header is inserted from displayed plots
|
||||
header_script = doc.header_script
|
||||
self_contained = (header_script ≠ "") ? [] : "--self-contained"
|
||||
# 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
|
||||
if haskey(doc.header, "bibliography")
|
||||
filt = "--filter"
|
||||
citeproc = "pandoc-citeproc"
|
||||
else
|
||||
filt = []
|
||||
citeproc = []
|
||||
end
|
||||
|
||||
#Change path for pandoc
|
||||
old_wd = pwd()
|
||||
cd(doc.cwd)
|
||||
html =""
|
||||
outname = basename(outname)
|
||||
# Change path for pandoc
|
||||
old_wd = pwd()
|
||||
cd(doc.cwd)
|
||||
html = ""
|
||||
outname = basename(outname)
|
||||
|
||||
open("temp.md", "w") do io
|
||||
println(io, formatted)
|
||||
end
|
||||
open("temp.md", "w") do io
|
||||
println(io, formatted)
|
||||
end
|
||||
|
||||
try
|
||||
cmd = `pandoc -f markdown+raw_html -s --mathjax=""
|
||||
$filt $citeproc $pandoc_options
|
||||
--template $html_template -H $css_template $self_contained
|
||||
-V wversion=$wversion -V wtime=$wtime -V wsource=$wsource
|
||||
-V highlightcss=$css
|
||||
-V headerscript=$header_script
|
||||
-o $outname`
|
||||
proc = open(cmd, "r+")
|
||||
println(proc.in, formatted)
|
||||
close(proc.in)
|
||||
proc_output = read(proc.out, String)
|
||||
cd(old_wd)
|
||||
catch e
|
||||
cd(old_wd)
|
||||
@warn("Error converting document to HTML")
|
||||
throw(e)
|
||||
end
|
||||
try
|
||||
cmd = `pandoc -f markdown+raw_html -s --mathjax=""
|
||||
$filt $citeproc $pandoc_options
|
||||
--template $html_template -H $css_template $self_contained
|
||||
-V wversion=$wversion -V wtime=$wtime -V wsource=$wsource
|
||||
-V highlightcss=$css
|
||||
-V headerscript=$header_script
|
||||
-o $outname`
|
||||
proc = open(cmd, "r+")
|
||||
println(proc.in, formatted)
|
||||
close(proc.in)
|
||||
proc_output = read(proc.out, String)
|
||||
cd(old_wd)
|
||||
catch e
|
||||
cd(old_wd)
|
||||
@warn("Error converting document to HTML")
|
||||
throw(e)
|
||||
end
|
||||
end
|
||||
|
||||
"""
|
||||
|
@ -63,64 +67,75 @@ end
|
|||
|
||||
Convert output from pandoc markdown to pdf using Weave.jl template
|
||||
"""
|
||||
function pandoc2pdf(formatted::AbstractString, doc::WeaveDoc, outname::AbstractString, pandoc_options)
|
||||
weavedir = dirname(@__FILE__)
|
||||
header_template = joinpath(weavedir, "../templates/pandoc_header.txt")
|
||||
function pandoc2pdf(
|
||||
formatted::AbstractString,
|
||||
doc::WeaveDoc,
|
||||
outname::AbstractString,
|
||||
pandoc_options,
|
||||
)
|
||||
weavedir = dirname(@__FILE__)
|
||||
header_template = joinpath(weavedir, "../templates/pandoc_header.txt")
|
||||
|
||||
path, wsource = splitdir(abspath(doc.source))
|
||||
#wversion = string(Pkg.installed("Weave"))
|
||||
wversion = ""
|
||||
wtime = Date(now())
|
||||
outname = basename(outname)
|
||||
path, wsource = splitdir(abspath(doc.source))
|
||||
# wversion = string(Pkg.installed("Weave"))
|
||||
wversion = ""
|
||||
wtime = Date(now())
|
||||
outname = basename(outname)
|
||||
|
||||
#Change path for pandoc
|
||||
old_wd = pwd()
|
||||
cd(doc.cwd)
|
||||
html =""
|
||||
# Change path for pandoc
|
||||
old_wd = pwd()
|
||||
cd(doc.cwd)
|
||||
html = ""
|
||||
|
||||
if haskey(doc.header, "bibliography")
|
||||
filt = "--filter"
|
||||
citeproc = "pandoc-citeproc"
|
||||
else
|
||||
filt = []
|
||||
citeproc = []
|
||||
end
|
||||
if haskey(doc.header, "bibliography")
|
||||
filt = "--filter"
|
||||
citeproc = "pandoc-citeproc"
|
||||
else
|
||||
filt = []
|
||||
citeproc = []
|
||||
end
|
||||
|
||||
@info("Done executing code. Running xelatex")
|
||||
try
|
||||
cmd = `pandoc -f markdown+raw_tex -s --pdf-engine=xelatex --highlight-style=tango
|
||||
$filt $citeproc $pandoc_options
|
||||
--include-in-header=$header_template
|
||||
-V fontsize=12pt -o $outname`
|
||||
proc = open(cmd, "r+")
|
||||
println(proc.in, formatted)
|
||||
close(proc.in)
|
||||
proc_output = read(proc.out, String)
|
||||
cd(old_wd)
|
||||
catch e
|
||||
cd(old_wd)
|
||||
@warn("Error converting document to pdf")
|
||||
throw(e)
|
||||
end
|
||||
@info("Done executing code. Running xelatex")
|
||||
try
|
||||
cmd = `pandoc -f markdown+raw_tex -s --pdf-engine=xelatex --highlight-style=tango
|
||||
$filt $citeproc $pandoc_options
|
||||
--include-in-header=$header_template
|
||||
-V fontsize=12pt -o $outname`
|
||||
proc = open(cmd, "r+")
|
||||
println(proc.in, formatted)
|
||||
close(proc.in)
|
||||
proc_output = read(proc.out, String)
|
||||
cd(old_wd)
|
||||
catch e
|
||||
cd(old_wd)
|
||||
@warn("Error converting document to pdf")
|
||||
throw(e)
|
||||
end
|
||||
end
|
||||
|
||||
function run_latex(doc::WeaveDoc, outname, latex_cmd = "xelatex")
|
||||
old_wd = pwd()
|
||||
cd(doc.cwd)
|
||||
xname = basename(outname)
|
||||
@info("Weaved code to $outname . Running $latex_cmd") # space before '.' added for link to be clickable in Juno terminal
|
||||
textmp = mktempdir(".")
|
||||
try
|
||||
out = read(`$latex_cmd -shell-escape $xname -aux-directory $textmp -include-directory $(doc.cwd)`, String)
|
||||
out = read(`$latex_cmd -shell-escape $xname -aux-directory $textmp -include-directory $(doc.cwd)`, String)
|
||||
rm(xname)
|
||||
rm(textmp, recursive=true)
|
||||
cd(old_wd)
|
||||
return true
|
||||
catch e
|
||||
@warn("Error converting document to pdf. Try running latex manually")
|
||||
cd(old_wd)
|
||||
rm(textmp)
|
||||
return false
|
||||
end
|
||||
old_wd = pwd()
|
||||
cd(doc.cwd)
|
||||
xname = basename(outname)
|
||||
@info("Weaved code to $outname . Running $latex_cmd") # space before '.' added for link to be clickable in Juno terminal
|
||||
textmp = mktempdir(".")
|
||||
try
|
||||
out = read(
|
||||
`$latex_cmd -shell-escape $xname -aux-directory $textmp -include-directory $(doc.cwd)`,
|
||||
String,
|
||||
)
|
||||
out = read(
|
||||
`$latex_cmd -shell-escape $xname -aux-directory $textmp -include-directory $(doc.cwd)`,
|
||||
String,
|
||||
)
|
||||
rm(xname)
|
||||
rm(textmp, recursive = true)
|
||||
cd(old_wd)
|
||||
return true
|
||||
catch e
|
||||
@warn("Error converting document to pdf. Try running latex manually")
|
||||
cd(old_wd)
|
||||
rm(textmp)
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
|
116
src/plots.jl
116
src/plots.jl
|
@ -6,64 +6,78 @@ import Weave
|
|||
|
||||
"""Pre-execute hooks to set the plot size for the chunk """
|
||||
function plots_set_size(chunk)
|
||||
w = chunk.options[:fig_width] * chunk.options[:dpi]
|
||||
h = chunk.options[:fig_height] * chunk.options[:dpi]
|
||||
Plots.default(size = (w,h))
|
||||
return chunk
|
||||
w = chunk.options[:fig_width] * chunk.options[:dpi]
|
||||
h = chunk.options[:fig_height] * chunk.options[:dpi]
|
||||
Plots.default(size = (w, h))
|
||||
return chunk
|
||||
end
|
||||
|
||||
Weave.push_preexecute_hook(plots_set_size)
|
||||
|
||||
#PNG or SVG is not working, output html
|
||||
function Base.display(report::Weave.Report, m::MIME"image/svg+xml", data::Plots.Plot{Plots.PlotlyBackend})#
|
||||
#Remove extra spaces from start of line for pandoc
|
||||
s = repr(MIME("text/html"), data)
|
||||
splitted = split(s, "\n")
|
||||
start = split(splitted[1], r"(?=<div)")
|
||||
#script = lstrip(start[1]) #local
|
||||
# PNG or SVG is not working, output html
|
||||
function Base.display(
|
||||
report::Weave.Report,
|
||||
m::MIME"image/svg+xml",
|
||||
data::Plots.Plot{Plots.PlotlyBackend},
|
||||
)#
|
||||
# Remove extra spaces from start of line for pandoc
|
||||
s = repr(MIME("text/html"), data)
|
||||
splitted = split(s, "\n")
|
||||
start = split(splitted[1], r"(?=<div)")
|
||||
# script = lstrip(start[1]) # local
|
||||
|
||||
div = lstrip(start[2])
|
||||
plot = join(map(lstrip, splitted[2:end]), "\n")
|
||||
div = lstrip(start[2])
|
||||
plot = join(map(lstrip, splitted[2:end]), "\n")
|
||||
|
||||
if report.first_plot
|
||||
report.header_script *= "<script src=\"https://cdn.plot.ly/plotly-latest.min.js\"></script>"
|
||||
report.first_plot = false
|
||||
end
|
||||
if report.first_plot
|
||||
report.header_script *= "<script src=\"https://cdn.plot.ly/plotly-latest.min.js\"></script>"
|
||||
report.first_plot = false
|
||||
end
|
||||
|
||||
report.rich_output *= "\n" * div * "\n" * plot
|
||||
end
|
||||
|
||||
function Base.display(report::Weave.Report, m::MIME"image/png", data::Plots.Plot{Plots.PlotlyBackend})#
|
||||
display(report, MIME("image/svg+xml"), data)
|
||||
function Base.display(
|
||||
report::Weave.Report,
|
||||
m::MIME"image/png",
|
||||
data::Plots.Plot{Plots.PlotlyBackend},
|
||||
)#
|
||||
display(report, MIME("image/svg+xml"), data)
|
||||
end
|
||||
|
||||
# PNG or SVG is not working, output html
|
||||
function Base.display(
|
||||
report::Weave.Report,
|
||||
m::MIME"image/svg+xml",
|
||||
plot::Plots.Plot{Plots.PlotlyJSBackend},
|
||||
)
|
||||
body = Plots.PlotlyJS.html_body(plot.o.plot)
|
||||
|
||||
#PNG or SVG is not working, output html
|
||||
function Base.display(report::Weave.Report, m::MIME"image/svg+xml", plot::Plots.Plot{Plots.PlotlyJSBackend})
|
||||
body = Plots.PlotlyJS.html_body(plot.o.plot)
|
||||
if report.first_plot
|
||||
report.header_script *= "<script src=\"https://cdn.plot.ly/plotly-latest.min.js\"></script>"
|
||||
report.first_plot = false
|
||||
end
|
||||
|
||||
if report.first_plot
|
||||
report.header_script *= "<script src=\"https://cdn.plot.ly/plotly-latest.min.js\"></script>"
|
||||
report.first_plot = false
|
||||
end
|
||||
|
||||
report.rich_output *= "\n" * body
|
||||
report.rich_output *= "\n" * body
|
||||
end
|
||||
|
||||
function Base.display(report::Weave.Report, m::MIME"image/png", plot::Plots.Plot{Plots.PlotlyJSBackend})
|
||||
display(report, MIME("image/svg+xml"), data)
|
||||
function Base.display(
|
||||
report::Weave.Report,
|
||||
m::MIME"image/png",
|
||||
plot::Plots.Plot{Plots.PlotlyJSBackend},
|
||||
)
|
||||
display(report, MIME("image/svg+xml"), data)
|
||||
end
|
||||
|
||||
|
||||
"""Add saved figure name to results and return the name"""
|
||||
function add_plots_figure(report::Weave.Report, plot::Plots.Plot, ext)
|
||||
chunk = report.cur_chunk
|
||||
full_name, rel_name = Weave.get_figname(report, chunk, ext = ext)
|
||||
chunk = report.cur_chunk
|
||||
full_name, rel_name = Weave.get_figname(report, chunk, ext = ext)
|
||||
|
||||
Plots.savefig(plot, full_name)
|
||||
push!(report.figures, rel_name)
|
||||
report.fignum += 1
|
||||
return full_name
|
||||
Plots.savefig(plot, full_name)
|
||||
push!(report.figures, rel_name)
|
||||
report.fignum += 1
|
||||
return full_name
|
||||
end
|
||||
|
||||
function Base.display(report::Weave.Report, m::MIME"application/pdf", plot::Plots.Plot)
|
||||
|
@ -80,21 +94,21 @@ end
|
|||
|
||||
# write out html to view Animated gif
|
||||
function Base.display(report::Weave.Report, ::MIME"text/html", agif::Plots.AnimatedGif)
|
||||
ext = agif.filename[end-2:end]
|
||||
res = ""
|
||||
if ext == "gif"
|
||||
img = stringmime(MIME("image/gif"), read(agif.filename))
|
||||
res = "<img src=\"data:image/gif;base64,$img\" />"
|
||||
elseif ext in ("mov", "mp4")
|
||||
#Uncomment to embed mp4, make global or chunk option?
|
||||
#img = stringmime(MIME("video/$ext"), read(agif.filename))
|
||||
#res = "<video controls><source src=\"data:video/$(ext);base64,$img\" type=\"video/$ext\"></video>"
|
||||
res = "<video controls><source src=\"$(relpath(agif.filename))\" type=\"video/$ext\"></video>"
|
||||
else
|
||||
error("Cannot show animation with extension $ext: $agif")
|
||||
end
|
||||
ext = agif.filename[end-2:end]
|
||||
res = ""
|
||||
if ext == "gif"
|
||||
img = stringmime(MIME("image/gif"), read(agif.filename))
|
||||
res = "<img src=\"data:image/gif;base64,$img\" />"
|
||||
elseif ext in ("mov", "mp4")
|
||||
# Uncomment to embed mp4, make global or chunk option?
|
||||
# img = stringmime(MIME("video/$ext"), read(agif.filename))
|
||||
# res = "<video controls><source src=\"data:video/$(ext);base64,$img\" type=\"video/$ext\"></video>"
|
||||
res = "<video controls><source src=\"$(relpath(agif.filename))\" type=\"video/$ext\"></video>"
|
||||
else
|
||||
error("Cannot show animation with extension $ext: $agif")
|
||||
end
|
||||
|
||||
report.rich_output *= "\n" * res * "\n"
|
||||
report.rich_output *= "\n" * res * "\n"
|
||||
end
|
||||
|
||||
end
|
||||
|
|
424
src/readers.jl
424
src/readers.jl
|
@ -1,6 +1,7 @@
|
|||
import JSON, YAML
|
||||
|
||||
pushopt(options::Dict,expr::Expr) = Base.Meta.isexpr(expr,:(=)) && (options[expr.args[1]] = expr.args[2])
|
||||
pushopt(options::Dict, expr::Expr) =
|
||||
Base.Meta.isexpr(expr, :(=)) && (options[expr.args[1]] = expr.args[2])
|
||||
|
||||
mutable struct MarkupInput
|
||||
codestart::Regex
|
||||
|
@ -9,47 +10,46 @@ mutable struct MarkupInput
|
|||
end
|
||||
|
||||
mutable struct ScriptInput
|
||||
doc_line::Regex
|
||||
doc_start::Regex
|
||||
opt_line::Regex
|
||||
opt_start::Regex
|
||||
inline::Regex
|
||||
doc_line::Regex
|
||||
doc_start::Regex
|
||||
opt_line::Regex
|
||||
opt_start::Regex
|
||||
inline::Regex
|
||||
end
|
||||
|
||||
mutable struct NotebookInput
|
||||
inline
|
||||
inline::Any
|
||||
end
|
||||
|
||||
const input_formats = Dict{AbstractString, Any}(
|
||||
"noweb" => MarkupInput(r"^<<(.*?)>>=\s*$",
|
||||
r"^@\s*$",
|
||||
r"`j\s+(.*?)`|^!\s(.*)$"m
|
||||
),
|
||||
"markdown" => MarkupInput(
|
||||
r"^[`~]{3,}(?:\{|\{\.|)julia(?:;|)\s*(.*?)(\}|\s*)$",
|
||||
r"^[`~]{3,}\s*$",
|
||||
r"`j\s+(.*?)`|^!\s(.*)$"m),
|
||||
"script" => ScriptInput(
|
||||
r"(^#'.*)|(^#%%.*)|(^# %%.*)",
|
||||
r"(^#')|(^#%%)|(^# %%)",
|
||||
r"(^#\+.*$)|(^#%%\+.*$)|(^# %%\+.*$)",
|
||||
r"(^#\+)|(^#%%\+)|(^# %%\+)",
|
||||
r"`j\s+(.*?)`|^!\s(.*)$"m),
|
||||
"notebook" => NotebookInput(nothing) #Don't parse inline code from notebooks
|
||||
)
|
||||
const input_formats = Dict{AbstractString,Any}(
|
||||
"noweb" => MarkupInput(r"^<<(.*?)>>=\s*$", r"^@\s*$", r"`j\s+(.*?)`|^!\s(.*)$"m),
|
||||
"markdown" => MarkupInput(
|
||||
r"^[`~]{3,}(?:\{|\{\.|)julia(?:;|)\s*(.*?)(\}|\s*)$",
|
||||
r"^[`~]{3,}\s*$",
|
||||
r"`j\s+(.*?)`|^!\s(.*)$"m,
|
||||
),
|
||||
"script" => ScriptInput(
|
||||
r"(^#'.*)|(^#%%.*)|(^# %%.*)",
|
||||
r"(^#')|(^#%%)|(^# %%)",
|
||||
r"(^#\+.*$)|(^#%%\+.*$)|(^# %%\+.*$)",
|
||||
r"(^#\+)|(^#%%\+)|(^# %%\+)",
|
||||
r"`j\s+(.*?)`|^!\s(.*)$"m,
|
||||
),
|
||||
"notebook" => NotebookInput(nothing), # Don't parse inline code from notebooks
|
||||
)
|
||||
|
||||
"""Detect the input format based on file extension"""
|
||||
function detect_informat(source::AbstractString)
|
||||
ext = lowercase(splitext(source)[2])
|
||||
ext = lowercase(splitext(source)[2])
|
||||
|
||||
ext == ".jl" && return "script"
|
||||
ext == ".jmd" && return "markdown"
|
||||
ext == ".ipynb" && return "notebook"
|
||||
return "noweb"
|
||||
ext == ".jl" && return "script"
|
||||
ext == ".jmd" && return "markdown"
|
||||
ext == ".ipynb" && return "notebook"
|
||||
return "noweb"
|
||||
end
|
||||
|
||||
"""Read and parse input document"""
|
||||
function read_doc(source::AbstractString, format=:auto)
|
||||
function read_doc(source::AbstractString, format = :auto)
|
||||
format == :auto && (format = detect_informat(source))
|
||||
document = read(source, String)
|
||||
document = replace(document, "\r\n" => "\n")
|
||||
|
@ -61,230 +61,232 @@ function read_doc(source::AbstractString, format=:auto)
|
|||
end
|
||||
|
||||
function parse_header(chunk::CodeChunk)
|
||||
return Dict()
|
||||
return Dict()
|
||||
end
|
||||
|
||||
const HEADER_REGEX = r"^---$(?<header>((?!---).)+)^---$"ms
|
||||
|
||||
function parse_header(chunk::DocChunk)
|
||||
m = match(HEADER_REGEX, chunk.content[1].content)
|
||||
if m !== nothing
|
||||
header = YAML.load(string(m[:header]))
|
||||
else
|
||||
header = Dict()
|
||||
end
|
||||
return header
|
||||
m = match(HEADER_REGEX, chunk.content[1].content)
|
||||
if m !== nothing
|
||||
header = YAML.load(string(m[:header]))
|
||||
else
|
||||
header = Dict()
|
||||
end
|
||||
return header
|
||||
end
|
||||
|
||||
function parse_doc(document::AbstractString, format="noweb"::AbstractString)
|
||||
return parse_doc(document, input_formats[format])
|
||||
function parse_doc(document::AbstractString, format = "noweb"::AbstractString)
|
||||
return parse_doc(document, input_formats[format])
|
||||
end
|
||||
|
||||
"""Parse documents with Weave.jl markup"""
|
||||
function parse_doc(document::AbstractString, format::MarkupInput)
|
||||
document = replace(document, "\r\n" => "\n")
|
||||
lines = split(document, "\n")
|
||||
document = replace(document, "\r\n" => "\n")
|
||||
lines = split(document, "\n")
|
||||
|
||||
codestart = format.codestart
|
||||
codeend = format.codeend
|
||||
state = "doc"
|
||||
codestart = format.codestart
|
||||
codeend = format.codeend
|
||||
state = "doc"
|
||||
|
||||
docno = 1
|
||||
codeno = 1
|
||||
content = ""
|
||||
start_line = 0
|
||||
docno = 1
|
||||
codeno = 1
|
||||
content = ""
|
||||
start_line = 0
|
||||
|
||||
options = Dict()
|
||||
optionString = ""
|
||||
parsed = Any[]
|
||||
for lineno in 1:length(lines)
|
||||
line = lines[lineno]
|
||||
if (m = match(codestart, line)) != nothing && state=="doc"
|
||||
state = "code"
|
||||
if m.captures[1] == nothing
|
||||
optionString = ""
|
||||
else
|
||||
optionString=strip(m.captures[1])
|
||||
end
|
||||
options = Dict()
|
||||
optionString = ""
|
||||
parsed = Any[]
|
||||
for lineno = 1:length(lines)
|
||||
line = lines[lineno]
|
||||
if (m = match(codestart, line)) != nothing && state == "doc"
|
||||
state = "code"
|
||||
if m.captures[1] == nothing
|
||||
optionString = ""
|
||||
else
|
||||
optionString = strip(m.captures[1])
|
||||
end
|
||||
|
||||
options = Dict{Symbol,Any}()
|
||||
if length(optionString) > 0
|
||||
expr = Meta.parse(optionString)
|
||||
Base.Meta.isexpr(expr,:(=)) && (options[expr.args[1]] = expr.args[2])
|
||||
Base.Meta.isexpr(expr,:toplevel) && map(pushopt,fill(options,length(expr.args)),expr.args)
|
||||
end
|
||||
haskey(options, :label) && (options[:name] = options[:label])
|
||||
haskey(options, :name) || (options[:name] = nothing)
|
||||
options = Dict{Symbol,Any}()
|
||||
if length(optionString) > 0
|
||||
expr = Meta.parse(optionString)
|
||||
Base.Meta.isexpr(expr, :(=)) && (options[expr.args[1]] = expr.args[2])
|
||||
Base.Meta.isexpr(expr, :toplevel) &&
|
||||
map(pushopt, fill(options, length(expr.args)), expr.args)
|
||||
end
|
||||
haskey(options, :label) && (options[:name] = options[:label])
|
||||
haskey(options, :name) || (options[:name] = nothing)
|
||||
|
||||
if !isempty(strip(content))
|
||||
if !isempty(strip(content))
|
||||
chunk = DocChunk(content, docno, start_line, format.inline)
|
||||
docno += 1
|
||||
push!(parsed, chunk)
|
||||
end
|
||||
|
||||
content = ""
|
||||
start_line = lineno
|
||||
|
||||
continue
|
||||
|
||||
end
|
||||
if occursin(codeend, line) && state == "code"
|
||||
|
||||
chunk = CodeChunk(content, codeno, start_line, optionString, options)
|
||||
|
||||
codeno += 1
|
||||
start_line = lineno
|
||||
content = ""
|
||||
state = "doc"
|
||||
push!(parsed, chunk)
|
||||
continue
|
||||
end
|
||||
|
||||
if lineno == 1
|
||||
content *= line
|
||||
else
|
||||
content *= "\n" * line
|
||||
end
|
||||
end
|
||||
|
||||
# Remember the last chunk
|
||||
if strip(content) != ""
|
||||
chunk = DocChunk(content, docno, start_line, format.inline)
|
||||
docno += 1
|
||||
# chunk = Dict{Symbol,Any}(:type => "doc", :content => content,
|
||||
# :number => docno, :start_line => start_line)
|
||||
push!(parsed, chunk)
|
||||
end
|
||||
|
||||
content = ""
|
||||
start_line = lineno
|
||||
|
||||
continue
|
||||
|
||||
end
|
||||
if occursin(codeend, line) && state=="code"
|
||||
|
||||
chunk = CodeChunk(content, codeno, start_line, optionString, options)
|
||||
|
||||
codeno+=1
|
||||
start_line = lineno
|
||||
content = ""
|
||||
state = "doc"
|
||||
push!(parsed, chunk)
|
||||
continue
|
||||
end
|
||||
|
||||
if lineno == 1
|
||||
content *= line
|
||||
else
|
||||
content *= "\n" * line
|
||||
end
|
||||
end
|
||||
|
||||
#Remember the last chunk
|
||||
if strip(content) != ""
|
||||
chunk = DocChunk(content, docno, start_line, format.inline)
|
||||
#chunk = Dict{Symbol,Any}(:type => "doc", :content => content,
|
||||
# :number => docno, :start_line => start_line)
|
||||
push!(parsed, chunk)
|
||||
end
|
||||
return parsed
|
||||
return parsed
|
||||
end
|
||||
|
||||
"""Parse .jl scripts with Weave.jl markup"""
|
||||
function parse_doc(document::AbstractString, format::ScriptInput)
|
||||
document = replace(document, "\r\n" => "\n")
|
||||
lines = split(document, "\n")
|
||||
document = replace(document, "\r\n" => "\n")
|
||||
lines = split(document, "\n")
|
||||
|
||||
doc_line = format.doc_line
|
||||
doc_start = format.doc_start
|
||||
opt_line = format.opt_line
|
||||
opt_start = format.opt_start
|
||||
doc_line = format.doc_line
|
||||
doc_start = format.doc_start
|
||||
opt_line = format.opt_line
|
||||
opt_start = format.opt_start
|
||||
|
||||
read = ""
|
||||
chunks = []
|
||||
docno = 1
|
||||
codeno = 1
|
||||
content = ""
|
||||
start_line = 1
|
||||
options = Dict{Symbol,Any}()
|
||||
optionString = ""
|
||||
parsed = Any[]
|
||||
state = "code"
|
||||
lineno = 1
|
||||
n_emptylines = 0
|
||||
read = ""
|
||||
chunks = []
|
||||
docno = 1
|
||||
codeno = 1
|
||||
content = ""
|
||||
start_line = 1
|
||||
options = Dict{Symbol,Any}()
|
||||
optionString = ""
|
||||
parsed = Any[]
|
||||
state = "code"
|
||||
lineno = 1
|
||||
n_emptylines = 0
|
||||
|
||||
for lineno = 1:length(lines)
|
||||
line = lines[lineno]
|
||||
if (m = match(doc_line, line)) != nothing && (m = match(opt_line, line)) == nothing
|
||||
line = replace(line, doc_start => "", count = 1)
|
||||
if startswith(line, " ")
|
||||
line = replace(line, " " => "", count = 1)
|
||||
end
|
||||
if state == "code" && strip(read) != ""
|
||||
chunk =
|
||||
CodeChunk("\n" * strip(read), codeno, start_line, optionString, options)
|
||||
push!(parsed, chunk)
|
||||
codeno += 1
|
||||
read = ""
|
||||
start_line = lineno
|
||||
end
|
||||
state = "doc"
|
||||
elseif (m = match(opt_line, line)) != nothing
|
||||
start_line = lineno
|
||||
if state == "code" && strip(read) != ""
|
||||
chunk =
|
||||
CodeChunk("\n" * strip(read), codeno, start_line, optionString, options)
|
||||
push!(parsed, chunk)
|
||||
read = ""
|
||||
codeno += 1
|
||||
end
|
||||
if state == "doc" && strip(read) != ""
|
||||
(docno > 1) && (read = "\n" * read) # Add whitespace to doc chunk. Needed for markdown output
|
||||
chunk = DocChunk(read, docno, start_line)
|
||||
push!(parsed, chunk)
|
||||
read = ""
|
||||
docno += 1
|
||||
end
|
||||
|
||||
optionString = replace(line, opt_start => "", count = 1)
|
||||
# Get options
|
||||
options = Dict{Symbol,Any}()
|
||||
if length(optionString) > 0
|
||||
expr = Meta.parse(optionString)
|
||||
Base.Meta.isexpr(expr, :(=)) && (options[expr.args[1]] = expr.args[2])
|
||||
Base.Meta.isexpr(expr, :toplevel) &&
|
||||
map(pushopt, fill(options, length(expr.args)), expr.args)
|
||||
end
|
||||
haskey(options, :label) && (options[:name] = options[:label])
|
||||
haskey(options, :name) || (options[:name] = nothing)
|
||||
|
||||
for lineno in 1:length(lines)
|
||||
line = lines[lineno]
|
||||
if (m = match(doc_line, line)) != nothing && (m = match(opt_line, line)) == nothing
|
||||
line = replace(line, doc_start => "", count=1)
|
||||
if startswith(line, " ")
|
||||
line = replace(line, " " => "", count=1)
|
||||
end
|
||||
if state == "code" && strip(read) != ""
|
||||
chunk = CodeChunk("\n" * strip(read), codeno, start_line, optionString, options)
|
||||
push!(parsed, chunk)
|
||||
codeno +=1
|
||||
read = ""
|
||||
start_line = lineno
|
||||
end
|
||||
state = "doc"
|
||||
elseif (m = match(opt_line, line)) != nothing
|
||||
start_line = lineno
|
||||
if state == "code" && strip(read) !=""
|
||||
chunk = CodeChunk("\n" * strip(read), codeno, start_line, optionString, options)
|
||||
push!(parsed, chunk)
|
||||
read = ""
|
||||
codeno +=1
|
||||
end
|
||||
if state == "doc" && strip(read) != ""
|
||||
(docno > 1) && (read = "\n" * read) # Add whitespace to doc chunk. Needed for markdown output
|
||||
chunk = DocChunk(read, docno, start_line)
|
||||
push!(parsed, chunk)
|
||||
read = ""
|
||||
docno += 1
|
||||
end
|
||||
state = "code"
|
||||
continue
|
||||
elseif state == "doc" # && strip(line) != "" && strip(read) != ""
|
||||
state = "code"
|
||||
(docno > 1) && (read = "\n" * read) # Add whitespace to doc chunk. Needed for markdown output
|
||||
chunk = DocChunk(read, docno, start_line, format.inline)
|
||||
push!(parsed, chunk)
|
||||
options = Dict{Symbol,Any}()
|
||||
start_line = lineno
|
||||
read = ""
|
||||
docno += 1
|
||||
end
|
||||
read *= line * "\n"
|
||||
|
||||
optionString = replace(line, opt_start => "", count=1)
|
||||
#Get options
|
||||
options = Dict{Symbol,Any}()
|
||||
if length(optionString) > 0
|
||||
expr = Meta.parse(optionString)
|
||||
Base.Meta.isexpr(expr,:(=)) && (options[expr.args[1]] = expr.args[2])
|
||||
Base.Meta.isexpr(expr,:toplevel) && map(pushopt,fill(options,length(expr.args)),expr.args)
|
||||
end
|
||||
haskey(options, :label) && (options[:name] = options[:label])
|
||||
haskey(options, :name) || (options[:name] = nothing)
|
||||
|
||||
state = "code"
|
||||
continue
|
||||
elseif state == "doc" #&& strip(line) != "" && strip(read) != ""
|
||||
state = "code"
|
||||
(docno > 1) && (read = "\n" * read) # Add whitespace to doc chunk. Needed for markdown output
|
||||
chunk = DocChunk(read, docno, start_line, format.inline)
|
||||
push!(parsed, chunk)
|
||||
options = Dict{Symbol,Any}()
|
||||
start_line = lineno
|
||||
read = ""
|
||||
docno += 1
|
||||
if strip(line) == ""
|
||||
n_emptylines += 1
|
||||
else
|
||||
n_emptylines = 0
|
||||
end
|
||||
end
|
||||
read *= line * "\n"
|
||||
|
||||
if strip(line) == ""
|
||||
n_emptylines += 1
|
||||
# Handle the last chunk
|
||||
if state == "code"
|
||||
chunk = CodeChunk("\n" * strip(read), codeno, start_line, optionString, options)
|
||||
push!(parsed, chunk)
|
||||
else
|
||||
n_emptylines = 0
|
||||
chunk = DocChunk(read, docno, start_line, format.inline)
|
||||
push!(parsed, chunk)
|
||||
end
|
||||
end
|
||||
|
||||
# Handle the last chunk
|
||||
if state == "code"
|
||||
chunk = CodeChunk("\n" * strip(read), codeno, start_line, optionString, options)
|
||||
push!(parsed, chunk)
|
||||
else
|
||||
chunk = DocChunk(read, docno, start_line, format.inline)
|
||||
push!(parsed, chunk)
|
||||
end
|
||||
|
||||
return parsed
|
||||
return parsed
|
||||
end
|
||||
|
||||
"""Parse IJUlia notebook"""
|
||||
function parse_doc(document::String, format::NotebookInput)
|
||||
document = replace(document, "\r\n" => "\n")
|
||||
nb = JSON.parse(document)
|
||||
parsed = Any[]
|
||||
options = Dict{Symbol,Any}()
|
||||
opt_string = ""
|
||||
docno = 1
|
||||
codeno = 1
|
||||
document = replace(document, "\r\n" => "\n")
|
||||
nb = JSON.parse(document)
|
||||
parsed = Any[]
|
||||
options = Dict{Symbol,Any}()
|
||||
opt_string = ""
|
||||
docno = 1
|
||||
codeno = 1
|
||||
|
||||
for cell in nb["cells"]
|
||||
srctext = "\n" * join(cell["source"], "")
|
||||
for cell in nb["cells"]
|
||||
srctext = "\n" * join(cell["source"], "")
|
||||
|
||||
if cell["cell_type"] == "code"
|
||||
chunk = CodeChunk(rstrip(srctext), codeno, 0, opt_string, options)
|
||||
push!(parsed, chunk)
|
||||
codeno += 1
|
||||
else
|
||||
chunk = DocChunk(srctext * "\n", docno, 0)
|
||||
push!(parsed, chunk)
|
||||
docno +=1
|
||||
if cell["cell_type"] == "code"
|
||||
chunk = CodeChunk(rstrip(srctext), codeno, 0, opt_string, options)
|
||||
push!(parsed, chunk)
|
||||
codeno += 1
|
||||
else
|
||||
chunk = DocChunk(srctext * "\n", docno, 0)
|
||||
push!(parsed, chunk)
|
||||
docno += 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return parsed
|
||||
return parsed
|
||||
end
|
||||
|
||||
#Use this if regex is undefined
|
||||
# Use this if regex is undefined
|
||||
function parse_inline(text, noex)
|
||||
return Inline[InlineText(text, 1, length(text), 1)]
|
||||
end
|
||||
|
@ -301,7 +303,7 @@ function parse_inline(text::AbstractString, inline_ex::Regex)
|
|||
|
||||
for ic in inline_chunks
|
||||
s = ic.offset
|
||||
doc = InlineText(text[e:(s-1)], e, s-1, textno)
|
||||
doc = InlineText(text[e:(s-1)], e, s - 1, textno)
|
||||
textno += 1
|
||||
push!(res, doc)
|
||||
e = s + lastindex(ic.match)
|
||||
|
|
197
src/run.jl
197
src/run.jl
|
@ -39,9 +39,9 @@ function Base.run(
|
|||
cache_path::AbstractString = "cache",
|
||||
cache::Symbol = :off,
|
||||
throw_errors::Bool = false,
|
||||
latex_keep_unicode::Bool = false
|
||||
latex_keep_unicode::Bool = false,
|
||||
)
|
||||
#cache :all, :user, :off, :refresh
|
||||
# cache :all, :user, :off, :refresh
|
||||
|
||||
doc.cwd = get_cwd(doc, out_path)
|
||||
doctype == :auto && (doctype = detect_doctype(doc.source))
|
||||
|
@ -62,13 +62,13 @@ function Base.run(
|
|||
|
||||
cache == :off || @eval import Serialization
|
||||
|
||||
#This is needed for latex and should work on all output formats
|
||||
# This is needed for latex and should work on all output formats
|
||||
Sys.iswindows() && (fig_path = replace(fig_path, "\\" => "/"))
|
||||
|
||||
doc.fig_path = fig_path
|
||||
set_rc_params(doc, fig_path, fig_ext)
|
||||
|
||||
#New sandbox for each document with args exposed
|
||||
# New sandbox for each document with args exposed
|
||||
if mod == :sandbox
|
||||
sandbox = "WeaveSandBox$(rcParams[:doc_number])"
|
||||
mod = Core.eval(Main, Meta.parse("module $sandbox\nend"))
|
||||
|
@ -79,9 +79,9 @@ function Base.run(
|
|||
rcParams[:doc_number] += 1
|
||||
|
||||
if haskey(doc.format.formatdict, :mimetypes)
|
||||
mimetypes = doc.format.formatdict[:mimetypes]
|
||||
mimetypes = doc.format.formatdict[:mimetypes]
|
||||
else
|
||||
mimetypes = default_mime_types
|
||||
mimetypes = default_mime_types
|
||||
end
|
||||
|
||||
report = Report(doc.cwd, doc.basename, doc.format.formatdict, mimetypes, throw_errors)
|
||||
|
@ -105,9 +105,9 @@ function Base.run(
|
|||
merge!(chunk.options, options)
|
||||
end
|
||||
|
||||
restore = (cache ==:user && typeof(chunk) == CodeChunk && chunk.options[:cache])
|
||||
restore = (cache == :user && typeof(chunk) == CodeChunk && chunk.options[:cache])
|
||||
|
||||
if cached != nothing && (cache == :all || restore)
|
||||
if cached != nothing && (cache == :all || restore)
|
||||
result_chunks = restore_chunk(chunk, cached)
|
||||
else
|
||||
result_chunks = run_chunk(chunk, doc, report, mod)
|
||||
|
@ -120,7 +120,7 @@ function Base.run(
|
|||
|
||||
popdisplay(report)
|
||||
|
||||
#Clear variables from used sandbox
|
||||
# Clear variables from used sandbox
|
||||
mod == :sandbox && clear_sandbox(SandBox)
|
||||
doc.chunks = executed
|
||||
|
||||
|
@ -142,16 +142,16 @@ function detect_doctype(path::AbstractString)
|
|||
match(r"^\.(jl|.?md|ipynb)", ext) !== nothing && return "md2html"
|
||||
ext == ".rst" && return "rst"
|
||||
ext == ".tex" && return "texminted"
|
||||
ext == ".txt" && return "asciidoc"
|
||||
ext == ".txt" && return "asciidoc"
|
||||
|
||||
return "pandoc"
|
||||
end
|
||||
|
||||
|
||||
function run_chunk(chunk::CodeChunk, doc::WeaveDoc, report::Report, SandBox::Module)
|
||||
@info("Weaving chunk $(chunk.number) from line $(chunk.start_line)")
|
||||
result_chunks = eval_chunk(chunk, report, SandBox)
|
||||
occursin("2html", report.formatdict[:doctype]) && (result_chunks = embed_figures(result_chunks, report.cwd))
|
||||
occursin("2html", report.formatdict[:doctype]) &&
|
||||
(result_chunks = embed_figures(result_chunks, report.cwd))
|
||||
return result_chunks
|
||||
end
|
||||
|
||||
|
@ -161,7 +161,7 @@ function embed_figures(chunk::CodeChunk, cwd)
|
|||
end
|
||||
|
||||
function embed_figures(result_chunks, cwd)
|
||||
for i in 1:length(result_chunks)
|
||||
for i = 1:length(result_chunks)
|
||||
figs = result_chunks[i].figures
|
||||
if !isempty(figs)
|
||||
result_chunks[i].figures = [img2base64(fig, cwd) for fig in figs]
|
||||
|
@ -171,23 +171,23 @@ function embed_figures(result_chunks, cwd)
|
|||
end
|
||||
|
||||
function img2base64(fig, cwd)
|
||||
ext = splitext(fig)[2]
|
||||
f = open(joinpath(cwd, fig), "r")
|
||||
ext = splitext(fig)[2]
|
||||
f = open(joinpath(cwd, fig), "r")
|
||||
raw = read(f)
|
||||
close(f)
|
||||
if ext == ".png"
|
||||
return "data:image/png;base64," * stringmime(MIME("image/png"), raw)
|
||||
elseif ext == ".svg"
|
||||
return "data:image/svg+xml;base64," * stringmime(MIME("image/svg"), raw)
|
||||
elseif ext == ".gif"
|
||||
return "data:image/gif;base64," * stringmime(MIME("image/gif"), raw)
|
||||
else
|
||||
return(fig)
|
||||
end
|
||||
close(f)
|
||||
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
|
||||
end
|
||||
|
||||
function run_chunk(chunk::DocChunk, doc::WeaveDoc, report::Report, SandBox::Module)
|
||||
chunk.content = [run_inline(c, doc, report, SandBox) for c in chunk.content]
|
||||
chunk.content = [run_inline(c, doc, report, SandBox) for c in chunk.content]
|
||||
return chunk
|
||||
end
|
||||
|
||||
|
@ -196,13 +196,14 @@ function run_inline(inline::InlineText, doc::WeaveDoc, report::Report, SandBox::
|
|||
end
|
||||
|
||||
function run_inline(inline::InlineCode, doc::WeaveDoc, report::Report, SandBox::Module)
|
||||
#Make a temporary CodeChunk for running code. Collect results and don't wrap
|
||||
# Make a temporary CodeChunk for running code. Collect results and don't wrap
|
||||
chunk = CodeChunk(inline.content, 0, 0, "", Dict(:hold => true, :wrap => false))
|
||||
options = merge(doc.chunk_defaults, chunk.options)
|
||||
merge!(chunk.options, options)
|
||||
|
||||
chunks = eval_chunk(chunk, report, SandBox)
|
||||
occursin("2html", report.formatdict[:doctype]) && (chunks = embed_figures(chunks, report.cwd))
|
||||
occursin("2html", report.formatdict[:doctype]) &&
|
||||
(chunks = embed_figures(chunks, report.cwd))
|
||||
|
||||
output = chunks[1].output
|
||||
endswith(output, "\n") && (output = output[1:end-1])
|
||||
|
@ -221,16 +222,22 @@ end
|
|||
function run_code(chunk::CodeChunk, report::Report, SandBox::Module)
|
||||
expressions = parse_input(chunk.content)
|
||||
N = length(expressions)
|
||||
#@show expressions
|
||||
# @show expressions
|
||||
result_no = 1
|
||||
results = ChunkOutput[ ]
|
||||
results = ChunkOutput[]
|
||||
|
||||
for (str_expr, expr) = expressions
|
||||
for (str_expr, expr) in expressions
|
||||
reset_report(report)
|
||||
lastline = (result_no == N)
|
||||
(obj, out) = capture_output(expr, SandBox, chunk.options[:term],
|
||||
chunk.options[:display], lastline, report.throw_errors)
|
||||
figures = report.figures #Captured figures
|
||||
(obj, out) = capture_output(
|
||||
expr,
|
||||
SandBox,
|
||||
chunk.options[:term],
|
||||
chunk.options[:display],
|
||||
lastline,
|
||||
report.throw_errors,
|
||||
)
|
||||
figures = report.figures # Captured figures
|
||||
result = ChunkOutput(str_expr, out, report.cur_result, report.rich_output, figures)
|
||||
report.rich_output = ""
|
||||
push!(results, result)
|
||||
|
@ -241,9 +248,8 @@ end
|
|||
|
||||
getstdout() = stdout
|
||||
|
||||
function capture_output(expr, SandBox::Module, term, disp,
|
||||
lastline, throw_errors=false)
|
||||
#oldSTDOUT = STDOUT
|
||||
function capture_output(expr, SandBox::Module, term, disp, lastline, throw_errors = false)
|
||||
# oldSTDOUT = STDOUT
|
||||
oldSTDOUT = getstdout()
|
||||
out = nothing
|
||||
obj = nothing
|
||||
|
@ -253,8 +259,8 @@ function capture_output(expr, SandBox::Module, term, disp,
|
|||
obj = Core.eval(SandBox, expr)
|
||||
if (term || disp) && (typeof(expr) != Expr || expr.head != :toplevel)
|
||||
obj != nothing && display(obj)
|
||||
#This shows images and lone variables, result can
|
||||
#Handle last line sepately
|
||||
# This shows images and lone variables, result can
|
||||
# Handle last line sepately
|
||||
elseif lastline && obj != nothing
|
||||
(typeof(expr) != Expr || expr.head != :toplevel) && display(obj)
|
||||
end
|
||||
|
@ -268,26 +274,24 @@ function capture_output(expr, SandBox::Module, term, disp,
|
|||
out = fetch(reader)
|
||||
close(rw)
|
||||
end
|
||||
out = replace(out, r"\u001b\[.*?m" => "") #Remove ANSI color codes
|
||||
out = replace(out, r"\u001b\[.*?m" => "") # Remove ANSI color codes
|
||||
return (obj, out)
|
||||
end
|
||||
|
||||
|
||||
#Parse chunk input to array of expressions
|
||||
# Parse chunk input to array of expressions
|
||||
function parse_input(input::AbstractString)
|
||||
parsed = Tuple{AbstractString, Any}[]
|
||||
parsed = Tuple{AbstractString,Any}[]
|
||||
input = lstrip(input)
|
||||
n = sizeof(input)
|
||||
pos = 1 #The first character is extra line end
|
||||
pos = 1 # The first character is extra line end
|
||||
while pos ≤ n
|
||||
oldpos = pos
|
||||
code, pos = Meta.parse(input, pos)
|
||||
push!(parsed, (input[oldpos:pos-1] , code ))
|
||||
code, pos = Meta.parse(input, pos)
|
||||
push!(parsed, (input[oldpos:pos-1], code))
|
||||
end
|
||||
parsed
|
||||
end
|
||||
|
||||
|
||||
function eval_chunk(chunk::CodeChunk, report::Report, SandBox::Module)
|
||||
if !chunk.options[:eval]
|
||||
chunk.output = ""
|
||||
|
@ -295,9 +299,9 @@ function eval_chunk(chunk::CodeChunk, report::Report, SandBox::Module)
|
|||
return chunk
|
||||
end
|
||||
|
||||
#Run preexecute_hooks
|
||||
# Run preexecute_hooks
|
||||
for hook in preexecute_hooks
|
||||
chunk = Base.invokelatest(hook, chunk)
|
||||
chunk = Base.invokelatest(hook, chunk)
|
||||
end
|
||||
|
||||
report.fignum = 1
|
||||
|
@ -309,10 +313,9 @@ function eval_chunk(chunk::CodeChunk, report::Report, SandBox::Module)
|
|||
|
||||
chunk.result = run_code(chunk, report, SandBox)
|
||||
|
||||
|
||||
#Run post_execute chunks
|
||||
# Run post_execute chunks
|
||||
for hook in postexecute_hooks
|
||||
chunk = Base.invokelatest(hook, chunk)
|
||||
chunk = Base.invokelatest(hook, chunk)
|
||||
end
|
||||
|
||||
if chunk.options[:term]
|
||||
|
@ -323,28 +326,29 @@ function eval_chunk(chunk::CodeChunk, report::Report, SandBox::Module)
|
|||
chunks = collect_results(chunk, ScriptResult())
|
||||
end
|
||||
|
||||
#else
|
||||
# chunk.options[:fig] && (chunk.figures = copy(report.figures))
|
||||
#end
|
||||
# else
|
||||
# chunk.options[:fig] && (chunk.figures = copy(report.figures))
|
||||
# end
|
||||
|
||||
chunks
|
||||
end
|
||||
|
||||
|
||||
#function eval_chunk(chunk::DocChunk, report::Report, SandBox)
|
||||
# function eval_chunk(chunk::DocChunk, report::Report, SandBox)
|
||||
# chunk
|
||||
#end
|
||||
# end
|
||||
|
||||
#Set all variables to nothing
|
||||
# Set all variables to nothing
|
||||
function clear_sandbox(SandBox::Module)
|
||||
for name = names(SandBox, all=true)
|
||||
for name in names(SandBox, all = true)
|
||||
if name != :eval && name != names(SandBox)[1]
|
||||
try eval(SandBox, Meta.parse(AbstractString(AbstractString(name), "=nothing"))) catch; end
|
||||
try
|
||||
eval(SandBox, Meta.parse(AbstractString(AbstractString(name), "=nothing")))
|
||||
catch
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function get_figname(report::Report, chunk; fignum = nothing, ext = nothing)
|
||||
figpath = joinpath(report.cwd, chunk.options[:fig_path])
|
||||
isdir(figpath) || mkpath(figpath)
|
||||
|
@ -352,20 +356,23 @@ function get_figname(report::Report, chunk; fignum = nothing, ext = nothing)
|
|||
fignum == nothing && (fignum = report.fignum)
|
||||
|
||||
chunkid = (chunk.options[:label] == nothing) ? chunk.number : chunk.options[:label]
|
||||
full_name = joinpath(report.cwd, chunk.options[:fig_path],
|
||||
"$(report.basename)_$(chunkid)_$(fignum)$ext")
|
||||
rel_name = "$(chunk.options[:fig_path])/$(report.basename)_$(chunkid)_$(fignum)$ext" #Relative path is used in output
|
||||
full_name = joinpath(
|
||||
report.cwd,
|
||||
chunk.options[:fig_path],
|
||||
"$(report.basename)_$(chunkid)_$(fignum)$ext",
|
||||
)
|
||||
rel_name = "$(chunk.options[:fig_path])/$(report.basename)_$(chunkid)_$(fignum)$ext" # Relative path is used in output
|
||||
return full_name, rel_name
|
||||
end
|
||||
|
||||
function get_cwd(doc::WeaveDoc, out_path)
|
||||
#Set the output directory
|
||||
# Set the output directory
|
||||
if out_path == :doc
|
||||
cwd = doc.path
|
||||
elseif out_path == :pwd
|
||||
cwd = pwd()
|
||||
else
|
||||
#If there is no extension, use as path
|
||||
# If there is no extension, use as path
|
||||
splitted = splitext(out_path)
|
||||
if splitted[2] == ""
|
||||
cwd = expanduser(out_path)
|
||||
|
@ -376,14 +383,12 @@ function get_cwd(doc::WeaveDoc, out_path)
|
|||
return cwd
|
||||
end
|
||||
|
||||
|
||||
"""Get output file name based on out_path"""
|
||||
function get_outname(out_path::Symbol, doc::WeaveDoc; ext = nothing)
|
||||
ext == nothing && (ext = doc.format.formatdict[:extension])
|
||||
outname = "$(doc.cwd)/$(doc.basename).$ext"
|
||||
end
|
||||
|
||||
|
||||
"""Get output file name based on out_path"""
|
||||
function get_outname(out_path::AbstractString, doc::WeaveDoc; ext = nothing)
|
||||
ext == nothing && (ext = doc.format.formatdict[:extension])
|
||||
|
@ -402,24 +407,30 @@ function set_rc_params(doc::WeaveDoc, fig_path, fig_ext)
|
|||
else
|
||||
doc.chunk_defaults[:fig_ext] = fig_ext
|
||||
end
|
||||
doc.chunk_defaults[:fig_path] = fig_path
|
||||
doc.chunk_defaults[:fig_path] = fig_path
|
||||
return nothing
|
||||
end
|
||||
|
||||
function collect_results(chunk::CodeChunk, fmt::ScriptResult)
|
||||
content = ""
|
||||
result_no = 1
|
||||
result_chunks = CodeChunk[ ]
|
||||
for r = chunk.result
|
||||
#Check if there is any output from chunk
|
||||
if strip(r.stdout) == "" && isempty(r.figures) && strip(r.rich_output) == ""
|
||||
result_chunks = CodeChunk[]
|
||||
for r in chunk.result
|
||||
# Check if there is any output from chunk
|
||||
if strip(r.stdout) == "" && isempty(r.figures) && strip(r.rich_output) == ""
|
||||
content *= r.code
|
||||
else
|
||||
content = "\n" * content * r.code
|
||||
rchunk = CodeChunk(content, chunk.number, chunk.start_line, chunk.optionstring, copy(chunk.options))
|
||||
rchunk = CodeChunk(
|
||||
content,
|
||||
chunk.number,
|
||||
chunk.start_line,
|
||||
chunk.optionstring,
|
||||
copy(chunk.options),
|
||||
)
|
||||
content = ""
|
||||
rchunk.result_no = result_no
|
||||
result_no *=1
|
||||
result_no *= 1
|
||||
rchunk.figures = r.figures
|
||||
rchunk.output = r.stdout * r.displayed
|
||||
rchunk.rich_output = r.rich_output
|
||||
|
@ -428,7 +439,13 @@ function collect_results(chunk::CodeChunk, fmt::ScriptResult)
|
|||
end
|
||||
if content != ""
|
||||
startswith(content, "\n") || (content = "\n" * content)
|
||||
rchunk = CodeChunk(content, chunk.number, chunk.start_line, chunk.optionstring, copy(chunk.options))
|
||||
rchunk = CodeChunk(
|
||||
content,
|
||||
chunk.number,
|
||||
chunk.start_line,
|
||||
chunk.optionstring,
|
||||
copy(chunk.options),
|
||||
)
|
||||
push!(result_chunks, rchunk)
|
||||
end
|
||||
|
||||
|
@ -439,12 +456,18 @@ function collect_results(chunk::CodeChunk, fmt::TermResult)
|
|||
output = ""
|
||||
prompt = chunk.options[:prompt]
|
||||
result_no = 1
|
||||
result_chunks = CodeChunk[ ]
|
||||
for r = chunk.result
|
||||
result_chunks = CodeChunk[]
|
||||
for r in chunk.result
|
||||
output *= prompt * r.code
|
||||
output *= r.displayed * r.stdout
|
||||
if !isempty(r.figures)
|
||||
rchunk = CodeChunk("", chunk.number, chunk.start_line, chunk.optionstring, copy(chunk.options))
|
||||
rchunk = CodeChunk(
|
||||
"",
|
||||
chunk.number,
|
||||
chunk.start_line,
|
||||
chunk.optionstring,
|
||||
copy(chunk.options),
|
||||
)
|
||||
rchunk.output = output
|
||||
output = ""
|
||||
rchunk.figures = r.figures
|
||||
|
@ -452,8 +475,14 @@ function collect_results(chunk::CodeChunk, fmt::TermResult)
|
|||
end
|
||||
end
|
||||
if output != ""
|
||||
rchunk = CodeChunk("", chunk.number, chunk.start_line, chunk.optionstring, copy(chunk.options))
|
||||
rchunk.output = output
|
||||
rchunk = CodeChunk(
|
||||
"",
|
||||
chunk.number,
|
||||
chunk.start_line,
|
||||
chunk.optionstring,
|
||||
copy(chunk.options),
|
||||
)
|
||||
rchunk.output = output
|
||||
push!(result_chunks, rchunk)
|
||||
end
|
||||
|
||||
|
@ -462,8 +491,8 @@ end
|
|||
|
||||
function collect_results(chunk::CodeChunk, fmt::CollectResult)
|
||||
result_no = 1
|
||||
for r =chunk.result
|
||||
chunk.output *= r.stdout
|
||||
for r in chunk.result
|
||||
chunk.output *= r.stdout
|
||||
chunk.rich_output *= r.rich_output
|
||||
chunk.figures = [chunk.figures; r.figures]
|
||||
end
|
||||
|
|
177
src/writers.jl
177
src/writers.jl
|
@ -1,33 +1,29 @@
|
|||
import JSON
|
||||
import Mustache
|
||||
|
||||
mutable struct NotebookOutput
|
||||
end
|
||||
mutable struct NotebookOutput end
|
||||
|
||||
mutable struct MarkdownOutput
|
||||
end
|
||||
mutable struct MarkdownOutput end
|
||||
|
||||
mutable struct NowebOutput
|
||||
end
|
||||
mutable struct NowebOutput end
|
||||
|
||||
mutable struct ScriptOutput
|
||||
end
|
||||
mutable struct ScriptOutput end
|
||||
|
||||
const output_formats = Dict{String, Any}(
|
||||
"noweb" => NowebOutput(),
|
||||
"notebook" => NotebookOutput(),
|
||||
"markdown" => MarkdownOutput(),
|
||||
"script" => ScriptOutput()
|
||||
const output_formats = Dict{String,Any}(
|
||||
"noweb" => NowebOutput(),
|
||||
"notebook" => NotebookOutput(),
|
||||
"markdown" => MarkdownOutput(),
|
||||
"script" => ScriptOutput(),
|
||||
)
|
||||
|
||||
"""Autodetect format for converter"""
|
||||
function detect_outformat(outfile::String)
|
||||
ext = lowercase(splitext(outfile)[2])
|
||||
ext = lowercase(splitext(outfile)[2])
|
||||
|
||||
ext == ".jl" && return "script"
|
||||
ext == ".jmd" && return "markdown"
|
||||
ext == ".ipynb" && return "notebook"
|
||||
return "noweb"
|
||||
ext == ".jl" && return "script"
|
||||
ext == ".jmd" && return "markdown"
|
||||
ext == ".ipynb" && return "notebook"
|
||||
return "noweb"
|
||||
end
|
||||
|
||||
"""
|
||||
|
@ -39,37 +35,41 @@ Convert Weave documents between different formats
|
|||
- `outfile`: Path of the output document
|
||||
- `format = nothing`: Output document format (optional). It will be detected automatically from the `outfile` extension. You can also specify either of `"script"`, `"markdown"`, `"notebook"`, or `"noweb"`
|
||||
"""
|
||||
function convert_doc(infile::AbstractString, outfile::AbstractString; format::Union{Nothing,AbstractString} = nothing)
|
||||
doc = read_doc(infile)
|
||||
function convert_doc(
|
||||
infile::AbstractString,
|
||||
outfile::AbstractString;
|
||||
format::Union{Nothing,AbstractString} = nothing,
|
||||
)
|
||||
doc = read_doc(infile)
|
||||
|
||||
if format == nothing
|
||||
format = detect_outformat(outfile)
|
||||
end
|
||||
if format == nothing
|
||||
format = detect_outformat(outfile)
|
||||
end
|
||||
|
||||
converted = convert_doc(doc, output_formats[format])
|
||||
converted = convert_doc(doc, output_formats[format])
|
||||
|
||||
open(outfile, "w") do f
|
||||
write(f, converted)
|
||||
end
|
||||
open(outfile, "w") do f
|
||||
write(f, converted)
|
||||
end
|
||||
|
||||
return nothing
|
||||
return nothing
|
||||
end
|
||||
|
||||
"""Convert Weave document to Jupyter notebook format"""
|
||||
function convert_doc(doc::WeaveDoc, format::NotebookOutput)
|
||||
nb = Dict()
|
||||
nb["nbformat"] = 4
|
||||
nb["nbformat"] = 4
|
||||
nb["nbformat_minor"] = 2
|
||||
metadata = Dict()
|
||||
kernelspec = Dict()
|
||||
kernelspec["language"] = "julia"
|
||||
kernelspec["name"] = "julia-$(VERSION.major).$(VERSION.minor)"
|
||||
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["name"] = "julia"
|
||||
language_info["version"] = "$(VERSION.major).$(VERSION.minor).$(VERSION.patch)"
|
||||
metadata["language_info"] = language_info
|
||||
cells = []
|
||||
|
@ -84,30 +84,35 @@ function convert_doc(doc::WeaveDoc, format::NotebookOutput)
|
|||
|
||||
if isa(doc.chunks[1], DocChunk)
|
||||
strip_header!(doc)
|
||||
doc.chunks[1].content[1].content = Mustache.render(head_tpl;
|
||||
[Pair(Symbol(k), v) for (k,v) in doc.header]...) * doc.chunks[1].content[1].content
|
||||
doc.chunks[1].content[1].content =
|
||||
Mustache.render(head_tpl; [Pair(Symbol(k), v) for (k, v) in doc.header]...) * doc.chunks[1].content[1].content
|
||||
end
|
||||
|
||||
for chunk in doc.chunks
|
||||
|
||||
if isa(chunk, DocChunk)
|
||||
push!(cells,
|
||||
Dict("cell_type" => "markdown",
|
||||
"metadata" => Dict(),
|
||||
"source" => [strip(join([repr(c) for c in chunk.content], ""))])
|
||||
)
|
||||
push!(
|
||||
cells,
|
||||
Dict(
|
||||
"cell_type" => "markdown",
|
||||
"metadata" => Dict(),
|
||||
"source" => [strip(join([repr(c) for c in chunk.content], ""))],
|
||||
),
|
||||
)
|
||||
elseif haskey(chunk.options, :skip) && chunk.options[:skip] == "notebook"
|
||||
continue
|
||||
else
|
||||
push!(cells,
|
||||
Dict("cell_type" => "code",
|
||||
"metadata" => Dict(),
|
||||
"source" => [strip(chunk.content)],
|
||||
"execution_count" => nothing,
|
||||
"outputs" => []
|
||||
))
|
||||
end
|
||||
end
|
||||
push!(
|
||||
cells,
|
||||
Dict(
|
||||
"cell_type" => "code",
|
||||
"metadata" => Dict(),
|
||||
"source" => [strip(chunk.content)],
|
||||
"execution_count" => nothing,
|
||||
"outputs" => [],
|
||||
),
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
nb["cells"] = cells
|
||||
nb["metadata"] = metadata
|
||||
|
@ -118,61 +123,61 @@ end
|
|||
|
||||
"""Convert Weave document to Jupyter notebook format"""
|
||||
function convert_doc(doc::WeaveDoc, format::MarkdownOutput)
|
||||
output = ""
|
||||
for chunk in doc.chunks
|
||||
if isa(chunk, DocChunk)
|
||||
output *= join([repr(c) for c in chunk.content], "")
|
||||
else
|
||||
output *= "\n" * "```julia"
|
||||
isempty(chunk.optionstring) || (output *= ";" * chunk.optionstring)
|
||||
output *= "\n" * lstrip(chunk.content)
|
||||
output *= "```\n"
|
||||
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
|
||||
end
|
||||
|
||||
return output
|
||||
return output
|
||||
end
|
||||
|
||||
"""Convert Weave document to noweb format"""
|
||||
function convert_doc(doc::WeaveDoc, format::NowebOutput)
|
||||
output = ""
|
||||
for chunk in doc.chunks
|
||||
if isa(chunk, DocChunk)
|
||||
output *= join([repr(c) for c in chunk.content], "")
|
||||
else
|
||||
output *= "\n" * "<<"
|
||||
isempty(chunk.optionstring) || (output *= strip(chunk.optionstring))
|
||||
output *= ">>="
|
||||
output *= "\n" * lstrip(chunk.content)
|
||||
output *= "@\n"
|
||||
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
|
||||
end
|
||||
|
||||
return output
|
||||
return output
|
||||
end
|
||||
|
||||
"""Convert Weave document to script format"""
|
||||
function convert_doc(doc::WeaveDoc, format::ScriptOutput)
|
||||
output = ""
|
||||
for chunk in doc.chunks
|
||||
if typeof(chunk) == Weave.DocChunk
|
||||
content = join([repr(c) for c in chunk.content], "")
|
||||
output *= join(["#' " * s for s in split(content, "\n")], "\n")
|
||||
else
|
||||
output *= "\n#+ "
|
||||
isempty(chunk.optionstring) || (output *= strip(chunk.optionstring))
|
||||
output *= "\n\n" * lstrip(chunk.content)
|
||||
output *= "\n"
|
||||
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
|
||||
end
|
||||
|
||||
return output
|
||||
return output
|
||||
end
|
||||
|
||||
function Base.repr(c::InlineText)
|
||||
return c.content
|
||||
return c.content
|
||||
end
|
||||
|
||||
function Base.repr(c::InlineCode)
|
||||
return "`j $(c.content)`"
|
||||
return "`j $(c.content)`"
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue