diff --git a/docs/make.jl b/docs/make.jl index 64c1363..f4b0691 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -5,7 +5,11 @@ if haskey(ENV, "GITHUB_ACTIONS") end deployconfig = Documenter.auto_detect_deploy_system() -Documenter.post_status(deployconfig; type="pending", repo="github.com/fredrikekre/Literate.jl.git") +Documenter.post_status( + deployconfig; + type = "pending", + repo = "github.com/fredrikekre/Literate.jl.git", +) using Literate using Plots # to not capture precompilation output @@ -14,7 +18,7 @@ EXAMPLE = joinpath(@__DIR__, "..", "examples", "example.jl") OUTPUT = joinpath(@__DIR__, "src/generated") function preprocess(str) - str = replace(str, "x = 123" => "y = 321"; count=1) + str = replace(str, "x = 123" => "y = 321"; count = 1) return str end @@ -23,7 +27,12 @@ Literate.notebook(EXAMPLE, OUTPUT, preprocess = preprocess) Literate.script(EXAMPLE, OUTPUT, preprocess = preprocess) # generate the example notebook for the documentation, keep in sync with outputformats.md -Literate.markdown(joinpath(@__DIR__, "src/outputformats.jl"), OUTPUT; credit = false, name = "name") +Literate.markdown( + joinpath(@__DIR__, "src/outputformats.jl"), + OUTPUT; + credit = false, + name = "name", +) Literate.notebook(joinpath(@__DIR__, "src/outputformats.jl"), OUTPUT; name = "notebook") Literate.script(joinpath(@__DIR__, "src/outputformats.jl"), OUTPUT; credit = false) @@ -41,7 +50,10 @@ if haskey(ENV, "GITHUB_ACTIONS") end url = "https://nbviewer.jupyter.org/github/fredrikekre/Literate.jl/blob/gh-pages/$(folder)/" str = read(joinpath(@__DIR__, "src/outputformats.md"), String) - str = replace(str, "[notebook.ipynb](generated/notebook.ipynb)." => "[notebook.ipynb]($(url)generated/notebook.ipynb).") + str = replace( + str, + "[notebook.ipynb](generated/notebook.ipynb)." => "[notebook.ipynb]($(url)generated/notebook.ipynb).", + ) write(joinpath(@__DIR__, "src/outputformats.md"), str) end @@ -61,7 +73,8 @@ makedocs( "customprocessing.md", "documenter.md", "tips.md", - "generated/example.md"] + "generated/example.md", + ], ) deploydocs( diff --git a/docs/src/outputformats.jl b/docs/src/outputformats.jl index 9dbdad1..91fb42c 100644 --- a/docs/src/outputformats.jl +++ b/docs/src/outputformats.jl @@ -3,9 +3,9 @@ # In julia rational numbers can be constructed with the `//` operator. # Lets define two rational numbers, `x` and `y`: -x = 1//3 +x = 1 // 3 #- -y = 2//5 +y = 2 // 5 # When adding `x` and `y` together we obtain a new rational number: diff --git a/examples/README.jl b/examples/README.jl index d0966c8..1e8af36 100644 --- a/examples/README.jl +++ b/examples/README.jl @@ -20,7 +20,7 @@ # running these commands from the package root of Literate.jl: using Literate -Literate.markdown("examples/README.jl", "."; flavor=Literate.CommonMarkFlavor()) +Literate.markdown("examples/README.jl", "."; flavor = Literate.CommonMarkFlavor()) # [docs-img]: https://img.shields.io/badge/docs-latest%20release-blue.svg # [docs-url]: https://fredrikekre.github.io/Literate.jl/ diff --git a/examples/example.jl b/examples/example.jl index 6423481..6b61d8b 100644 --- a/examples/example.jl +++ b/examples/example.jl @@ -33,8 +33,8 @@ # as markdown, and all the other lines are interpreted as code. Here is some code: #nb %% A slide [code] {"slideshow": {"slide_type": "fragment"}} -x = 1//3 -y = 2//5 +x = 1 // 3 +y = 2 // 5 #nb # %% A slide [markdown] {"slideshow": {"slide_type": "subslide"}} # In markdown sections we can use markdown syntax. For example, we can @@ -96,7 +96,7 @@ foo() #nb %% A slide [code] {"slideshow": {"slide_type": "subslide"}} using Plots -x = range(0, stop=6π, length=1000) +x = range(0, stop = 6π, length = 1000) y1 = sin.(x) y2 = cos.(x) plot(x, [y1, y2]) diff --git a/src/IJulia.jl b/src/IJulia.jl index f1fb302..e5f5ad5 100644 --- a/src/IJulia.jl +++ b/src/IJulia.jl @@ -19,7 +19,8 @@ const application_vnd_vegalite_v2 = MIME("application/vnd.vegalite.v2+json") function display_dict(x) data = Dict{String,Any}("text/plain" => limitstringmime(text_plain, x)) if showable(application_vnd_vegalite_v2, x) - data[string(application_vnd_vegalite_v2)] = JSON.parse(limitstringmime(application_vnd_vegalite_v2, x)) + data[string(application_vnd_vegalite_v2)] = + JSON.parse(limitstringmime(application_vnd_vegalite_v2, x)) end if showable(image_svg, x) data[string(image_svg)] = limitstringmime(image_svg, x) @@ -57,14 +58,14 @@ function limitstringmime(mime::MIME, x) if israwtext(mime, x) return String(x) else - show(IOContext(buf, :limit=>true, :color=>true), mime, x) + show(IOContext(buf, :limit => true, :color => true), mime, x) end else b64 = Base64EncodePipe(buf) if isa(x, Vector{UInt8}) write(b64, x) # x assumed to be raw binary data else - show(IOContext(b64, :limit=>true, :color=>true), mime, x) + show(IOContext(b64, :limit => true, :color => true), mime, x) end close(b64) end diff --git a/src/Literate.jl b/src/Literate.jl index 440b748..bb41ea3 100644 --- a/src/Literate.jl +++ b/src/Literate.jl @@ -44,7 +44,9 @@ mutable struct CodeChunk <: Chunk end CodeChunk() = CodeChunk(String[], false) -ismdline(line) = (occursin(r"^\h*#$", line) || occursin(r"^\h*# .*$", line)) && !occursin(r"^\h*##", line) +ismdline(line) = + (occursin(r"^\h*#$", line) || occursin(r"^\h*# .*$", line)) && + !occursin(r"^\h*##", line) function parse(content; allow_continued = true) lines = collect(eachline(IOBuffer(content))) @@ -78,7 +80,10 @@ function parse(content; allow_continued = true) end # remove "## " and "##\n", strip the leading "#" from "## xyz" and "##| xyz" # Note: accepts only standard space character (not no-break space U+00A0) - line = replace(replace(line, r"^(\h*)#(#(:? |\|).*)$" => s"\1\2"), r"^(\h*#)#$" => s"\1") + line = replace( + replace(line, r"^(\h*)#(#(:? |\|).*)$" => s"\1\2"), + r"^(\h*#)#$" => s"\1", + ) push!(chunks[end].lines, line) end end @@ -108,7 +113,10 @@ function parse(content; allow_continued = true) append!(merged_chunks[end].lines, chunk.lines) else # need to put back "#" for line in chunk.lines - push!(merged_chunks[end].lines, rstrip(line.first * "# " * line.second)) + push!( + merged_chunks[end].lines, + rstrip(line.first * "# " * line.second), + ) end end else @@ -124,11 +132,7 @@ function parse(content; allow_continued = true) return chunks end -function replace_default(content, sym; - config::Dict, - branch = "gh-pages", - commit = "master" - ) +function replace_default(content, sym; config::Dict, branch = "gh-pages", commit = "master") repls = Pair{Any,Any}[] # add some shameless advertisement @@ -159,7 +163,7 @@ function replace_default(content, sym; newlines = sprint() do io foreach(l -> println(io, "# ", l), eachline(IOBuffer(m[1]))) end - str = replace(str, multiline_r => chop(newlines); count=1) + str = replace(str, multiline_r => chop(newlines); count = 1) end return str end @@ -199,12 +203,16 @@ function replace_default(content, sym; # fix links if get(ENV, "DOCUMENTATIONGENERATOR", "") == "true" ## DocumentationGenerator.jl - base_url = get(ENV, "DOCUMENTATIONGENERATOR_BASE_URL", "DOCUMENTATIONGENERATOR_BASE_URL") + base_url = + get(ENV, "DOCUMENTATIONGENERATOR_BASE_URL", "DOCUMENTATIONGENERATOR_BASE_URL") nbviewer_root_url = "https://nbviewer.jupyter.org/urls/$(base_url)" push!(repls, "@__NBVIEWER_ROOT_URL__" => nbviewer_root_url) else push!(repls, "@__REPO_ROOT_URL__" => get(config, "repo_root_url", "")) - push!(repls, "@__NBVIEWER_ROOT_URL__" => get(config, "nbviewer_root_url", "")) + push!( + repls, + "@__NBVIEWER_ROOT_URL__" => get(config, "nbviewer_root_url", ""), + ) push!(repls, "@__BINDER_ROOT_URL__" => get(config, "binder_root_url", "")) end @@ -227,8 +235,11 @@ end 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")] +_DEFAULT_IMAGE_FORMATS = [ + (MIME("image/svg+xml"), ".svg"), + (MIME("image/png"), ".png"), + (MIME("image/jpeg"), ".jpeg"), +] # Cache of inputfile => head branch const HEAD_BRANCH_CACHE = Dict{String,String}() @@ -245,9 +256,9 @@ function edit_commit(inputfile, user_config) git_root = try readchomp( pipeline( - setenv(`$(git) rev-parse --show-toplevel`; dir=dirname(inputfile)); - stderr=devnull, - ) + setenv(`$(git) rev-parse --show-toplevel`; dir = dirname(inputfile)); + stderr = devnull, + ), ) catch end @@ -266,8 +277,8 @@ function edit_commit(inputfile, user_config) str = try read( pipeline( - setenv(`$(git) remote show origin`, env; dir=dirname(inputfile)), - stderr=devnull, + setenv(`$(git) remote show origin`, env; dir = dirname(inputfile)), + stderr = devnull, ), String, ) @@ -283,16 +294,20 @@ function edit_commit(inputfile, user_config) end # Default to DefaultFlavor() setting -pick_codefence(flavor::AbstractFlavor,execute::Bool,name::AbstractString)=pick_codefence(DefaultFlavor(),execute,name) -pick_codefence(flavor::DefaultFlavor,execute::Bool,name::AbstractString)=("````julia" => "````") -pick_codefence(flavor::DocumenterFlavor,execute::Bool,name::AbstractString)=(execute ? - pick_codefence(DefaultFlavor(),execute,name) : ("````@example $(name)" => "````") +pick_codefence(flavor::AbstractFlavor, execute::Bool, name::AbstractString) = + pick_codefence(DefaultFlavor(), execute, name) +pick_codefence(flavor::DefaultFlavor, execute::Bool, name::AbstractString) = + ("````julia" => "````") +pick_codefence(flavor::DocumenterFlavor, execute::Bool, name::AbstractString) = ( + execute ? pick_codefence(DefaultFlavor(), execute, name) : + ("````@example $(name)" => "````") ) -pick_codefence(flavor::QuartoFlavor,execute::Bool,name::AbstractString)=(execute ? - error("QuartoFlavor does not support argument execute=true!") : ("```{julia}" => "```") +pick_codefence(flavor::QuartoFlavor, execute::Bool, name::AbstractString) = ( + execute ? error("QuartoFlavor does not support argument execute=true!") : + ("```{julia}" => "```") ) -function create_configuration(inputfile; user_config, user_kwargs, type=nothing) +function create_configuration(inputfile; user_config, user_kwargs, type = nothing) # Combine user config with user kwargs user_config = Dict{String,Any}(string(k) => v for (k, v) in user_config) user_kwargs = Dict{String,Any}(string(k) => v for (k, v) in user_kwargs) @@ -301,16 +316,25 @@ function create_configuration(inputfile; user_config, user_kwargs, type=nothing) # deprecation of documenter kwarg if (d = get(user_config, "documenter", nothing); d !== nothing) if type === :md - Base.depwarn("The documenter=$(d) keyword to Literate.markdown is deprecated." * + Base.depwarn( + "The documenter=$(d) keyword to Literate.markdown is deprecated." * " Pass `flavor = Literate.$(d ? "DocumenterFlavor" : "CommonMarkFlavor")()`" * - " instead.", Symbol("Literate.markdown")) + " 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")) + Base.depwarn( + "The documenter=$(d) keyword to Literate.notebook is deprecated." * + " 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")) + Base.depwarn( + "The documenter=$(d) keyword to Literate.script is deprecated." * + " It is not used anymore for script output.", + Symbol("Literate.script"), + ) end end @@ -327,7 +351,7 @@ function create_configuration(inputfile; user_config, user_kwargs, type=nothing) cfg["codefence"] = pick_codefence( get(user_config, "flavor", cfg["flavor"]), get(user_config, "execute", cfg["execute"]), - get(user_config, "name", replace(cfg["name"], r"\s" => "_")) + get(user_config, "name", replace(cfg["name"], r"\s" => "_")), ) cfg["image_formats"] = _DEFAULT_IMAGE_FORMATS cfg["edit_commit"] = edit_commit(inputfile, user_config) @@ -367,7 +391,8 @@ function create_configuration(inputfile; user_config, user_kwargs, type=nothing) else get(user_config, "devurl", "dev") end - elseif (m = match(r"refs\/pull\/(\d+)\/merge", get(ENV, "GITHUB_REF", ""))) !== nothing + elseif (m = match(r"refs\/pull\/(\d+)\/merge", get(ENV, "GITHUB_REF", ""))) !== + nothing "previews/PR$(m.captures[1])" else "dev" @@ -443,12 +468,16 @@ 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 - config = create_configuration(inputfile; user_config=user_config, - user_kwargs=user_kwargs, type=type) + config = create_configuration( + inputfile; + user_config = user_config, + user_kwargs = user_kwargs, + type = type, + ) # normalize paths inputfile = normpath(inputfile) @@ -457,15 +486,21 @@ function preprocessor(inputfile, outputdir; user_config, user_kwargs, type) mkpath(outputdir) outputdir = realpath(abspath(outputdir)) isdir(outputdir) || error("not a directory: $(outputdir)") - ext = type === (:nb) ? ".ipynb" : (type === (:md) && config["flavor"] isa QuartoFlavor) ? ".qmd" : ".$(type)" + ext = + type === (:nb) ? ".ipynb" : + (type === (:md) && config["flavor"] isa QuartoFlavor) ? ".qmd" : ".$(type)" outputfile = joinpath(outputdir, config["name"]::String * ext) if inputfile == outputfile - throw(ArgumentError("outputfile (`$outputfile`) is identical to inputfile (`$inputfile`)")) + throw( + ArgumentError( + "outputfile (`$outputfile`) is identical to inputfile (`$inputfile`)", + ), + ) end - output_thing = type === (:md) ? "markdown page" : - type === (:nb) ? "notebook" : - type === (:jl) ? "plain script file" : error("nope") + output_thing = + type === (:md) ? "markdown page" : + type === (:nb) ? "notebook" : type === (:jl) ? "plain script file" : error("nope") @info "generating $(output_thing) from `$(Base.contractuser(inputfile))`" # Add some information for passing around Literate methods @@ -494,7 +529,7 @@ function preprocessor(inputfile, outputdir; user_config, user_kwargs, type) end # default replacements - content = replace_default(content, type; config=config) + content = replace_default(content, type; config = config) # parse the content into chunks chunks = parse(content; allow_continued = type !== :nb) @@ -502,7 +537,7 @@ function preprocessor(inputfile, outputdir; user_config, user_kwargs, type) return chunks, config end -function write_result(content, config; print=print) +function write_result(content, config; print = print) outputfile = config["literate_outputfile"] @info "writing result to `$(Base.contractuser(outputfile))`" open(outputfile, "w") do io @@ -519,10 +554,15 @@ Generate a plain script file from `inputfile` and write the result to `outputdir See the manual section on [Configuration](@ref) for documentation of possible configuration with `config` and other keyword arguments. """ -function script(inputfile, outputdir=pwd(); config::AbstractDict=Dict(), kwargs...) +function script(inputfile, outputdir = pwd(); config::AbstractDict = Dict(), kwargs...) # preprocessing and parsing - chunks, config = - preprocessor(inputfile, outputdir; user_config=config, user_kwargs=kwargs, type=:jl) + chunks, config = preprocessor( + inputfile, + outputdir; + user_config = config, + user_kwargs = kwargs, + type = :jl, + ) # create the script file ioscript = IOBuffer() @@ -558,10 +598,15 @@ to the directory `outputdir`. See the manual section on [Configuration](@ref) for documentation of possible configuration with `config` and other keyword arguments. """ -function markdown(inputfile, outputdir=pwd(); config::AbstractDict=Dict(), kwargs...) +function markdown(inputfile, outputdir = pwd(); config::AbstractDict = Dict(), kwargs...) # preprocessing and parsing - chunks, config = - preprocessor(inputfile, outputdir; user_config=config, user_kwargs=kwargs, type=:md) + chunks, config = preprocessor( + inputfile, + outputdir; + user_config = config, + user_kwargs = kwargs, + type = :md, + ) # create the markdown file sb = sandbox() @@ -578,7 +623,9 @@ function markdown(inputfile, outputdir=pwd(); config::AbstractDict=Dict(), kwarg 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) + if chunk.continued && + occursin(r"^`{3,}@example", codefence.first) && + isdocumenter(config) write(iocode, "; continued = true") end write(iocode, '\n') @@ -596,11 +643,16 @@ function markdown(inputfile, outputdir=pwd(); config::AbstractDict=Dict(), kwarg 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"]) + 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"], + ) end end end @@ -615,18 +667,26 @@ function markdown(inputfile, outputdir=pwd(); config::AbstractDict=Dict(), kwarg return outputfile end -function execute_markdown!(io::IO, sb::Module, block::String, outputdir; - inputfile::String, fake_source::String, - flavor::AbstractFlavor, image_formats::Vector) +function execute_markdown!( + io::IO, + sb::Module, + block::String, + outputdir; + inputfile::String, + fake_source::String, + flavor::AbstractFlavor, + image_formats::Vector, +) # TODO: Deal with explicit display(...) calls - r, str, _ = execute_block(sb, block; inputfile=inputfile, fake_source=fake_source) + 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````" if r !== nothing && !REPL.ends_with_semicolon(block) if (flavor isa FranklinFlavor || flavor isa DocumenterFlavor) && Base.invokelatest(showable, MIME("text/html"), r) - htmlfence = flavor isa FranklinFlavor ? ("~~~" => "~~~") : ("```@raw html" => "```") + htmlfence = + flavor isa FranklinFlavor ? ("~~~" => "~~~") : ("```@raw html" => "```") write(io, "\n", htmlfence.first, "\n") Base.invokelatest(show, io, MIME("text/html"), r) write(io, "\n", htmlfence.second, "\n") @@ -668,8 +728,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) @@ -683,16 +743,21 @@ Generate a notebook from `inputfile` and write the result to `outputdir`. See the manual section on [Configuration](@ref) for documentation of possible configuration with `config` and other keyword arguments. """ -function notebook(inputfile, outputdir=pwd(); config::AbstractDict=Dict(), kwargs...) +function notebook(inputfile, outputdir = pwd(); config::AbstractDict = Dict(), kwargs...) # preprocessing and parsing - chunks, config = - preprocessor(inputfile, outputdir; user_config=config, user_kwargs=kwargs, type=:nb) + chunks, config = preprocessor( + inputfile, + outputdir; + user_config = config, + user_kwargs = kwargs, + type = :nb, + ) # create the notebook 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 @@ -708,14 +773,16 @@ function jupyter_notebook(chunks, config) chunktype = isa(chunk, MDChunk) ? "markdown" : "code" if !isempty(chunk.lines) && line_is_nbmeta(chunk.lines[1]) metatype, metadata = parse_nbmeta(chunk.lines[1]) - metatype !== nothing && metatype != chunktype && error("specifying a different cell type is not supported") + 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 + lines = + isa(chunk, MDChunk) ? 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 @@ -732,15 +799,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 @@ -753,8 +820,11 @@ function jupyter_notebook(chunks, config) @info "executing notebook `$(config["name"] * ".ipynb")`" try cd(config["literate_outputdir"]) do - nb = execute_notebook(nb; inputfile=config["literate_inputfile"], - fake_source=config["literate_outputfile"]) + nb = execute_notebook( + nb; + inputfile = config["literate_inputfile"], + fake_source = config["literate_outputfile"], + ) end catch err @error "error when executing notebook based on input file: " * @@ -773,7 +843,8 @@ function execute_notebook(nb; inputfile::String, fake_source::String) execution_count += 1 cell["execution_count"] = execution_count block = join(cell["source"]) - r, str, display_dicts = execute_block(sb, block; inputfile=inputfile, fake_source=fake_source) + r, str, display_dicts = + execute_block(sb, block; inputfile = inputfile, fake_source = fake_source) # str should go into stream if !isempty(str) @@ -875,14 +946,16 @@ function execute_block(sb::Module, block::String; inputfile::String, fake_source end popdisplay(disp) # IOCapture.capture has a try-catch so should always end up here if c.error - error(""" - $(sprint(showerror, c.value)) - when executing the following code block from inputfile `$(Base.contractuser(inputfile))` - - ```julia - $block - ``` - """) + error( + """ + $(sprint(showerror, c.value)) + when executing the following code block from inputfile `$(Base.contractuser(inputfile))` + + ```julia + $block + ``` + """, + ) end return c.value, c.output, disp.data end diff --git a/test/runtests.jl b/test/runtests.jl index f8fc514..aa51678 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -113,8 +113,8 @@ end expected_chunks = Chunk[ MDChunk(["" => "Line 1"]), CodeChunk(["Line 2"], false), - MDChunk(["" => "Line 3", "" => "","" => "Line 5"]), - CodeChunk(["Line 6", "","Line 8"], false), + MDChunk(["" => "Line 3", "" => "", "" => "Line 5"]), + CodeChunk(["Line 6", "", "Line 8"], false), MDChunk(["" => "Line 9"]), MDChunk(["" => "Line 11"]), CodeChunk(["Line 12"], false), @@ -146,7 +146,7 @@ end CodeChunk(["Line 64", " # Line 65", " Line 66", "Line 67"], false), CodeChunk(["# Line 73", "#", "# Line 75"], false), CodeChunk([" # Line 77", " #", " # Line 79"], false), - ] + ] parsed_chunks = Literate.parse(content) compare_chunks(parsed_chunks, expected_chunks) @@ -155,13 +155,13 @@ end iows = IOBuffer() for c in expected_chunks if isa(c, CodeChunk) - foreach(x-> println(io, x), c.lines) - foreach(x-> println(iows, x, " "), c.lines) + foreach(x -> println(io, x), c.lines) + foreach(x -> println(iows, x, " "), c.lines) else - foreach(x -> println(io, "# ", x), c.lines) + foreach(x -> println(io, "# ", x), c.lines) foreach(x -> println(iows, "# ", x, " "), c.lines) end - println(io, "#-") + println(io, "#-") println(iows, "#-") foreach(x -> println(iows), 1:rand(2:5)) end @@ -293,1073 +293,1322 @@ const GITLAB_ENV = Dict( (k => nothing for k in keys(TRAVIS_ENV))..., (k => nothing for k in keys(ACTIONS_ENV))..., ) -@testset "Literate.script" begin; Base.CoreLogging.with_logger(Base.CoreLogging.NullLogger()) do - mktempdir(@__DIR__) do sandbox - cd(sandbox) do - # write content to inputfile - inputfile = "inputfile.jl" - write(inputfile, content) - outdir = mktempdir(pwd()) - - # test defaults - withenv(TRAVIS_ENV...) do - Literate.script(inputfile, outdir) - end - expected_script = """ - x = 1 - - x * 1 - x * 1 +@testset "Literate.script" begin + Base.CoreLogging.with_logger(Base.CoreLogging.NullLogger()) do + mktempdir(@__DIR__) do sandbox + cd(sandbox) do + # write content to inputfile + inputfile = "inputfile.jl" + write(inputfile, content) + outdir = mktempdir(pwd()) + + # test defaults + withenv(TRAVIS_ENV...) do + Literate.script(inputfile, outdir) + end + expected_script = """ + x = 1 - x * 2 - x * 2 + x * 1 + x * 1 - x + 3 - x + 3 - # # Comment - # another comment - #| echo: false Quarto parameters + x * 2 + x * 2 - for i in 1:10 - print(i) + x + 3 + x + 3 + # # Comment + # another comment + #| echo: false Quarto parameters - end + for i in 1:10 + print(i) - # name: inputfile - # Link to repo root: https://github.com/fredrikekre/Literate.jl/blob/master/file.jl - # Link to nbviewer: https://nbviewer.jupyter.org/github/fredrikekre/Literate.jl/blob/gh-pages/v1.2.0/file.jl - # Link to binder: https://mybinder.org/v2/gh/fredrikekre/Literate.jl/gh-pages?filepath=v1.2.0/file.jl + end - # PLACEHOLDER3 - # PLACEHOLDER4 + # name: inputfile + # Link to repo root: https://github.com/fredrikekre/Literate.jl/blob/master/file.jl + # Link to nbviewer: https://nbviewer.jupyter.org/github/fredrikekre/Literate.jl/blob/gh-pages/v1.2.0/file.jl + # Link to binder: https://mybinder.org/v2/gh/fredrikekre/Literate.jl/gh-pages?filepath=v1.2.0/file.jl - for i in 1:10 + # PLACEHOLDER3 + # PLACEHOLDER4 - # Indented comment - end + for i in 1:10 - 1 + 1; + # Indented comment + end - hidden = 12 #hide - hidden * hidden #hide + 1 + 1; - hidden2 = 12 #hide - hidden2 * hidden2 + hidden = 12 #hide + hidden * hidden #hide - # This file was generated using Literate.jl, https://github.com/fredrikekre/Literate.jl + hidden2 = 12 #hide + hidden2 * hidden2 - """ - script = read(joinpath(outdir, "inputfile.jl"), String) - @test script == expected_script + # This file was generated using Literate.jl, https://github.com/fredrikekre/Literate.jl - # Travis with with PR preview build - withenv(TRAVIS_ENV..., - "TRAVIS_TAG" => "", - "TRAVIS_PULL_REQUEST" => "42") do - Literate.script(inputfile, outdir) - end - script = read(joinpath(outdir, "inputfile.jl"), String) - @test occursin("# Link to repo root: https://github.com/fredrikekre/Literate.jl/blob/master/file.jl", script) - @test occursin("# Link to nbviewer: https://nbviewer.jupyter.org/github/fredrikekre/Literate.jl/blob/gh-pages/previews/PR42/file.jl", script) - @test occursin("# Link to binder: https://mybinder.org/v2/gh/fredrikekre/Literate.jl/gh-pages?filepath=previews/PR42/file.jl", script) - - # Travis with no tag -> dev directory - withenv(TRAVIS_ENV..., - "TRAVIS_TAG" => "") do - Literate.script(inputfile, outdir) - end - script = read(joinpath(outdir, "inputfile.jl"), String) - @test occursin("# Link to repo root: https://github.com/fredrikekre/Literate.jl/blob/master/file.jl", script) - @test occursin("# Link to nbviewer: https://nbviewer.jupyter.org/github/fredrikekre/Literate.jl/blob/gh-pages/dev/file.jl", script) - @test occursin("# Link to binder: https://mybinder.org/v2/gh/fredrikekre/Literate.jl/gh-pages?filepath=dev/file.jl", script) - - # GitHub Actions with a tag - withenv(ACTIONS_ENV...) do - Literate.script(inputfile, outdir) - end - script = read(joinpath(outdir, "inputfile.jl"), String) - @test occursin("# Link to repo root: https://github.com/fredrikekre/Literate.jl/blob/master/file.jl", script) - @test occursin("# Link to nbviewer: https://nbviewer.jupyter.org/github/fredrikekre/Literate.jl/blob/gh-pages/v1.2.0/file.jl", script) - @test occursin("# Link to binder: https://mybinder.org/v2/gh/fredrikekre/Literate.jl/gh-pages?filepath=v1.2.0/file.jl", script) + """ + script = read(joinpath(outdir, "inputfile.jl"), String) + @test script == expected_script - # GitHub Actions with PR preview build - withenv(ACTIONS_ENV..., + # Travis with with PR preview build + withenv(TRAVIS_ENV..., "TRAVIS_TAG" => "", "TRAVIS_PULL_REQUEST" => "42") do + Literate.script(inputfile, outdir) + end + script = read(joinpath(outdir, "inputfile.jl"), String) + @test occursin( + "# Link to repo root: https://github.com/fredrikekre/Literate.jl/blob/master/file.jl", + script, + ) + @test occursin( + "# Link to nbviewer: https://nbviewer.jupyter.org/github/fredrikekre/Literate.jl/blob/gh-pages/previews/PR42/file.jl", + script, + ) + @test occursin( + "# Link to binder: https://mybinder.org/v2/gh/fredrikekre/Literate.jl/gh-pages?filepath=previews/PR42/file.jl", + script, + ) + + # Travis with no tag -> dev directory + withenv(TRAVIS_ENV..., "TRAVIS_TAG" => "") do + Literate.script(inputfile, outdir) + end + script = read(joinpath(outdir, "inputfile.jl"), String) + @test occursin( + "# Link to repo root: https://github.com/fredrikekre/Literate.jl/blob/master/file.jl", + script, + ) + @test occursin( + "# Link to nbviewer: https://nbviewer.jupyter.org/github/fredrikekre/Literate.jl/blob/gh-pages/dev/file.jl", + script, + ) + @test occursin( + "# Link to binder: https://mybinder.org/v2/gh/fredrikekre/Literate.jl/gh-pages?filepath=dev/file.jl", + script, + ) + + # GitHub Actions with a tag + withenv(ACTIONS_ENV...) do + Literate.script(inputfile, outdir) + end + script = read(joinpath(outdir, "inputfile.jl"), String) + @test occursin( + "# Link to repo root: https://github.com/fredrikekre/Literate.jl/blob/master/file.jl", + script, + ) + @test occursin( + "# Link to nbviewer: https://nbviewer.jupyter.org/github/fredrikekre/Literate.jl/blob/gh-pages/v1.2.0/file.jl", + script, + ) + @test occursin( + "# Link to binder: https://mybinder.org/v2/gh/fredrikekre/Literate.jl/gh-pages?filepath=v1.2.0/file.jl", + script, + ) + + # GitHub Actions with PR preview build + withenv( + ACTIONS_ENV..., "GITHUB_EVENT_NAME" => "pull_request", - "GITHUB_REF" => "refs/pull/42/merge") do - Literate.script(inputfile, outdir) - end - script = read(joinpath(outdir, "inputfile.jl"), String) - @test occursin("# Link to repo root: https://github.com/fredrikekre/Literate.jl/blob/master/file.jl", script) - @test occursin("# Link to nbviewer: https://nbviewer.jupyter.org/github/fredrikekre/Literate.jl/blob/gh-pages/previews/PR42/file.jl", script) - @test occursin("# Link to binder: https://mybinder.org/v2/gh/fredrikekre/Literate.jl/gh-pages?filepath=previews/PR42/file.jl", script) - - # GitHub Actions without a tag -> dev directory - withenv(ACTIONS_ENV..., - "GITHUB_REF" => "refs/heads/master") do - Literate.script(inputfile, outdir) - end - script = read(joinpath(outdir, "inputfile.jl"), String) - @test occursin("# Link to repo root: https://github.com/fredrikekre/Literate.jl/blob/master/file.jl", script) - @test occursin("# Link to nbviewer: https://nbviewer.jupyter.org/github/fredrikekre/Literate.jl/blob/gh-pages/dev/file.jl", script) - @test occursin("# Link to binder: https://mybinder.org/v2/gh/fredrikekre/Literate.jl/gh-pages?filepath=dev/file.jl", script) - - # building under DocumentationGenerator.jl - withenv("DOCUMENTATIONGENERATOR" => "true", - "DOCUMENTATIONGENERATOR_BASE_URL" => "pkg.julialang.org/docs/Literate/XPnWG/1.2.0") do - Literate.script(inputfile, outdir) + "GITHUB_REF" => "refs/pull/42/merge", + ) do + Literate.script(inputfile, outdir) + end + script = read(joinpath(outdir, "inputfile.jl"), String) + @test occursin( + "# Link to repo root: https://github.com/fredrikekre/Literate.jl/blob/master/file.jl", + script, + ) + @test occursin( + "# Link to nbviewer: https://nbviewer.jupyter.org/github/fredrikekre/Literate.jl/blob/gh-pages/previews/PR42/file.jl", + script, + ) + @test occursin( + "# Link to binder: https://mybinder.org/v2/gh/fredrikekre/Literate.jl/gh-pages?filepath=previews/PR42/file.jl", + script, + ) + + # GitHub Actions without a tag -> dev directory + withenv(ACTIONS_ENV..., "GITHUB_REF" => "refs/heads/master") do + Literate.script(inputfile, outdir) + end + script = read(joinpath(outdir, "inputfile.jl"), String) + @test occursin( + "# Link to repo root: https://github.com/fredrikekre/Literate.jl/blob/master/file.jl", + script, + ) + @test occursin( + "# Link to nbviewer: https://nbviewer.jupyter.org/github/fredrikekre/Literate.jl/blob/gh-pages/dev/file.jl", + script, + ) + @test occursin( + "# Link to binder: https://mybinder.org/v2/gh/fredrikekre/Literate.jl/gh-pages?filepath=dev/file.jl", + script, + ) + + # building under DocumentationGenerator.jl + withenv( + "DOCUMENTATIONGENERATOR" => "true", + "DOCUMENTATIONGENERATOR_BASE_URL" => "pkg.julialang.org/docs/Literate/XPnWG/1.2.0", + ) do + Literate.script(inputfile, outdir) + end + script = read(joinpath(outdir, "inputfile.jl"), String) + @test occursin( + "jupyter.org/urls/pkg.julialang.org/docs/Literate/XPnWG/1.2.0/file.jl", + script, + ) + @test_broken occursin( + "https://github.com/fredrikekre/Literate.jl/blob/master/file.jl", + script, + ) + + # pre- and post-processing + Literate.script( + inputfile, + outdir, + preprocess = x -> replace(x, "PLACEHOLDER3" => "3REDLOHECALP"), + postprocess = x -> replace(x, "PLACEHOLDER4" => "4REDLOHECALP"), + ) + script = read(joinpath(outdir, "inputfile.jl"), String) + @test !occursin("PLACEHOLDER1", script) + @test !occursin("PLACEHOLDER2", script) + @test !occursin("PLACEHOLDER3", script) + @test !occursin("PLACEHOLDER4", script) + @test occursin("3REDLOHECALP", script) + @test occursin("4REDLOHECALP", script) + + # name + Literate.script(inputfile, outdir, name = "foobar") + script = read(joinpath(outdir, "foobar.jl"), String) + @test occursin("name: foobar", script) + @test !occursin("name: inputfile", script) + @test !occursin("name: @__NAME__", script) + + # keep_comments + Literate.script(inputfile, outdir, keep_comments = true) + script = read(joinpath(outdir, "inputfile.jl"), String) + @test occursin("# # Example", script) + @test occursin("# foo, bar", script) + @test occursin("# \\int f(x) dx", script) + @test occursin("# First multiline", script) + @test occursin("# Second multiline comment", script) + + # mdstrings + mdstrings_file = "inputfile_mdstrings.jl" + write( + mdstrings_file, + """ +md\"\"\" +# Markdown header + +Content of the multiline markdown +string +\"\"\" +#- +#=== +# Markdown header 2 + +Content of the multiline +comment +===# +2 + 2 +""", + ) + Literate.script( + mdstrings_file, + outdir, + keep_comments = true, + credit = false, + ) + script = read(joinpath(outdir, mdstrings_file), String) + @test strip(script) == """ + md\"\"\" + + # Markdown header + + Content of the multiline markdown + string + \"\"\" + + # # Markdown header 2 + # + # Content of the multiline + # comment + + 2 + 2""" + Literate.script( + mdstrings_file, + outdir, + keep_comments = true, + mdstrings = true, + credit = false, + ) + script = read(joinpath(outdir, mdstrings_file), String) + @test strip(script) == """ + # # Markdown header + # + # Content of the multiline markdown + # string + + # # Markdown header 2 + # + # Content of the multiline + # comment + + 2 + 2""" + + # verify that inputfile exists + @test_throws ArgumentError Literate.script("nonexistent.jl", outdir) + + # default output directory + Literate.script(inputfile; name = "default-output-directory") + @test isfile("default-output-directory.jl") + @test_throws ArgumentError Literate.script(inputfile) end - script = read(joinpath(outdir, "inputfile.jl"), String) - @test occursin("jupyter.org/urls/pkg.julialang.org/docs/Literate/XPnWG/1.2.0/file.jl", script) - @test_broken occursin("https://github.com/fredrikekre/Literate.jl/blob/master/file.jl", script) - - # pre- and post-processing - Literate.script(inputfile, outdir, - preprocess = x -> replace(x, "PLACEHOLDER3" => "3REDLOHECALP"), - postprocess = x -> replace(x, "PLACEHOLDER4" => "4REDLOHECALP")) - script = read(joinpath(outdir, "inputfile.jl"), String) - @test !occursin("PLACEHOLDER1", script) - @test !occursin("PLACEHOLDER2", script) - @test !occursin("PLACEHOLDER3", script) - @test !occursin("PLACEHOLDER4", script) - @test occursin("3REDLOHECALP", script) - @test occursin("4REDLOHECALP", script) - - # name - Literate.script(inputfile, outdir, name = "foobar") - script = read(joinpath(outdir, "foobar.jl"), String) - @test occursin("name: foobar", script) - @test !occursin("name: inputfile", script) - @test !occursin("name: @__NAME__", script) - - # keep_comments - Literate.script(inputfile, outdir, keep_comments = true) - script = read(joinpath(outdir, "inputfile.jl"), String) - @test occursin("# # Example", script) - @test occursin("# foo, bar", script) - @test occursin("# \\int f(x) dx", script) - @test occursin("# First multiline", script) - @test occursin("# Second multiline comment", script) - - # mdstrings - mdstrings_file = "inputfile_mdstrings.jl" - write(mdstrings_file, """ - md\"\"\" - # Markdown header - - Content of the multiline markdown - string - \"\"\" - #- - #=== - # Markdown header 2 - - Content of the multiline - comment - ===# - 2 + 2 - """) - Literate.script(mdstrings_file, outdir, - keep_comments = true, credit=false) - script = read(joinpath(outdir, mdstrings_file), String) - @test strip(script) == """ - md\"\"\" - - # Markdown header - - Content of the multiline markdown - string - \"\"\" - - # # Markdown header 2 - # - # Content of the multiline - # comment - - 2 + 2""" - Literate.script(mdstrings_file, outdir, - keep_comments = true, mdstrings = true, credit=false) - script = read(joinpath(outdir, mdstrings_file), String) - @test strip(script) == """ - # # Markdown header - # - # Content of the multiline markdown - # string - - # # Markdown header 2 - # - # Content of the multiline - # comment - - 2 + 2""" - - # verify that inputfile exists - @test_throws ArgumentError Literate.script("nonexistent.jl", outdir) - - # default output directory - Literate.script(inputfile; name="default-output-directory") - @test isfile("default-output-directory.jl") - @test_throws ArgumentError Literate.script(inputfile) end end -end end - -@testset "Literate.markdown" begin; Base.CoreLogging.with_logger(Base.CoreLogging.NullLogger()) do - mktempdir(@__DIR__) do sandbox - cd(sandbox) do - # write content to inputfile - inputfile = "inputfile.jl" - write(inputfile, content) - outdir = mktempdir(pwd()) - - # test defaults - withenv(TRAVIS_ENV...) do - Literate.markdown(inputfile, outdir) - end - expected_markdown = """ - ```@meta - EditURL = "https://github.com/fredrikekre/Literate.jl/blob/master/test/$(basename(sandbox))/inputfile.jl" - ``` +end - # [Example](@id example-id) - [foo](@ref), [bar](@ref bbaarr) +@testset "Literate.markdown" begin + Base.CoreLogging.with_logger(Base.CoreLogging.NullLogger()) do + mktempdir(@__DIR__) do sandbox + cd(sandbox) do + # write content to inputfile + inputfile = "inputfile.jl" + write(inputfile, content) + outdir = mktempdir(pwd()) + + # test defaults + withenv(TRAVIS_ENV...) do + Literate.markdown(inputfile, outdir) + end + expected_markdown = """ + ```@meta + EditURL = "https://github.com/fredrikekre/Literate.jl/blob/master/test/$(basename(sandbox))/inputfile.jl" + ``` - ````@example inputfile - x = 1 - ```` + # [Example](@id example-id) + [foo](@ref), [bar](@ref bbaarr) - Only markdown - Only markdown + ````@example inputfile + x = 1 + ```` - ````@example inputfile - x + 1 - x + 1 - ```` + Only markdown + Only markdown - Not notebook - Not notebook + ````@example inputfile + x + 1 + x + 1 + ```` - ````@example inputfile - x * 2 - x * 2 - ```` + Not notebook + Not notebook - Not script - Not script + ````@example inputfile + x * 2 + x * 2 + ```` - ````@example inputfile - x * 3 - x * 3 - # # Comment - # another comment - #| echo: false Quarto parameters - ```` + Not script + Not script - ````@example inputfile; continued = true - for i in 1:10 - print(i) - ```` + ````@example inputfile + x * 3 + x * 3 + # # Comment + # another comment + #| echo: false Quarto parameters + ```` - some markdown in a code block + ````@example inputfile; continued = true + for i in 1:10 + print(i) + ```` - ````@example inputfile - end - ```` + some markdown in a code block - name: inputfile - Link to repo root: https://github.com/fredrikekre/Literate.jl/blob/master/file.jl - Link to nbviewer: https://nbviewer.jupyter.org/github/fredrikekre/Literate.jl/blob/gh-pages/v1.2.0/file.jl - Link to binder: https://mybinder.org/v2/gh/fredrikekre/Literate.jl/gh-pages?filepath=v1.2.0/file.jl + ````@example inputfile + end + ```` - ````@example inputfile - # name: inputfile - # Link to repo root: https://github.com/fredrikekre/Literate.jl/blob/master/file.jl - # Link to nbviewer: https://nbviewer.jupyter.org/github/fredrikekre/Literate.jl/blob/gh-pages/v1.2.0/file.jl - # Link to binder: https://mybinder.org/v2/gh/fredrikekre/Literate.jl/gh-pages?filepath=v1.2.0/file.jl - ```` + name: inputfile + Link to repo root: https://github.com/fredrikekre/Literate.jl/blob/master/file.jl + Link to nbviewer: https://nbviewer.jupyter.org/github/fredrikekre/Literate.jl/blob/gh-pages/v1.2.0/file.jl + Link to binder: https://mybinder.org/v2/gh/fredrikekre/Literate.jl/gh-pages?filepath=v1.2.0/file.jl - PLACEHOLDER1 - PLACEHOLDER2 + ````@example inputfile + # name: inputfile + # Link to repo root: https://github.com/fredrikekre/Literate.jl/blob/master/file.jl + # Link to nbviewer: https://nbviewer.jupyter.org/github/fredrikekre/Literate.jl/blob/gh-pages/v1.2.0/file.jl + # Link to binder: https://mybinder.org/v2/gh/fredrikekre/Literate.jl/gh-pages?filepath=v1.2.0/file.jl + ```` - ````@example inputfile - # PLACEHOLDER3 - # PLACEHOLDER4 - ```` + PLACEHOLDER1 + PLACEHOLDER2 - Some inline math: ``\\frac{df}{dx}``, some multiline inline math: ``y = - kx + m``, and some display math: - ```math - \\int f(x) dx - ``` + ````@example inputfile + # PLACEHOLDER3 + # PLACEHOLDER4 + ```` - Indented markdown + Some inline math: ``\\frac{df}{dx}``, some multiline inline math: ``y = + kx + m``, and some display math: + ```math + \\int f(x) dx + ``` - ````@example inputfile; continued = true - for i in 1:10 - ```` + Indented markdown - Indented markdown + ````@example inputfile; continued = true + for i in 1:10 + ```` - ````@example inputfile - # Indented comment - end - ```` + Indented markdown - Semicolon output supression + ````@example inputfile + # Indented comment + end + ```` - ````@example inputfile - 1 + 1; - nothing #hide - ```` + Semicolon output supression - Completely hidden + ````@example inputfile + 1 + 1; + nothing #hide + ```` - ````@example inputfile - hidden = 12 #hide - hidden * hidden #hide - ```` + Completely hidden - Partially hidden + ````@example inputfile + hidden = 12 #hide + hidden * hidden #hide + ```` - ````@example inputfile - hidden2 = 12 #hide - hidden2 * hidden2 - ```` + Partially hidden - First multiline - comment + ````@example inputfile + hidden2 = 12 #hide + hidden2 * hidden2 + ```` - Second multiline comment + First multiline + comment - --- + Second multiline comment - *This page was generated using [Literate.jl](https://github.com/fredrikekre/Literate.jl).* + --- - """ - markdown = read(joinpath(outdir, "inputfile.md"), String) - @test markdown == expected_markdown + *This page was generated using [Literate.jl](https://github.com/fredrikekre/Literate.jl).* - # Travis with PR preview build - withenv(TRAVIS_ENV..., - "TRAVIS_TAG" => "", - "TRAVIS_PULL_REQUEST" => "42") do - Literate.markdown(inputfile, outdir) - end - markdown = read(joinpath(outdir, "inputfile.md"), String) - @test occursin("Link to repo root: https://github.com/fredrikekre/Literate.jl/blob/master/file.jl", markdown) - @test occursin("Link to nbviewer: https://nbviewer.jupyter.org/github/fredrikekre/Literate.jl/blob/gh-pages/previews/PR42/file.jl", markdown) - @test occursin("Link to binder: https://mybinder.org/v2/gh/fredrikekre/Literate.jl/gh-pages?filepath=previews/PR42/file.jl", markdown) - @test occursin("EditURL = \"https://github.com/fredrikekre/Literate.jl/blob/master/test/$(basename(sandbox))/inputfile.jl\"", markdown) - - # Travis with no tag -> dev directory - withenv(TRAVIS_ENV..., - "TRAVIS_TAG" => "") do - Literate.markdown(inputfile, outdir) - end - markdown = read(joinpath(outdir, "inputfile.md"), String) - @test occursin("Link to repo root: https://github.com/fredrikekre/Literate.jl/blob/master/file.jl", markdown) - @test occursin("Link to nbviewer: https://nbviewer.jupyter.org/github/fredrikekre/Literate.jl/blob/gh-pages/dev/file.jl", markdown) - @test occursin("Link to binder: https://mybinder.org/v2/gh/fredrikekre/Literate.jl/gh-pages?filepath=dev/file.jl", markdown) - @test occursin("EditURL = \"https://github.com/fredrikekre/Literate.jl/blob/master/test/$(basename(sandbox))/inputfile.jl\"", markdown) - - # GitHub Actions with a tag - withenv(ACTIONS_ENV...) do - Literate.markdown(inputfile, outdir) - end - markdown = read(joinpath(outdir, "inputfile.md"), String) - @test occursin("Link to repo root: https://github.com/fredrikekre/Literate.jl/blob/master/file.jl", markdown) - @test occursin("Link to nbviewer: https://nbviewer.jupyter.org/github/fredrikekre/Literate.jl/blob/gh-pages/v1.2.0/file.jl", markdown) - @test occursin("Link to binder: https://mybinder.org/v2/gh/fredrikekre/Literate.jl/gh-pages?filepath=v1.2.0/file.jl", markdown) - @test occursin("EditURL = \"https://github.com/fredrikekre/Literate.jl/blob/master/test/$(basename(sandbox))/inputfile.jl\"", markdown) - - # GitHub Actions with PR preview build - withenv(ACTIONS_ENV..., + """ + markdown = read(joinpath(outdir, "inputfile.md"), String) + @test markdown == expected_markdown + + # Travis with PR preview build + withenv(TRAVIS_ENV..., "TRAVIS_TAG" => "", "TRAVIS_PULL_REQUEST" => "42") do + Literate.markdown(inputfile, outdir) + end + markdown = read(joinpath(outdir, "inputfile.md"), String) + @test occursin( + "Link to repo root: https://github.com/fredrikekre/Literate.jl/blob/master/file.jl", + markdown, + ) + @test occursin( + "Link to nbviewer: https://nbviewer.jupyter.org/github/fredrikekre/Literate.jl/blob/gh-pages/previews/PR42/file.jl", + markdown, + ) + @test occursin( + "Link to binder: https://mybinder.org/v2/gh/fredrikekre/Literate.jl/gh-pages?filepath=previews/PR42/file.jl", + markdown, + ) + @test occursin( + "EditURL = \"https://github.com/fredrikekre/Literate.jl/blob/master/test/$(basename(sandbox))/inputfile.jl\"", + markdown, + ) + + # Travis with no tag -> dev directory + withenv(TRAVIS_ENV..., "TRAVIS_TAG" => "") do + Literate.markdown(inputfile, outdir) + end + markdown = read(joinpath(outdir, "inputfile.md"), String) + @test occursin( + "Link to repo root: https://github.com/fredrikekre/Literate.jl/blob/master/file.jl", + markdown, + ) + @test occursin( + "Link to nbviewer: https://nbviewer.jupyter.org/github/fredrikekre/Literate.jl/blob/gh-pages/dev/file.jl", + markdown, + ) + @test occursin( + "Link to binder: https://mybinder.org/v2/gh/fredrikekre/Literate.jl/gh-pages?filepath=dev/file.jl", + markdown, + ) + @test occursin( + "EditURL = \"https://github.com/fredrikekre/Literate.jl/blob/master/test/$(basename(sandbox))/inputfile.jl\"", + markdown, + ) + + # GitHub Actions with a tag + withenv(ACTIONS_ENV...) do + Literate.markdown(inputfile, outdir) + end + markdown = read(joinpath(outdir, "inputfile.md"), String) + @test occursin( + "Link to repo root: https://github.com/fredrikekre/Literate.jl/blob/master/file.jl", + markdown, + ) + @test occursin( + "Link to nbviewer: https://nbviewer.jupyter.org/github/fredrikekre/Literate.jl/blob/gh-pages/v1.2.0/file.jl", + markdown, + ) + @test occursin( + "Link to binder: https://mybinder.org/v2/gh/fredrikekre/Literate.jl/gh-pages?filepath=v1.2.0/file.jl", + markdown, + ) + @test occursin( + "EditURL = \"https://github.com/fredrikekre/Literate.jl/blob/master/test/$(basename(sandbox))/inputfile.jl\"", + markdown, + ) + + # GitHub Actions with PR preview build + withenv( + ACTIONS_ENV..., "GITHUB_REF" => "refs/pull/42/merge", - "GITHUB_EVENT_NAME" => "pull_request") do - Literate.markdown(inputfile, outdir) - end - markdown = read(joinpath(outdir, "inputfile.md"), String) - @test occursin("Link to repo root: https://github.com/fredrikekre/Literate.jl/blob/master/file.jl", markdown) - @test occursin("Link to nbviewer: https://nbviewer.jupyter.org/github/fredrikekre/Literate.jl/blob/gh-pages/previews/PR42/file.jl", markdown) - @test occursin("Link to binder: https://mybinder.org/v2/gh/fredrikekre/Literate.jl/gh-pages?filepath=previews/PR42/file.jl", markdown) - @test occursin("EditURL = \"https://github.com/fredrikekre/Literate.jl/blob/master/test/$(basename(sandbox))/inputfile.jl\"", markdown) - - # GitHub Actions without a tag -> dev directory - withenv(ACTIONS_ENV..., - "GITHUB_REF" => "refs/heads/master") do - Literate.markdown(inputfile, outdir) - end - markdown = read(joinpath(outdir, "inputfile.md"), String) - @test occursin("Link to repo root: https://github.com/fredrikekre/Literate.jl/blob/master/file.jl", markdown) - @test occursin("Link to nbviewer: https://nbviewer.jupyter.org/github/fredrikekre/Literate.jl/blob/gh-pages/dev/file.jl", markdown) - @test occursin("Link to binder: https://mybinder.org/v2/gh/fredrikekre/Literate.jl/gh-pages?filepath=dev/file.jl", markdown) - @test occursin("EditURL = \"https://github.com/fredrikekre/Literate.jl/blob/master/test/$(basename(sandbox))/inputfile.jl\"", markdown) - - # GitLab CI with GitLab Pages - withenv(GITLAB_ENV...) do - Literate.markdown(inputfile, outdir) - end - markdown = read(joinpath(outdir, "inputfile.md"), String) - @test occursin("Link to repo root: https://gitlab.com/fredrikekre/Literate.jl/blob/master/file.jl", markdown) - @test occursin("Link to nbviewer: https://nbviewer.jupyter.org/urls/fredrikekre.gitlab.io/Literate.jl/file.jl", markdown) - @test_broken occursin("Link to binder: https://mybinder.org/v2/gh/fredrikekre/Literate.jl/gh-pages?filepath=dev/file.jl", markdown) - @test occursin("EditURL = \"https://gitlab.com/fredrikekre/Literate.jl/blob/master/test/$(basename(sandbox))/inputfile.jl\"", markdown) - - # building under DocumentationGenerator.jl - withenv("DOCUMENTATIONGENERATOR" => "true", - "DOCUMENTATIONGENERATOR_BASE_URL" => "pkg.julialang.org/docs/Literate/XPnWG/1.2.0") do - Literate.markdown(inputfile, outdir) - end - markdown = read(joinpath(outdir, "inputfile.md"), String) - @test occursin("jupyter.org/urls/pkg.julialang.org/docs/Literate/XPnWG/1.2.0/file.jl", markdown) - @test_broken occursin("https://github.com/fredrikekre/Literate.jl/blob/master/file.jl", markdown) - - # pre- and post-processing - Literate.markdown(inputfile, outdir, - preprocess = x -> replace(replace(x, "PLACEHOLDER1" => "1REDLOHECALP"), "PLACEHOLDER3" => "3REDLOHECALP"), - postprocess = x -> replace(replace(x, "PLACEHOLDER2" => "2REDLOHECALP"), "PLACEHOLDER4" => "4REDLOHECALP")) - markdown = read(joinpath(outdir, "inputfile.md"), String) - @test !occursin("PLACEHOLDER1", markdown) - @test !occursin("PLACEHOLDER2", markdown) - @test !occursin("PLACEHOLDER3", markdown) - @test !occursin("PLACEHOLDER4", markdown) - @test occursin("1REDLOHECALP", markdown) - @test occursin("2REDLOHECALP", markdown) - @test occursin("3REDLOHECALP", markdown) - @test occursin("4REDLOHECALP", markdown) - - # flavor = CommonMarkFlavor() - Literate.markdown(inputfile, outdir, flavor = Literate.CommonMarkFlavor()) - markdown = read(joinpath(outdir, "inputfile.md"), String) - @test occursin("```julia", markdown) - @test !occursin(r"`{3,}@example", markdown) - @test !occursin("continued = true", markdown) - @test !occursin("EditURL", markdown) - @test !occursin("#hide", markdown) - - # flavor = QuartoFlavor() - # execution of Quarto markdown is not allowed - let expected_error = ErrorException("QuartoFlavor does not support argument execute=true!") - @test_throws expected_error Literate.markdown("quarto.jl",flavor=Literate.QuartoFlavor(),execute=true) - end - Literate.markdown(inputfile, outdir, flavor = Literate.QuartoFlavor(),execute=false) - markdown = read(joinpath(outdir, "inputfile.qmd"), String) - @test occursin("```{julia}", markdown) - @test !occursin(r"`{3,}@example", markdown) - @test !occursin("continued = true", markdown) - @test !occursin("EditURL", markdown) - @test !occursin("#hide", markdown) - - # documenter = false (deprecated) - @test_deprecated r"The documenter=true keyword to Literate.markdown is deprecated" begin - Literate.markdown(inputfile, outdir, documenter = true) - end - @test_deprecated r"The documenter=false keyword to Literate.markdown is deprecated" begin - Literate.markdown(inputfile, outdir, documenter = false) - end - markdown = read(joinpath(outdir, "inputfile.md"), String) - @test occursin("```julia", markdown) - @test !occursin(r"`{3,}@example", markdown) - - # codefence - Literate.markdown(inputfile, outdir, codefence = "```c" => "```") - markdown = read(joinpath(outdir, "inputfile.md"), String) - @test occursin("```c", markdown) - @test !occursin(r"`{3,}@example", markdown) - @test !occursin("```julia", markdown) - - # name - Literate.markdown(inputfile, outdir, name = "foobar") - markdown = read(joinpath(outdir, "foobar.md"), String) - @test occursin(r"`{3,}@example foobar", markdown) - @test !occursin(r"`{3,}@example inputfile", markdown) - @test occursin("name: foobar", markdown) - @test !occursin("name: inputfile", markdown) - @test !occursin("name: @__NAME__", markdown) - - # mdstrings - Literate.markdown(inputfile, outdir, mdstrings = true) - markdown = read(joinpath(outdir, "inputfile.md"), String) - @test !occursin("md\"\"\"", markdown) - - # edit_commit - withenv(ACTIONS_ENV...) do - Literate.markdown(inputfile, outdir; edit_commit="retsam") + "GITHUB_EVENT_NAME" => "pull_request", + ) do + Literate.markdown(inputfile, outdir) + end + markdown = read(joinpath(outdir, "inputfile.md"), String) + @test occursin( + "Link to repo root: https://github.com/fredrikekre/Literate.jl/blob/master/file.jl", + markdown, + ) + @test occursin( + "Link to nbviewer: https://nbviewer.jupyter.org/github/fredrikekre/Literate.jl/blob/gh-pages/previews/PR42/file.jl", + markdown, + ) + @test occursin( + "Link to binder: https://mybinder.org/v2/gh/fredrikekre/Literate.jl/gh-pages?filepath=previews/PR42/file.jl", + markdown, + ) + @test occursin( + "EditURL = \"https://github.com/fredrikekre/Literate.jl/blob/master/test/$(basename(sandbox))/inputfile.jl\"", + markdown, + ) + + # GitHub Actions without a tag -> dev directory + withenv(ACTIONS_ENV..., "GITHUB_REF" => "refs/heads/master") do + Literate.markdown(inputfile, outdir) + end + markdown = read(joinpath(outdir, "inputfile.md"), String) + @test occursin( + "Link to repo root: https://github.com/fredrikekre/Literate.jl/blob/master/file.jl", + markdown, + ) + @test occursin( + "Link to nbviewer: https://nbviewer.jupyter.org/github/fredrikekre/Literate.jl/blob/gh-pages/dev/file.jl", + markdown, + ) + @test occursin( + "Link to binder: https://mybinder.org/v2/gh/fredrikekre/Literate.jl/gh-pages?filepath=dev/file.jl", + markdown, + ) + @test occursin( + "EditURL = \"https://github.com/fredrikekre/Literate.jl/blob/master/test/$(basename(sandbox))/inputfile.jl\"", + markdown, + ) + + # GitLab CI with GitLab Pages + withenv(GITLAB_ENV...) do + Literate.markdown(inputfile, outdir) + end + markdown = read(joinpath(outdir, "inputfile.md"), String) + @test occursin( + "Link to repo root: https://gitlab.com/fredrikekre/Literate.jl/blob/master/file.jl", + markdown, + ) + @test occursin( + "Link to nbviewer: https://nbviewer.jupyter.org/urls/fredrikekre.gitlab.io/Literate.jl/file.jl", + markdown, + ) + @test_broken occursin( + "Link to binder: https://mybinder.org/v2/gh/fredrikekre/Literate.jl/gh-pages?filepath=dev/file.jl", + markdown, + ) + @test occursin( + "EditURL = \"https://gitlab.com/fredrikekre/Literate.jl/blob/master/test/$(basename(sandbox))/inputfile.jl\"", + markdown, + ) + + # building under DocumentationGenerator.jl + withenv( + "DOCUMENTATIONGENERATOR" => "true", + "DOCUMENTATIONGENERATOR_BASE_URL" => "pkg.julialang.org/docs/Literate/XPnWG/1.2.0", + ) do + Literate.markdown(inputfile, outdir) + end + markdown = read(joinpath(outdir, "inputfile.md"), String) + @test occursin( + "jupyter.org/urls/pkg.julialang.org/docs/Literate/XPnWG/1.2.0/file.jl", + markdown, + ) + @test_broken occursin( + "https://github.com/fredrikekre/Literate.jl/blob/master/file.jl", + markdown, + ) + + # pre- and post-processing + Literate.markdown( + inputfile, + outdir, + preprocess = x -> replace( + replace(x, "PLACEHOLDER1" => "1REDLOHECALP"), + "PLACEHOLDER3" => "3REDLOHECALP", + ), + postprocess = x -> replace( + replace(x, "PLACEHOLDER2" => "2REDLOHECALP"), + "PLACEHOLDER4" => "4REDLOHECALP", + ), + ) + markdown = read(joinpath(outdir, "inputfile.md"), String) + @test !occursin("PLACEHOLDER1", markdown) + @test !occursin("PLACEHOLDER2", markdown) + @test !occursin("PLACEHOLDER3", markdown) + @test !occursin("PLACEHOLDER4", markdown) + @test occursin("1REDLOHECALP", markdown) + @test occursin("2REDLOHECALP", markdown) + @test occursin("3REDLOHECALP", markdown) + @test occursin("4REDLOHECALP", markdown) + + # flavor = CommonMarkFlavor() + Literate.markdown(inputfile, outdir, flavor = Literate.CommonMarkFlavor()) + markdown = read(joinpath(outdir, "inputfile.md"), String) + @test occursin("```julia", markdown) + @test !occursin(r"`{3,}@example", markdown) + @test !occursin("continued = true", markdown) + @test !occursin("EditURL", markdown) + @test !occursin("#hide", markdown) + + # flavor = QuartoFlavor() + # execution of Quarto markdown is not allowed + let expected_error = ErrorException( + "QuartoFlavor does not support argument execute=true!", + ) + @test_throws expected_error Literate.markdown( + "quarto.jl", + flavor = Literate.QuartoFlavor(), + execute = true, + ) + end + Literate.markdown( + inputfile, + outdir, + flavor = Literate.QuartoFlavor(), + execute = false, + ) + markdown = read(joinpath(outdir, "inputfile.qmd"), String) + @test occursin("```{julia}", markdown) + @test !occursin(r"`{3,}@example", markdown) + @test !occursin("continued = true", markdown) + @test !occursin("EditURL", markdown) + @test !occursin("#hide", markdown) + + # documenter = false (deprecated) + @test_deprecated r"The documenter=true keyword to Literate.markdown is deprecated" begin + Literate.markdown(inputfile, outdir, documenter = true) + end + @test_deprecated r"The documenter=false keyword to Literate.markdown is deprecated" begin + Literate.markdown(inputfile, outdir, documenter = false) + end + markdown = read(joinpath(outdir, "inputfile.md"), String) + @test occursin("```julia", markdown) + @test !occursin(r"`{3,}@example", markdown) + + # codefence + Literate.markdown(inputfile, outdir, codefence = "```c" => "```") + markdown = read(joinpath(outdir, "inputfile.md"), String) + @test occursin("```c", markdown) + @test !occursin(r"`{3,}@example", markdown) + @test !occursin("```julia", markdown) + + # name + Literate.markdown(inputfile, outdir, name = "foobar") + markdown = read(joinpath(outdir, "foobar.md"), String) + @test occursin(r"`{3,}@example foobar", markdown) + @test !occursin(r"`{3,}@example inputfile", markdown) + @test occursin("name: foobar", markdown) + @test !occursin("name: inputfile", markdown) + @test !occursin("name: @__NAME__", markdown) + + # mdstrings + Literate.markdown(inputfile, outdir, mdstrings = true) + markdown = read(joinpath(outdir, "inputfile.md"), String) + @test !occursin("md\"\"\"", markdown) + + # edit_commit + withenv(ACTIONS_ENV...) do + Literate.markdown(inputfile, outdir; edit_commit = "retsam") + end + markdown = read(joinpath(outdir, "inputfile.md"), String) + @test occursin("blob/retsam/", markdown) + @test !occursin("blob/master/", markdown) + + # execute + write( + inputfile, + """ + using DisplayAs + #- + 1+1 + #- + [1 2; 3 4] + #- + struct PNG end + Base.show(io::IO, mime::MIME"image/png", ::PNG) = print(io, "PNG") + PNG() + #- + struct JPEG end + Base.show(io::IO, mime::MIME"image/jpeg", ::JPEG) = print(io, "JPEG") + JPEG() + #- + struct SVG end + Base.show(io::IO, mime::MIME"image/svg+xml", ::SVG) = print(io, "SVG") + SVG() + #- + struct MD end + Base.show(io::IO, mime::MIME"text/markdown", ::MD) = print(io, "# " * "MD") + Base.show(io::IO, mime::MIME"text/html", ::MD) = + print(io, "

" * "MD" * "

") + #- + DisplayAs.MD(MD()) + #- + DisplayAs.HTML(MD()) + #- + struct Plain end + Base.showable(::MIME, ::Plain) = false + Base.showable(::MIME"text/plain", ::Plain) = true + Base.show(::IO, ::MIME, ::Plain) = error("only plain output supported") + Base.show(io::IO, ::MIME"text/plain", ::Plain) = print(io, "Plain") + Plain() + #- + print("hello"); print(stdout, ", "); print(stderr, "world") + #- + print("hej, världen") + 42 + #- + 123+123; + #- + nothing + #- + print("hello there") + nothing + #- + a = 2 + 2 + print("a: ", a); nothing #hide + #- + 47 #hide + #- + (@__DIR__) == pwd() ? "cwd correct" : "cwd incorrect" + #- + basename(@__FILE__) + """, + ) + Literate.markdown(inputfile, outdir; execute = true) + markdown = read(joinpath(outdir, "inputfile.md"), String) + @test occursin("```\n2\n```", markdown) # text/plain + @test occursin("```\n2×2 $(Matrix{Int}):\n 1 2\n 3 4\n```", markdown) # text/plain + @test occursin(r"!\[\]\(\d+\.png\)", markdown) # image/png + @test occursin(r"!\[\]\(\d+\.jpeg\)", markdown) # image/jpeg + @test occursin(r"!\[\]\(\d+\.svg\)", markdown) # image/svg+xml, fredrikekre/Literate.jl#182 + @test occursin("# MD", markdown) # text/markdown + @test occursin("```@raw html\n

MD

\n```", markdown) # text/html + @test occursin("```\nPlain\n```", markdown) # text/plain, fredrikekre/Literate#187 + @test occursin("```\nhello, world\n```", markdown) # stdout/stderr + @test occursin("```\n42\n```", markdown) # result over stdout/stderr + @test occursin("```julia\n123+123;\n```", markdown) # no additional `nothing #hide`, fredrikekre/Literate.jl/issues/166#issuecomment-979987878 + @test !occursin("246", markdown) # empty output because trailing ; + @test !occursin("```\nnothing\n```", markdown) # empty output because nothing as return value + @test occursin("```\nhello there\n```", markdown) # nothing as return value, non-empty stdout + @test occursin("```julia\na = 2 + 2\n```", markdown) # line with `#hide` removed + @test occursin("```\na: 4\n```", markdown) # nothing as return value, non-empty stdout + @test !occursin("```julia\n47 #hide\n```", markdown) # line with `#hide` removed + @test !occursin("```julia\n```", markdown) # no empty code block + @test occursin("```\n47\n```", markdown) # return value (even though line/block removed) + @test occursin("```\n\"cwd correct\"\n```", markdown) # Correct cwd (@__DIR__) + @test occursin("```\n\"inputfile.md\"\n```", markdown) # Correct source file (@__FILE__) + + # FranklinFlavor + Literate.markdown( + inputfile, + outdir; + execute = true, + flavor = Literate.FranklinFlavor(), + ) + markdown = read(joinpath(outdir, "inputfile.md"), String) + @test occursin("# MD", markdown) # text/markdown + @test occursin("~~~\n

MD

\n~~~", markdown) # text/html + + # QuartoFlavor file extension + write(inputfile, "#=\r\nhello world\n=#\r\n") + _, config = Literate.preprocessor( + inputfile, + outdir; + user_kwargs = (), + user_config = Dict("flavor" => Literate.QuartoFlavor()), + type = :md, + ) + @test config["literate_ext"] == ".qmd" + + # verify that inputfile exists + @test_throws ArgumentError Literate.markdown("nonexistent.jl", outdir) + + # default output directory + @test !isfile("inputfile.md") + Literate.markdown(inputfile; execute = false) + @test isfile("inputfile.md") + + # fredrikekre/Literate.jl#165: \r\n line endings with multiline comments/mdstrings + write(inputfile, "#=\r\nhello world\r\nhej världen\r\n=#\r\n") + chunks, _ = Literate.preprocessor( + inputfile, + outdir; + user_kwargs = (), + user_config = (), + type = :md, + ) + @test chunks[2].lines == ["" => "hello world", "" => "hej världen"] + write(inputfile, "md\"\"\"\r\nhello world\r\nhej världen\r\n\"\"\"\r\n") + chunks, _ = Literate.preprocessor( + inputfile, + outdir; + user_kwargs = pairs((; mdstrings = true)), + user_config = (), + type = :md, + ) + @test chunks[2].lines == ["" => "hello world", "" => "hej världen"] + + # fredrikekre/Literate.jl#168 + f = "file with space.jl" + write(f, "1 + 1") + Literate.markdown(f, outdir) + @test occursin( + "file_with_space", + read(joinpath(outdir, "file with space.md"), String), + ) end - markdown = read(joinpath(outdir, "inputfile.md"), String) - @test occursin("blob/retsam/", markdown) - @test !occursin("blob/master/", markdown) - - # execute - write(inputfile, """ - using DisplayAs - #- - 1+1 - #- - [1 2; 3 4] - #- - struct PNG end - Base.show(io::IO, mime::MIME"image/png", ::PNG) = print(io, "PNG") - PNG() - #- - struct JPEG end - Base.show(io::IO, mime::MIME"image/jpeg", ::JPEG) = print(io, "JPEG") - JPEG() - #- - struct SVG end - Base.show(io::IO, mime::MIME"image/svg+xml", ::SVG) = print(io, "SVG") - SVG() - #- - struct MD end - Base.show(io::IO, mime::MIME"text/markdown", ::MD) = print(io, "# " * "MD") - Base.show(io::IO, mime::MIME"text/html", ::MD) = - print(io, "

" * "MD" * "

") - #- - DisplayAs.MD(MD()) - #- - DisplayAs.HTML(MD()) - #- - struct Plain end - Base.showable(::MIME, ::Plain) = false - Base.showable(::MIME"text/plain", ::Plain) = true - Base.show(::IO, ::MIME, ::Plain) = error("only plain output supported") - Base.show(io::IO, ::MIME"text/plain", ::Plain) = print(io, "Plain") - Plain() - #- - print("hello"); print(stdout, ", "); print(stderr, "world") - #- - print("hej, världen") - 42 - #- - 123+123; - #- - nothing - #- - print("hello there") - nothing - #- - a = 2 + 2 - print("a: ", a); nothing #hide - #- - 47 #hide - #- - (@__DIR__) == pwd() ? "cwd correct" : "cwd incorrect" - #- - basename(@__FILE__) - """) - Literate.markdown(inputfile, outdir; execute=true) - markdown = read(joinpath(outdir, "inputfile.md"), String) - @test occursin("```\n2\n```", markdown) # text/plain - @test occursin("```\n2×2 $(Matrix{Int}):\n 1 2\n 3 4\n```", markdown) # text/plain - @test occursin(r"!\[\]\(\d+\.png\)", markdown) # image/png - @test occursin(r"!\[\]\(\d+\.jpeg\)", markdown) # image/jpeg - @test occursin(r"!\[\]\(\d+\.svg\)", markdown) # image/svg+xml, fredrikekre/Literate.jl#182 - @test occursin("# MD", markdown) # text/markdown - @test occursin("```@raw html\n

MD

\n```", markdown) # text/html - @test occursin("```\nPlain\n```", markdown) # text/plain, fredrikekre/Literate#187 - @test occursin("```\nhello, world\n```", markdown) # stdout/stderr - @test occursin("```\n42\n```", markdown) # result over stdout/stderr - @test occursin("```julia\n123+123;\n```", markdown) # no additional `nothing #hide`, fredrikekre/Literate.jl/issues/166#issuecomment-979987878 - @test !occursin("246", markdown) # empty output because trailing ; - @test !occursin("```\nnothing\n```", markdown) # empty output because nothing as return value - @test occursin("```\nhello there\n```", markdown) # nothing as return value, non-empty stdout - @test occursin("```julia\na = 2 + 2\n```", markdown) # line with `#hide` removed - @test occursin("```\na: 4\n```", markdown) # nothing as return value, non-empty stdout - @test !occursin("```julia\n47 #hide\n```", markdown) # line with `#hide` removed - @test !occursin("```julia\n```", markdown) # no empty code block - @test occursin("```\n47\n```", markdown) # return value (even though line/block removed) - @test occursin("```\n\"cwd correct\"\n```", markdown) # Correct cwd (@__DIR__) - @test occursin("```\n\"inputfile.md\"\n```", markdown) # Correct source file (@__FILE__) - - # FranklinFlavor - Literate.markdown(inputfile, outdir; execute=true, flavor=Literate.FranklinFlavor()) - markdown = read(joinpath(outdir, "inputfile.md"), String) - @test occursin("# MD", markdown) # text/markdown - @test occursin("~~~\n

MD

\n~~~", markdown) # text/html - - # QuartoFlavor file extension - write(inputfile, "#=\r\nhello world\n=#\r\n") - _, config = Literate.preprocessor(inputfile, outdir; user_kwargs=(), user_config=Dict("flavor"=>Literate.QuartoFlavor()), type=:md) - @test config["literate_ext"] == ".qmd" - - # verify that inputfile exists - @test_throws ArgumentError Literate.markdown("nonexistent.jl", outdir) - - # default output directory - @test !isfile("inputfile.md") - Literate.markdown(inputfile; execute=false) - @test isfile("inputfile.md") - - # fredrikekre/Literate.jl#165: \r\n line endings with multiline comments/mdstrings - write(inputfile, "#=\r\nhello world\r\nhej världen\r\n=#\r\n") - chunks, _ = Literate.preprocessor(inputfile, outdir; user_kwargs=(), user_config=(), type=:md) - @test chunks[2].lines == ["" => "hello world", "" => "hej världen"] - write(inputfile, "md\"\"\"\r\nhello world\r\nhej världen\r\n\"\"\"\r\n") - chunks, _ = Literate.preprocessor(inputfile, outdir; user_kwargs=pairs((; mdstrings=true)), - user_config=(), type=:md) - @test chunks[2].lines == ["" => "hello world", "" => "hej världen"] - - # fredrikekre/Literate.jl#168 - f = "file with space.jl" - write(f, "1 + 1") - Literate.markdown(f, outdir) - @test occursin("file_with_space", read(joinpath(outdir, "file with space.md"), String)) end end -end end - -@testset "Literate.notebook" begin; Base.CoreLogging.with_logger(Base.CoreLogging.NullLogger()) do - mktempdir(@__DIR__) do sandbox - cd(sandbox) do - # write content to inputfile - inputfile = "inputfile.jl" - write(inputfile, content) - outdir = mktempdir(pwd()) - - # test defaults - withenv(TRAVIS_ENV...) do - Literate.notebook(inputfile, outdir, execute = false) - end - expected_cells = rstrip.(( - """ - "cells": [ - """, - - """ - "source": [ - "# Example\\n", - "foo, bar" - ] - """, - - """ - "source": [ - "x = 1" - ] - """, - - """ - "source": [ - "Not markdown\\n", - "Not markdown" - ], - """, - - """ - "source": [ - "x * 1\\n", - "x * 1" - ], - """, - - """ - "source": [ - "Only notebook\\n", - "Only notebook" - ] - """, - - """ - "source": [ - "x + 2\\n", - "x + 2" - ] - """, - - """ - "source": [ - "Not script\\n", - "Not script" - ], - """, - - """ - "source": [ - "x * 3\\n", - "x * 3\\n", - "# # Comment\\n", - "# another comment\\n", - "#| echo: false Quarto parameters" - ], - """, - - """ - "source": [ - "for i in 1:10\\n", - " print(i)\\n", - "# some markdown in a code block\\n", - "end" - ] - """, - - """ - "source": [ - "name: inputfile\\n", - "Link to repo root: https://github.com/fredrikekre/Literate.jl/blob/master/file.jl\\n", - "Link to nbviewer: https://nbviewer.jupyter.org/github/fredrikekre/Literate.jl/blob/gh-pages/v1.2.0/file.jl\\n", - "Link to binder: https://mybinder.org/v2/gh/fredrikekre/Literate.jl/gh-pages?filepath=v1.2.0/file.jl" - ] - """, - - """ - "source": [ - "# name: inputfile\\n", - "# Link to repo root: https://github.com/fredrikekre/Literate.jl/blob/master/file.jl\\n", - "# Link to nbviewer: https://nbviewer.jupyter.org/github/fredrikekre/Literate.jl/blob/gh-pages/v1.2.0/file.jl\\n", - "# Link to binder: https://mybinder.org/v2/gh/fredrikekre/Literate.jl/gh-pages?filepath=v1.2.0/file.jl" - ] - """, - - """ - "source": [ - "PLACEHOLDER1\\n", - "PLACEHOLDER2" - ] - """, - - """ - "source": [ - "# PLACEHOLDER3\\n", - "# PLACEHOLDER4" - ] - """, - - """ - "source": [ - "Some inline math: \$\\\\frac{df}{dx}\$, some multiline inline math: \$y =\\n", - "kx + m\$, and some display math:\\n", - "\$\$\\n", - "\\\\int f(x) dx\\n", - "\$\$" - ] - """, - - """ - "source": [ - "Indented markdown" - ] - """, - - """ - "source": [ - "for i in 1:10\\n", - " # Indented markdown\\n", - " # Indented comment\\n", - "end" - ] - """, - - """ - "metadata": { - "meta": "data" - } - """, - - """ - "source": [ - "First multiline\\n", - "comment" - ] - """, - - """ - "source": [ - "---\\n", - "\\n", - "*This notebook was generated using [Literate.jl](https://github.com/fredrikekre/Literate.jl).*" - ] - """)) - - notebook = read(joinpath(outdir, "inputfile.ipynb"), String) - - lastidx = 1 - for cell in expected_cells - idx = findnext(cell, notebook, lastidx) - @test idx !== nothing - lastidx = nextind(notebook, last(idx)) - end - # test some of the required metadata - for metadata in (" \"nbformat\": ", " \"nbformat_minor\": ", " \"metadata\": {", " \"language_info\": {", - " \"file_extension\": \".jl\"", " \"mimetype\": \"application/julia\"", - " \"name\": \"julia\"", " \"version\": ", " \"kernelspec\": {", - " \"name\": \"julia-", " \"display_name\": \"Julia ", " \"language\": \"julia\"") - @test occursin(metadata, notebook) - end - - # no tag -> latest directory - withenv(TRAVIS_ENV..., - "TRAVIS_TAG" => "") do - Literate.notebook(inputfile, outdir, execute = false) - end - notebook = read(joinpath(outdir, "inputfile.ipynb"), String) - @test occursin("fredrikekre/Literate.jl/blob/gh-pages/dev/", notebook) +end - # GitHub Actions with a tag - withenv(ACTIONS_ENV...) do - Literate.notebook(inputfile, outdir, execute = false) - end - notebook = read(joinpath(outdir, "inputfile.ipynb"), String) - @test occursin("fredrikekre/Literate.jl/blob/gh-pages/v1.2.0/", notebook) +@testset "Literate.notebook" begin + Base.CoreLogging.with_logger(Base.CoreLogging.NullLogger()) do + mktempdir(@__DIR__) do sandbox + cd(sandbox) do + # write content to inputfile + inputfile = "inputfile.jl" + write(inputfile, content) + outdir = mktempdir(pwd()) + + # test defaults + withenv(TRAVIS_ENV...) do + Literate.notebook(inputfile, outdir, execute = false) + end + expected_cells = + rstrip.(( + """ + "cells": [ + """, + """ + "source": [ + "# Example\\n", + "foo, bar" + ] + """, + """ + "source": [ + "x = 1" + ] + """, + """ + "source": [ + "Not markdown\\n", + "Not markdown" + ], + """, + """ + "source": [ + "x * 1\\n", + "x * 1" + ], + """, + """ + "source": [ + "Only notebook\\n", + "Only notebook" + ] + """, + """ + "source": [ + "x + 2\\n", + "x + 2" + ] + """, + """ + "source": [ + "Not script\\n", + "Not script" + ], + """, + """ + "source": [ + "x * 3\\n", + "x * 3\\n", + "# # Comment\\n", + "# another comment\\n", + "#| echo: false Quarto parameters" + ], + """, + """ + "source": [ + "for i in 1:10\\n", + " print(i)\\n", + "# some markdown in a code block\\n", + "end" + ] + """, + """ + "source": [ + "name: inputfile\\n", + "Link to repo root: https://github.com/fredrikekre/Literate.jl/blob/master/file.jl\\n", + "Link to nbviewer: https://nbviewer.jupyter.org/github/fredrikekre/Literate.jl/blob/gh-pages/v1.2.0/file.jl\\n", + "Link to binder: https://mybinder.org/v2/gh/fredrikekre/Literate.jl/gh-pages?filepath=v1.2.0/file.jl" + ] + """, + """ + "source": [ + "# name: inputfile\\n", + "# Link to repo root: https://github.com/fredrikekre/Literate.jl/blob/master/file.jl\\n", + "# Link to nbviewer: https://nbviewer.jupyter.org/github/fredrikekre/Literate.jl/blob/gh-pages/v1.2.0/file.jl\\n", + "# Link to binder: https://mybinder.org/v2/gh/fredrikekre/Literate.jl/gh-pages?filepath=v1.2.0/file.jl" + ] + """, + """ + "source": [ + "PLACEHOLDER1\\n", + "PLACEHOLDER2" + ] + """, + """ + "source": [ + "# PLACEHOLDER3\\n", + "# PLACEHOLDER4" + ] + """, + """ + "source": [ + "Some inline math: \$\\\\frac{df}{dx}\$, some multiline inline math: \$y =\\n", + "kx + m\$, and some display math:\\n", + "\$\$\\n", + "\\\\int f(x) dx\\n", + "\$\$" + ] + """, + """ + "source": [ + "Indented markdown" + ] + """, + """ + "source": [ + "for i in 1:10\\n", + " # Indented markdown\\n", + " # Indented comment\\n", + "end" + ] + """, + """ + "metadata": { + "meta": "data" + } + """, + """ + "source": [ + "First multiline\\n", + "comment" + ] + """, + """ + "source": [ + "---\\n", + "\\n", + "*This notebook was generated using [Literate.jl](https://github.com/fredrikekre/Literate.jl).*" + ] + """, + )) + + notebook = read(joinpath(outdir, "inputfile.ipynb"), String) + + lastidx = 1 + for cell in expected_cells + idx = findnext(cell, notebook, lastidx) + @test idx !== nothing + lastidx = nextind(notebook, last(idx)) + end + # test some of the required metadata + for metadata in ( + " \"nbformat\": ", + " \"nbformat_minor\": ", + " \"metadata\": {", + " \"language_info\": {", + " \"file_extension\": \".jl\"", + " \"mimetype\": \"application/julia\"", + " \"name\": \"julia\"", + " \"version\": ", + " \"kernelspec\": {", + " \"name\": \"julia-", + " \"display_name\": \"Julia ", + " \"language\": \"julia\"", + ) + @test occursin(metadata, notebook) + end - # GitHub Actions with PR preview build - withenv(ACTIONS_ENV..., - "GITHUB_REF" => "refs/pull/42/merge", - "GITHUB_EVENT_NAME" => "pull_request") do - Literate.notebook(inputfile, outdir, execute = false) - end - notebook = read(joinpath(outdir, "inputfile.ipynb"), String) - @test occursin("fredrikekre/Literate.jl/blob/gh-pages/previews/PR42/", notebook) + # no tag -> latest directory + withenv(TRAVIS_ENV..., "TRAVIS_TAG" => "") do + Literate.notebook(inputfile, outdir, execute = false) + end + notebook = read(joinpath(outdir, "inputfile.ipynb"), String) + @test occursin("fredrikekre/Literate.jl/blob/gh-pages/dev/", notebook) - # GitHub Actions without a tag - withenv(ACTIONS_ENV..., - "GITHUB_REF" => "refs/heads/master") do - Literate.notebook(inputfile, outdir, execute = false) - end - notebook = read(joinpath(outdir, "inputfile.ipynb"), String) - @test occursin("fredrikekre/Literate.jl/blob/gh-pages/dev/", notebook) + # GitHub Actions with a tag + withenv(ACTIONS_ENV...) do + Literate.notebook(inputfile, outdir, execute = false) + end + notebook = read(joinpath(outdir, "inputfile.ipynb"), String) + @test occursin("fredrikekre/Literate.jl/blob/gh-pages/v1.2.0/", notebook) - # building under DocumentationGenerator.jl - withenv("DOCUMENTATIONGENERATOR" => "true", - "DOCUMENTATIONGENERATOR_BASE_URL" => "pkg.julialang.org/docs/Literate/XPnWG/1.2.0") do - Literate.notebook(inputfile, outdir, execute = false) - end - notebook = read(joinpath(outdir, "inputfile.ipynb"), String) - @test occursin("jupyter.org/urls/pkg.julialang.org/docs/Literate/XPnWG/1.2.0/file.jl", notebook) - @test_broken occursin("https://github.com/fredrikekre/Literate.jl/blob/master/file.jl", notebook) - - # pre- and post-processing - function post(nb) - for cell in nb["cells"] - for i in eachindex(cell["source"]) - cell["source"][i] = replace(cell["source"][i], "PLACEHOLDER2" => "2REDLOHECALP") - cell["source"][i] = replace(cell["source"][i], "PLACEHOLDER4" => "4REDLOHECALP") + # GitHub Actions with PR preview build + withenv( + ACTIONS_ENV..., + "GITHUB_REF" => "refs/pull/42/merge", + "GITHUB_EVENT_NAME" => "pull_request", + ) do + Literate.notebook(inputfile, outdir, execute = false) + end + notebook = read(joinpath(outdir, "inputfile.ipynb"), String) + @test occursin( + "fredrikekre/Literate.jl/blob/gh-pages/previews/PR42/", + notebook, + ) + + # GitHub Actions without a tag + withenv(ACTIONS_ENV..., "GITHUB_REF" => "refs/heads/master") do + Literate.notebook(inputfile, outdir, execute = false) + end + notebook = read(joinpath(outdir, "inputfile.ipynb"), String) + @test occursin("fredrikekre/Literate.jl/blob/gh-pages/dev/", notebook) + + # building under DocumentationGenerator.jl + withenv( + "DOCUMENTATIONGENERATOR" => "true", + "DOCUMENTATIONGENERATOR_BASE_URL" => "pkg.julialang.org/docs/Literate/XPnWG/1.2.0", + ) do + Literate.notebook(inputfile, outdir, execute = false) + end + notebook = read(joinpath(outdir, "inputfile.ipynb"), String) + @test occursin( + "jupyter.org/urls/pkg.julialang.org/docs/Literate/XPnWG/1.2.0/file.jl", + notebook, + ) + @test_broken occursin( + "https://github.com/fredrikekre/Literate.jl/blob/master/file.jl", + notebook, + ) + + # pre- and post-processing + function post(nb) + for cell in nb["cells"] + for i in eachindex(cell["source"]) + cell["source"][i] = + replace(cell["source"][i], "PLACEHOLDER2" => "2REDLOHECALP") + cell["source"][i] = + replace(cell["source"][i], "PLACEHOLDER4" => "4REDLOHECALP") + end end + return nb + end + Literate.notebook( + inputfile, + outdir, + execute = false, + preprocess = x -> replace( + replace(x, "PLACEHOLDER1" => "1REDLOHECALP"), + "PLACEHOLDER3" => "3REDLOHECALP", + ), + postprocess = post, + ) + notebook = read(joinpath(outdir, "inputfile.ipynb"), String) + @test !occursin("PLACEHOLDER1", notebook) + @test !occursin("PLACEHOLDER2", notebook) + @test !occursin("PLACEHOLDER3", notebook) + @test !occursin("PLACEHOLDER4", notebook) + @test occursin("1REDLOHECALP", notebook) + @test occursin("2REDLOHECALP", notebook) + @test occursin("3REDLOHECALP", notebook) + @test occursin("4REDLOHECALP", notebook) + + # documenter = false (deprecated) + @test_deprecated r"The documenter=false keyword to Literate.notebook is deprecated." begin + Literate.notebook( + inputfile, + outdir, + documenter = false, + execute = false, + ) + end + notebook = read(joinpath(outdir, "inputfile.ipynb"), String) + @test !occursin("# [Example](@id example-id", notebook) + @test !occursin("[foo](@ref), [bar](@ref bbaarr)", notebook) + + # name + Literate.notebook(inputfile, outdir, name = "foobar", execute = false) + notebook = read(joinpath(outdir, "foobar.ipynb"), String) + @test occursin("name: foobar", notebook) + @test !occursin("name: inputfile", notebook) + @test !occursin("name: @__NAME__", notebook) + + # execute = true + Literate.notebook(inputfile, outdir) + expected_outputs = + rstrip.(( + """ + "cells": [ + """, + """ + "data": { + "text/plain": "3" + }, + """, + """ + "text": [ + "12345678910" + ] + """, + )) + + notebook = read(joinpath(outdir, "inputfile.ipynb"), String) + + lastidx = 1 + for out in expected_outputs + idx = findnext(out, notebook, lastidx) + @test idx !== nothing + lastidx = nextind(notebook, last(idx)) end - return nb - end - Literate.notebook(inputfile, outdir, execute = false, - preprocess = x -> replace(replace(x, "PLACEHOLDER1" => "1REDLOHECALP"), "PLACEHOLDER3" => "3REDLOHECALP"), - postprocess = post) - notebook = read(joinpath(outdir, "inputfile.ipynb"), String) - @test !occursin("PLACEHOLDER1", notebook) - @test !occursin("PLACEHOLDER2", notebook) - @test !occursin("PLACEHOLDER3", notebook) - @test !occursin("PLACEHOLDER4", notebook) - @test occursin("1REDLOHECALP", notebook) - @test occursin("2REDLOHECALP", notebook) - @test occursin("3REDLOHECALP", notebook) - @test occursin("4REDLOHECALP", notebook) - - # documenter = false (deprecated) - @test_deprecated r"The documenter=false keyword to Literate.notebook is deprecated." begin - Literate.notebook(inputfile, outdir, documenter = false, execute = false) - end - notebook = read(joinpath(outdir, "inputfile.ipynb"), String) - @test !occursin("# [Example](@id example-id", notebook) - @test !occursin("[foo](@ref), [bar](@ref bbaarr)", notebook) - - # name - Literate.notebook(inputfile, outdir, name = "foobar", execute = false) - notebook = read(joinpath(outdir, "foobar.ipynb"), String) - @test occursin("name: foobar", notebook) - @test !occursin("name: inputfile", notebook) - @test !occursin("name: @__NAME__", notebook) - - # execute = true - Literate.notebook(inputfile, outdir) - expected_outputs = rstrip.(( - """ - "cells": [ - """, - - """ - "data": { - "text/plain": "3" - }, - """, - - """ - "text": [ - "12345678910" - ] - """)) - - notebook = read(joinpath(outdir, "inputfile.ipynb"), String) - - lastidx = 1 - for out in expected_outputs - idx = findnext(out, notebook, lastidx) - @test idx !== nothing - lastidx = nextind(notebook, last(idx)) - end - # issue #31 - write(inputfile, "include(\"issue31.jl\")") - write(joinpath(outdir, "issue31.jl"), "10 + 21") - Literate.notebook(inputfile, outdir) - notebook = read(joinpath(outdir, "inputfile.ipynb"), String) - @test occursin("\"data\": {\n \"text/plain\": \"31\"\n }", notebook) - - # test error when executing notebook - write(inputfile, "for i in 1:10\n println(i)") - r = @test_logs((:error, r"error when executing notebook based on input file: "), match_mode=:any, - try - Literate.notebook(inputfile, outdir) - catch err - err - end) - @test isa(r, ErrorException) - @test occursin("when executing the following code block from inputfile ", r.msg) - @test occursin(inputfile, r.msg) - - # verify that inputfile exists - @test_throws ArgumentError Literate.notebook("nonexistent.jl", outdir) - - # default output directory - @test !isfile("inputfile.ipynb") - Literate.notebook(inputfile; execute=false) - @test isfile("inputfile.ipynb") - - # world time problem with `IJulia.display_dict` - write(inputfile, """ - struct VegaLiteRenderable end - Base.show(io::IO, ::MIME"application/vnd.vegalite.v2+json", ::VegaLiteRenderable) = - write(io, \"\"\" - {"encoding":{"x":{"field":"x","type":"quantitative"},"y":{"field":"y","type":"quantitative"}},"data":{"values":[{"x":1,"y":1},{"x":2,"y":3},{"x":3,"y":2}]},"mark":"point"} - \"\"\") - Base.Multimedia.istextmime(::MIME{Symbol("application/vnd.vegalite.v2+json")}) = true - VegaLiteRenderable() - """) - Literate.notebook(inputfile, outdir) - notebook = read(joinpath(outdir, "inputfile.ipynb"), String) - @test occursin("\"application/vnd.vegalite.v2+json\":", notebook) - - - # Capturing output of more exotic types when executing a notebook - script = """ - using DisplayAs - struct X end - Base.show(io::IO, ::MIME"text/plain", ::X) = print(io, "X as text/plain") - Base.show(io::IO, ::MIME"image/svg+xml", ::X) = print(io, "X as image/svg+xml") - Base.show(io::IO, ::MIME"image/png", ::X) = print(io, "X as image/png") - Base.show(io::IO, ::MIME"image/jpeg", ::X) = print(io, "X as image/jpeg") - Base.show(io::IO, ::MIME"text/markdown", ::X) = print(io, "X as text/markdown") - Base.show(io::IO, ::MIME"text/html", ::X) = print(io, "X as text/html") - Base.show(io::IO, ::MIME"text/latex", ::X) = print(io, "X as text/latex") - Base.show(io::IO, ::MIME"application/x-latex", ::X) = print(io, "X as application/x-latex") - Base.show(io::IO, ::MIME"application/vnd.vegalite.v2+json", ::X) = print(io, "{\\"X\\": \\"as application/vnd.vegalite.v2+json\\"}") - - # DisplayAs does not define the following - Base.show(io::IO, ::MIME"application/x-latex", s::DisplayAs.Showable{>:MIME"application/x-latex"}) = - show(io, MIME"application/x-latex"(), s.content) - Base.show(io::IO, ::MIME"application/vnd.vegalite.v2+json", s::DisplayAs.Showable{>:MIME"application/vnd.vegalite.v2+json"}) = - show(io, MIME"application/vnd.vegalite.v2+json"(), s.content) - xs = [] - for mime in [ - MIME"text/plain", - MIME"image/svg+xml", - MIME"image/png", - MIME"image/jpeg", - MIME"text/markdown", - MIME"text/html", - MIME"text/latex", - MIME"application/x-latex", - MIME"application/vnd.vegalite.v2+json" - ] - x = X() |> DisplayAs.Showable{mime} |> DisplayAs.Text - push!(xs, x) + # issue #31 + write(inputfile, "include(\"issue31.jl\")") + write(joinpath(outdir, "issue31.jl"), "10 + 21") + Literate.notebook(inputfile, outdir) + notebook = read(joinpath(outdir, "inputfile.ipynb"), String) + @test occursin( + "\"data\": {\n \"text/plain\": \"31\"\n }", + notebook, + ) + + # test error when executing notebook + write(inputfile, "for i in 1:10\n println(i)") + r = @test_logs( + (:error, r"error when executing notebook based on input file: "), + match_mode = :any, + try + Literate.notebook(inputfile, outdir) + catch err + err + end + ) + @test isa(r, ErrorException) + @test occursin( + "when executing the following code block from inputfile ", + r.msg, + ) + @test occursin(inputfile, r.msg) + + # verify that inputfile exists + @test_throws ArgumentError Literate.notebook("nonexistent.jl", outdir) + + # default output directory + @test !isfile("inputfile.ipynb") + Literate.notebook(inputfile; execute = false) + @test isfile("inputfile.ipynb") + + # world time problem with `IJulia.display_dict` + write( + inputfile, + """ + struct VegaLiteRenderable end + Base.show(io::IO, ::MIME"application/vnd.vegalite.v2+json", ::VegaLiteRenderable) = + write(io, \"\"\" + {"encoding":{"x":{"field":"x","type":"quantitative"},"y":{"field":"y","type":"quantitative"}},"data":{"values":[{"x":1,"y":1},{"x":2,"y":3},{"x":3,"y":2}]},"mark":"point"} + \"\"\") + Base.Multimedia.istextmime(::MIME{Symbol("application/vnd.vegalite.v2+json")}) = true + VegaLiteRenderable() + """, + ) + Literate.notebook(inputfile, outdir) + notebook = read(joinpath(outdir, "inputfile.ipynb"), String) + @test occursin("\"application/vnd.vegalite.v2+json\":", notebook) + + + # Capturing output of more exotic types when executing a notebook + script = """ + using DisplayAs + struct X end + Base.show(io::IO, ::MIME"text/plain", ::X) = print(io, "X as text/plain") + Base.show(io::IO, ::MIME"image/svg+xml", ::X) = print(io, "X as image/svg+xml") + Base.show(io::IO, ::MIME"image/png", ::X) = print(io, "X as image/png") + Base.show(io::IO, ::MIME"image/jpeg", ::X) = print(io, "X as image/jpeg") + Base.show(io::IO, ::MIME"text/markdown", ::X) = print(io, "X as text/markdown") + Base.show(io::IO, ::MIME"text/html", ::X) = print(io, "X as text/html") + Base.show(io::IO, ::MIME"text/latex", ::X) = print(io, "X as text/latex") + Base.show(io::IO, ::MIME"application/x-latex", ::X) = print(io, "X as application/x-latex") + Base.show(io::IO, ::MIME"application/vnd.vegalite.v2+json", ::X) = print(io, "{\\"X\\": \\"as application/vnd.vegalite.v2+json\\"}") + + # DisplayAs does not define the following + Base.show(io::IO, ::MIME"application/x-latex", s::DisplayAs.Showable{>:MIME"application/x-latex"}) = + show(io, MIME"application/x-latex"(), s.content) + Base.show(io::IO, ::MIME"application/vnd.vegalite.v2+json", s::DisplayAs.Showable{>:MIME"application/vnd.vegalite.v2+json"}) = + show(io, MIME"application/vnd.vegalite.v2+json"(), s.content) + xs = [] + for mime in [ + MIME"text/plain", + MIME"image/svg+xml", + MIME"image/png", + MIME"image/jpeg", + MIME"text/markdown", + MIME"text/html", + MIME"text/latex", + MIME"application/x-latex", + MIME"application/vnd.vegalite.v2+json" + ] + x = X() |> DisplayAs.Showable{mime} |> DisplayAs.Text + push!(xs, x) + end + """ + for i = 1:9 + script *= "\n#-\nxs[$i]" end + write(inputfile, script) + Literate.notebook(inputfile, outdir) + + # Calls to display(x) and display(mime, x) + script = """ + struct DF x end + Base.show(io::IO, ::MIME"text/plain", df::DF) = print(io, "DF(\$(df.x)) as text/plain") + Base.show(io::IO, ::MIME"text/html", df::DF) = print(io, "DF(\$(df.x)) as text/html") + Base.show(io::IO, ::MIME"text/latex", df::DF) = print(io, "DF(\$(df.x)) as text/latex") + #- + foreach(display, [DF(1), DF(2)]) + DF(3) + #- + display(MIME("text/latex"), DF(4)) """ - for i in 1:9 - script *= "\n#-\nxs[$i]" - end - write(inputfile, script) - Literate.notebook(inputfile, outdir) - - # Calls to display(x) and display(mime, x) - script = """ - struct DF x end - Base.show(io::IO, ::MIME"text/plain", df::DF) = print(io, "DF(\$(df.x)) as text/plain") - Base.show(io::IO, ::MIME"text/html", df::DF) = print(io, "DF(\$(df.x)) as text/html") - Base.show(io::IO, ::MIME"text/latex", df::DF) = print(io, "DF(\$(df.x)) as text/latex") - #- - foreach(display, [DF(1), DF(2)]) - DF(3) - #- - display(MIME("text/latex"), DF(4)) - """ - write(inputfile, script) - Literate.notebook(inputfile, outdir) - json = JSON.parsefile(joinpath(outdir, "inputfile.ipynb")) - cells = json["cells"] - @test length(cells) == 4 - # Cell 2 has 3 outputs: 2 display and one execute result - cellout = cells[2]["outputs"] - @test length(cellout) == 3 - for i in 1:3 - exe_res = i == 3 - @test cellout[i]["output_type"] == (exe_res ? "execute_result" : "display_data") - @test keys(cellout[i]["data"]) == Set(("text/plain", "text/html")) - @test cellout[i]["data"]["text/plain"] == "DF($i) as text/plain" - @test cellout[i]["data"]["text/html"] == Any["DF($i) as text/html"] - @test haskey(cellout[i], "execution_count") == exe_res + write(inputfile, script) + Literate.notebook(inputfile, outdir) + json = JSON.parsefile(joinpath(outdir, "inputfile.ipynb")) + cells = json["cells"] + @test length(cells) == 4 + # Cell 2 has 3 outputs: 2 display and one execute result + cellout = cells[2]["outputs"] + @test length(cellout) == 3 + for i = 1:3 + exe_res = i == 3 + @test cellout[i]["output_type"] == + (exe_res ? "execute_result" : "display_data") + @test keys(cellout[i]["data"]) == Set(("text/plain", "text/html")) + @test cellout[i]["data"]["text/plain"] == "DF($i) as text/plain" + @test cellout[i]["data"]["text/html"] == Any["DF($i) as text/html"] + @test haskey(cellout[i], "execution_count") == exe_res + end + # Cell 3 has one output from a single display call + cellout = cells[3]["outputs"] + @test length(cellout) == 1 + @test cellout[1]["output_type"] == "display_data" + @test keys(cellout[1]["data"]) == Set(("text/latex",)) + @test cellout[1]["data"]["text/latex"] == "DF(4) as text/latex" + @test !haskey(cellout[1], "execution_count") end - # Cell 3 has one output from a single display call - cellout = cells[3]["outputs"] - @test length(cellout) == 1 - @test cellout[1]["output_type"] == "display_data" - @test keys(cellout[1]["data"]) == Set(("text/latex",)) - @test cellout[1]["data"]["text/latex"] == "DF(4) as text/latex" - @test !haskey(cellout[1], "execution_count") end end -end end - -@testset "Configuration" begin; Base.CoreLogging.with_logger(Base.CoreLogging.NullLogger()) do - mktempdir(@__DIR__) do sandbox - cd(sandbox) do - # write content to inputfile - inputfile = "inputfile.jl" - write(inputfile, content) - outdir = mktempdir(pwd()) - - config=Dict( - "repo_root_url" => "www.example1.com", - "nbviewer_root_url" => "www.example2.com", - "binder_root_url" => "www.example3.com", - ) - - # Overwriting of URLs - withenv("TRAVIS_REPO_SLUG" => "fredrikekre/Literate.jl", +end + +@testset "Configuration" begin + Base.CoreLogging.with_logger(Base.CoreLogging.NullLogger()) do + mktempdir(@__DIR__) do sandbox + cd(sandbox) do + # write content to inputfile + inputfile = "inputfile.jl" + write(inputfile, content) + outdir = mktempdir(pwd()) + + config = Dict( + "repo_root_url" => "www.example1.com", + "nbviewer_root_url" => "www.example2.com", + "binder_root_url" => "www.example3.com", + ) + + # Overwriting of URLs + withenv( + "TRAVIS_REPO_SLUG" => "fredrikekre/Literate.jl", "TRAVIS_TAG" => "", "TRAVIS_PULL_REQUEST" => "false", - "HAS_JOSH_K_SEAL_OF_APPROVAL" => "true") do - Literate.script(inputfile, outdir; config=config) - end - script = read(joinpath(outdir, "inputfile.jl"), String) - @test occursin("Link to repo root: www.example1.com/file.jl", script) - @test occursin("Link to nbviewer: www.example2.com/file.jl", script) - @test occursin("Link to binder: www.example3.com/file.jl", script) - - # Test pick_codefence function - default_codefence=pick_codefence(Literate.DefaultFlavor(),true,"testname") - @test default_codefence == ("````julia" => "````") - @test default_codefence == pick_codefence(Literate.FranklinFlavor(),true,"testname") - @test default_codefence == pick_codefence(Literate.DocumenterFlavor(),true,"testname") - documenter_codefence = ("````@example testname" => "````") - @test documenter_codefence == pick_codefence(Literate.DocumenterFlavor(),false,"testname") - let expected_exception=ErrorException("QuartoFlavor does not support argument execute=true!") - @test_throws expected_exception pick_codefence(Literate.QuartoFlavor(),true,"testname") + "HAS_JOSH_K_SEAL_OF_APPROVAL" => "true", + ) do + Literate.script(inputfile, outdir; config = config) + end + script = read(joinpath(outdir, "inputfile.jl"), String) + @test occursin("Link to repo root: www.example1.com/file.jl", script) + @test occursin("Link to nbviewer: www.example2.com/file.jl", script) + @test occursin("Link to binder: www.example3.com/file.jl", script) + + # Test pick_codefence function + default_codefence = + pick_codefence(Literate.DefaultFlavor(), true, "testname") + @test default_codefence == ("````julia" => "````") + @test default_codefence == + pick_codefence(Literate.FranklinFlavor(), true, "testname") + @test default_codefence == + pick_codefence(Literate.DocumenterFlavor(), true, "testname") + documenter_codefence = ("````@example testname" => "````") + @test documenter_codefence == + pick_codefence(Literate.DocumenterFlavor(), false, "testname") + let expected_exception = ErrorException( + "QuartoFlavor does not support argument execute=true!", + ) + @test_throws expected_exception pick_codefence( + Literate.QuartoFlavor(), + true, + "testname", + ) + end + @test ("```{julia}" => "```") == + pick_codefence(Literate.QuartoFlavor(), false, "testname") + + # Misc default configs + create(; type, kw...) = Literate.create_configuration( + inputfile; + user_config = Dict(), + user_kwargs = kw, + type = type, + ) + cfg = create(; type = :md, execute = true) + @test cfg["execute"] + @test cfg["codefence"] == ("````julia" => "````") + cfg = create(; type = :md, execute = false) + @test !cfg["execute"] + @test cfg["codefence"] == ("````@example inputfile" => "````") end - @test ("```{julia}" => "```") == pick_codefence(Literate.QuartoFlavor(),false,"testname") - - # Misc default configs - create(; type, kw...) = Literate.create_configuration(inputfile; user_config=Dict(), user_kwargs=kw, type=type) - cfg = create(; type=:md, execute=true) - @test cfg["execute"] - @test cfg["codefence"] == ("````julia" => "````") - cfg = create(; type=:md, execute=false) - @test !cfg["execute"] - @test cfg["codefence"] == ("````@example inputfile" => "````") end end -end end +end