Browse Source

fix stuff

pull/220/head
Simon Christ 2 years ago
parent
commit
8f0468303f
  1. 236
      src/Literate.jl

236
src/Literate.jl

@ -16,7 +16,7 @@ struct DefaultFlavor <: AbstractFlavor end @@ -16,7 +16,7 @@ struct DefaultFlavor <: AbstractFlavor end
struct DocumenterFlavor <: AbstractFlavor end
struct CommonMarkFlavor <: AbstractFlavor end
struct FranklinFlavor <: AbstractFlavor end
struct CarpentriesFlavor <: AbstractFlavor end
struct CarpentriesFlavor <: AbstractFlavor end
# # Some simple rules:
#
@ -46,7 +46,7 @@ CodeChunk() = CodeChunk(String[], false) @@ -46,7 +46,7 @@ CodeChunk() = CodeChunk(String[], false)
ismdline(line) = (occursin(r"^\h*#$", line) || occursin(r"^\h*# .*$", line)) && !occursin(r"^\h*##", line)
function parse(content; allow_continued = true)
function parse(content; allow_continued=true)
lines = collect(eachline(IOBuffer(content)))
chunks = Chunk[]
@ -124,10 +124,10 @@ function parse(content; allow_continued = true) @@ -124,10 +124,10 @@ function parse(content; allow_continued = true)
end
function replace_default(content, sym;
config::Dict,
branch = "gh-pages",
commit = "master"
)
config::Dict,
branch="gh-pages",
commit="master"
)
repls = Pair{Any,Any}[]
# add some shameless advertisement
@ -227,7 +227,7 @@ filename(str) = first(splitext(last(splitdir(str)))) @@ -227,7 +227,7 @@ filename(str) = first(splitext(last(splitdir(str))))
isdocumenter(cfg) = cfg["flavor"]::AbstractFlavor isa DocumenterFlavor
_DEFAULT_IMAGE_FORMATS = [(MIME("image/svg+xml"), ".svg"), (MIME("image/png"), ".png"),
(MIME("image/jpeg"), ".jpeg")]
(MIME("image/jpeg"), ".jpeg")]
# Cache of inputfile => head branch
const HEAD_BRANCH_CACHE = Dict{String,String}()
@ -245,7 +245,7 @@ function edit_commit(inputfile, user_config) @@ -245,7 +245,7 @@ function edit_commit(inputfile, user_config)
readchomp(
pipeline(
setenv(`$(git) rev-parse --show-toplevel`; dir=dirname(inputfile));
stderr=devnull,
stderr=devnull
)
)
catch
@ -291,15 +291,15 @@ function create_configuration(inputfile; user_config, user_kwargs, type=nothing) @@ -291,15 +291,15 @@ function create_configuration(inputfile; user_config, user_kwargs, type=nothing)
if (d = get(user_config, "documenter", nothing); d !== nothing)
if type === :md
Base.depwarn("The documenter=$(d) keyword to Literate.markdown is deprecated." *
" Pass `flavor = Literate.$(d ? "DocumenterFlavor" : "CommonMarkFlavor")()`" *
" instead.", Symbol("Literate.markdown"))
" Pass `flavor = Literate.$(d ? "DocumenterFlavor" : "CommonMarkFlavor")()`" *
" instead.", Symbol("Literate.markdown"))
user_config["flavor"] = d ? DocumenterFlavor() : CommonMarkFlavor()
elseif type === :nb
Base.depwarn("The documenter=$(d) keyword to Literate.notebook is deprecated." *
" It is not used anymore for notebook output.", Symbol("Literate.notebook"))
" It is not used anymore for notebook output.", Symbol("Literate.notebook"))
elseif type === :jl
Base.depwarn("The documenter=$(d) keyword to Literate.script is deprecated." *
" It is not used anymore for script output.", Symbol("Literate.script"))
" It is not used anymore for script output.", Symbol("Literate.script"))
end
end
@ -431,7 +431,7 @@ Available options: @@ -431,7 +431,7 @@ Available options:
`$(_DEFAULT_IMAGE_FORMATS)`. Results which are `showable` with a MIME type are saved with
the first match, with the corresponding extension.
"""
const DEFAULT_CONFIGURATION=nothing # Dummy const for documentation
const DEFAULT_CONFIGURATION = nothing # Dummy const for documentation
function preprocessor(inputfile, outputdir; user_config, user_kwargs, type)
# Create configuration by merging default and userdefined
@ -485,7 +485,7 @@ function preprocessor(inputfile, outputdir; user_config, user_kwargs, type) @@ -485,7 +485,7 @@ function preprocessor(inputfile, outputdir; user_config, user_kwargs, type)
content = replace_default(content, type; config=config)
# parse the content into chunks
chunks = parse(content; allow_continued = type !== :nb)
chunks = parse(content; allow_continued=type !== :nb)
return chunks, config
end
@ -572,7 +572,7 @@ function processNonAdmonitions(item, io) @@ -572,7 +572,7 @@ function processNonAdmonitions(item, io)
write(io, string(Markdown.MD(item)))
end
function writeContent(mdContent, io)
function writeContent(mdContent, io)
for item in mdContent
if isa(item, Markdown.Admonition)
CarpentriesAdmonition(item, io)
@ -592,7 +592,7 @@ function CarpentriesCallout(admonition, io) @@ -592,7 +592,7 @@ function CarpentriesCallout(admonition, io)
write(io, ":::::::: callout", '\n')
else
if line != ""
write(io, line, '\n')
write(io, line, '\n')
end
end
end
@ -648,13 +648,13 @@ function CarpentriesAdmonition(admonition, io) @@ -648,13 +648,13 @@ function CarpentriesAdmonition(admonition, io)
category = admonition.category
admonition = split(string(Markdown.MD(admonition)), '\n')
if category in ("sc", "mc", "freecode")
CarpentriesChallenge(admonition, io)
CarpentriesChallenge(admonition, io)
elseif category == "tip"
CarpentriesTestamonial(admonition, io)
CarpentriesTestamonial(admonition, io)
elseif category == "warning"
CarpentriesWarning(admonition, io)
CarpentriesWarning(admonition, io)
elseif category in ("info", "note")
CarpentriesCallout(admonition, io)
CarpentriesCallout(admonition, io)
elseif category == "carp"
CarpentriesYAML(admonition, io)
end
@ -676,135 +676,91 @@ function markdown(inputfile, outputdir=pwd(); config::AbstractDict=Dict(), kwarg @@ -676,135 +676,91 @@ function markdown(inputfile, outputdir=pwd(); config::AbstractDict=Dict(), kwarg
# preprocessing and parsing
chunks, config =
preprocessor(inputfile, outputdir; user_config=config, user_kwargs=kwargs, type=:md)
flavor=config["flavor"]
# create the markdown file
sb = sandbox()
iomd = IOBuffer()
if flavor isa CarpentriesFlavor
for chunk in chunks
if isa(chunk, MDChunk)
if containsAdmonition(chunk)
str = chunkToMD(chunk)
mdContent = str.content
writeContent(mdContent, iomd)
else
# Handle chunks without admonitions
for line in chunk.lines
write(iomd, line.second, '\n') # Skip indent
end
end
## `else` is copied from vanilla:
else # isa(chunk, CodeChunk)
iocode = IOBuffer()
codefence = config["codefence"]::Pair
write(iocode, codefence.first)
# make sure the code block is finalized if we are printing to ```@example
# (or ````@example, any number of backticks >= 3 works)
if chunk.continued && occursin(r"^`{3,}@example", codefence.first) && isdocumenter(config)
write(iocode, "; continued = true")
end
write(iocode, '\n')
# filter out trailing #hide unless code is executed by Documenter
execute = config["execute"]::Bool
write_hide = isdocumenter(config) && !execute
write_line(line) = write_hide || !endswith(line, "#hide")
for line in chunk.lines
write_line(line) && write(iocode, line, '\n')
end
if write_hide && REPL.ends_with_semicolon(chunk.lines[end])
write(iocode, "nothing #hide\n")
end
write(iocode, codefence.second, '\n')
any(write_line, chunk.lines) && write(iomd, seekstart(iocode))
if execute
cd(config["literate_outputdir"]) do
execute_markdown!(iomd, sb, join(chunk.lines, '\n'), outputdir;
inputfile=config["literate_inputfile"],
fake_source=config["literate_outputfile"],
flavor=config["flavor"],
image_formats=config["image_formats"],
file_prefix="$(config["name"])-$(chunknum)",
)
end
end
end
end
else
# kinda Vanilla Function
for (chunknum, chunk) in enumerate(chunks)
if isa(chunk, MDChunk)
write_md_chunks!(iomd, chunks, outputdir, config)
#______________________________________________________________________________________________________________
# custom post-processing from user
content = config["postprocess"](String(take!(iomd)))
# write to file
outputfile = write_result(content, config)
return outputfile
end
function write_md_chunks!(iomd, chunks, outputdir, config)
flavor = config["flavor"]
sb = sandbox()
for (chunknum, chunk) in enumerate(chunks)
if isa(chunk, MDChunk)
#______________________________________________________________________________________________________________
if flavor isa CarpentriesFlavor
if containsAdmonition(chunk)
writeContent(chunk.lines, iomd)
end
else
if containsYAML(chunk) # This part is the only change. It (should) delete the YAML Admo for non Carpentries MD.
continue
end
#______________________________________________________________________________________________________________
end
#______________________________________________________________________________________________________________
for line in chunk.lines
write(iomd, line.second, '\n') # skip indent here
end
else # isa(chunk, CodeChunk)
iocode = IOBuffer()
codefence = config["codefence"]::Pair
write(iocode, codefence.first)
# make sure the code block is finalized if we are printing to ```@example
# (or ````@example, any number of backticks >= 3 works)
if chunk.continued && occursin(r"^`{3,}@example", codefence.first) && isdocumenter(config)
write(iocode, "; continued = true")
end
write(iocode, '\n')
# filter out trailing #hide unless code is executed by Documenter
execute = config["execute"]::Bool
write_hide = isdocumenter(config) && !execute
write_line(line) = write_hide || !endswith(line, "#hide")
for line in chunk.lines
write_line(line) && write(iocode, line, '\n')
end
if write_hide && REPL.ends_with_semicolon(chunk.lines[end])
write(iocode, "nothing #hide\n")
end
write(iocode, codefence.second, '\n')
any(write_line, chunk.lines) && write(iomd, seekstart(iocode))
if execute
cd(config["literate_outputdir"]) do
for line in chunk.lines
write(iomd, line.second, '\n') # skip indent here
end
else # isa(chunk, CodeChunk)
iocode = IOBuffer()
codefence = config["codefence"]::Pair
write(iocode, codefence.first)
# make sure the code block is finalized if we are printing to ```@example
# (or ````@example, any number of backticks >= 3 works)
if chunk.continued && occursin(r"^`{3,}@example", codefence.first) && isdocumenter(config)
write(iocode, "; continued = true")
end
write(iocode, '\n')
# filter out trailing #hide unless code is executed by Documenter
execute = config["execute"]::Bool
write_hide = isdocumenter(config) && !execute
write_line(line) = write_hide || !endswith(line, "#hide")
for line in chunk.lines
write_line(line) && write(iocode, line, '\n')
end
if write_hide && REPL.ends_with_semicolon(chunk.lines[end])
write(iocode, "nothing #hide\n")
end
write(iocode, codefence.second, '\n')
any(write_line, chunk.lines) && write(iomd, seekstart(iocode))
if execute
cd(config["literate_outputdir"]) do
execute_markdown!(iomd, sb, join(chunk.lines, '\n'), outputdir;
inputfile=config["literate_inputfile"],
fake_source=config["literate_outputfile"],
flavor=config["flavor"],
image_formats=config["image_formats"],
file_prefix="$(config["name"])-$(chunknum)",
inputfile=config["literate_inputfile"],
fake_source=config["literate_outputfile"],
flavor=config["flavor"],
image_formats=config["image_formats"],
file_prefix="$(config["name"])-$(chunknum)"
)
end
end
end
end
write(iomd, '\n') # add a newline between each chunk
end
write(iomd, '\n') # add a newline between each chunk
# custom post-processing from user
content = config["postprocess"](String(take!(iomd)))
# write to file
outputfile = write_result(content, config)
return outputfile
end
end
function execute_markdown!(io::IO, sb::Module, block::String, outputdir;
inputfile::String, fake_source::String,
flavor::AbstractFlavor, image_formats::Vector, file_prefix::String)
inputfile::String, fake_source::String,
flavor::AbstractFlavor, image_formats::Vector, file_prefix::String)
# TODO: Deal with explicit display(...) calls
r, str, _ = execute_block(sb, block; inputfile=inputfile, fake_source=fake_source)
# issue #101: consecutive codefenced blocks need newline
# issue #144: quadruple backticks allow for triple backticks in the output
plain_fence = "\n````\n" => "\n````"
plain_fence = "\n````\n" => "\n````"
# Here CarpentiresFlavor fork...
if r !== nothing && !REPL.ends_with_semicolon(block)
if (flavor isa FranklinFlavor || flavor isa DocumenterFlavor) &&
@ -851,8 +807,8 @@ function parse_nbmeta(line) @@ -851,8 +807,8 @@ function parse_nbmeta(line)
# Cf. https://jupytext.readthedocs.io/en/latest/formats.html#the-percent-format
m = match(r"^%% ([^[{]+)?\s*(?:\[(\w+)\])?\s*(\{.*)?$", line)
typ = m.captures[2]
name = m.captures[1] === nothing ? Dict{String, String}() : Dict("name" => m.captures[1])
meta = m.captures[3] === nothing ? Dict{String, Any}() : JSON.parse(m.captures[3])
name = m.captures[1] === nothing ? Dict{String,String}() : Dict("name" => m.captures[1])
meta = m.captures[3] === nothing ? Dict{String,Any}() : JSON.parse(m.captures[3])
return typ, merge(name, meta)
end
line_is_nbmeta(line::Pair) = line_is_nbmeta(line.second)
@ -875,7 +831,7 @@ function notebook(inputfile, outputdir=pwd(); config::AbstractDict=Dict(), kwarg @@ -875,7 +831,7 @@ function notebook(inputfile, outputdir=pwd(); config::AbstractDict=Dict(), kwarg
nb = jupyter_notebook(chunks, config)
# write to file
outputfile = write_result(nb, config; print = (io, c)->JSON.print(io, c, 1))
outputfile = write_result(nb, config; print=(io, c) -> JSON.print(io, c, 1))
return outputfile
end
@ -894,11 +850,11 @@ function jupyter_notebook(chunks, config) @@ -894,11 +850,11 @@ function jupyter_notebook(chunks, config)
metatype !== nothing && metatype != chunktype && error("specifying a different cell type is not supported")
popfirst!(chunk.lines)
else
metadata = Dict{String, Any}()
metadata = Dict{String,Any}()
end
lines = isa(chunk, MDChunk) ?
String[x.second for x in chunk.lines] : # skip indent
chunk.lines
String[x.second for x in chunk.lines] : # skip indent
chunk.lines
@views map!(x -> x * '\n', lines[1:end-1], lines[1:end-1])
cell["cell_type"] = chunktype
cell["metadata"] = metadata
@ -915,15 +871,15 @@ function jupyter_notebook(chunks, config) @@ -915,15 +871,15 @@ function jupyter_notebook(chunks, config)
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 $(string(VERSION))"
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"] = string(VERSION)
metadata["language_info"] = language_info
@ -937,7 +893,7 @@ function jupyter_notebook(chunks, config) @@ -937,7 +893,7 @@ function jupyter_notebook(chunks, config)
try
cd(config["literate_outputdir"]) do
nb = execute_notebook(nb; inputfile=config["literate_inputfile"],
fake_source=config["literate_outputfile"])
fake_source=config["literate_outputfile"])
end
catch err
@error "error when executing notebook based on input file: " *
@ -963,7 +919,7 @@ function execute_notebook(nb; inputfile::String, fake_source::String) @@ -963,7 +919,7 @@ function execute_notebook(nb; inputfile::String, fake_source::String)
stream = Dict{String,Any}()
stream["output_type"] = "stream"
stream["name"] = "stdout"
stream["text"] = collect(Any, eachline(IOBuffer(String(str)), keep = true))
stream["text"] = collect(Any, eachline(IOBuffer(String(str)), keep=true))
push!(cell["outputs"], stream)
end
@ -973,7 +929,7 @@ function execute_notebook(nb; inputfile::String, fake_source::String) @@ -973,7 +929,7 @@ function execute_notebook(nb; inputfile::String, fake_source::String)
function split_mime(dict)
for mime in ("image/svg+xml", "text/html")
if haskey(dict, mime)
dict[mime] = collect(Any, eachline(IOBuffer(dict[mime]), keep = true))
dict[mime] = collect(Any, eachline(IOBuffer(dict[mime]), keep=true))
end
end
return dict
@ -1053,7 +1009,7 @@ function execute_block(sb::Module, block::String; inputfile::String, fake_source @@ -1053,7 +1009,7 @@ function execute_block(sb::Module, block::String; inputfile::String, fake_source
# - c.output: combined stdout and stderr
# `rethrow = Union{}` means that we try-catch all the exceptions thrown in the do-block
# and return them via the return value (they get handled below).
c = IOCapture.capture(rethrow = Union{}) do
c = IOCapture.capture(rethrow=Union{}) do
include_string(sb, block, fake_source)
end
popdisplay(disp) # IOCapture.capture has a try-catch so should always end up here
@ -1070,4 +1026,4 @@ function execute_block(sb::Module, block::String; inputfile::String, fake_source @@ -1070,4 +1026,4 @@ function execute_block(sb::Module, block::String; inputfile::String, fake_source
return c.value, c.output, disp.data
end
end # module
end # module

Loading…
Cancel
Save