diff --git a/docs/src/fileformat.md b/docs/src/fileformat.md index 6f45cae..efb5562 100644 --- a/docs/src/fileformat.md +++ b/docs/src/fileformat.md @@ -45,7 +45,7 @@ For simple use this is all you need to know. The following additional special sy There is also some default convenience replacements that will always be performed, see [Default replacements](@ref). -### Multiline comments +### Multiline comments and markdown strings Literate version 2.7 adds support for Julia multiline comments for markdown input. All multiline comments in the input are rewritten to regular comments as part of the @@ -71,6 +71,22 @@ is rewritten to # This is also markdown. ``` +Similarly, Literate version 2.9 adds support for using literal markdown strings, +`md""" ... """`, for the markdown sections, for example + +```julia +md""" +# Title +blah blah blah +""" +``` +is rewritten to +```julia +# # Title +# blah blah blah +``` +This is not enabled by default -- it requires passing `mdstrings=true`. +`Literate.markdown`/`Literate.notebook`/`Literate.script`. ## [**2.2.** Filtering lines](@id Filtering-lines) @@ -104,7 +120,7 @@ is a case where we can prepend `#md` to those lines: #md # ```@docs #md # Literate.markdown #md # Literate.notebook -#md # Literate.markdown +#md # Literate.script #md # ``` ```` The lines in the example above would be filtered out in the preprocessing step, unless we are diff --git a/src/Literate.jl b/src/Literate.jl index 3d74a6b..496f5cb 100644 --- a/src/Literate.jl +++ b/src/Literate.jl @@ -150,15 +150,23 @@ function replace_default(content, sym; push!(repls, "\r\n" => "\n") # normalize line endings - # unconditionally rewrite multiline comments to regular comments - multiline_r = r"^#=+$\R^(\X*?)\R^=+#$"m - while (m = match(multiline_r, content); m !== nothing) - newlines = sprint() do io - foreach(l -> println(io, "# ", l), eachline(IOBuffer(m[1]))) + # unconditionally rewrite multiline comments and + # conditionally multiline markdown strings to regular comments + function replace_multiline(multiline_r, str) + while (m = match(multiline_r, str); m !== nothing) + newlines = sprint() do io + foreach(l -> println(io, "# ", l), eachline(IOBuffer(m[1]))) + end + str = replace(str, multiline_r => chop(newlines); count=1) end - content = replace(content, multiline_r => chop(newlines); count=1) + return str + end + content = replace_multiline(r"^#=+$\R^(\X*?)\R^=+#$"m, content) + if config["mdstrings"]::Bool + content = replace_multiline(r"^md\"\"\"$\R^(\X*?)\R^\"\"\"$"m, content) end + # unconditionally remove #src lines push!(repls, r"^#src.*\n?"m => "") # remove leading #src lines push!(repls, r".*#src$\n?"m => "") # remove trailing #src lines @@ -245,6 +253,7 @@ function create_configuration(inputfile; user_config, user_kwargs, type=nothing) cfg["postprocess"] = identity cfg["flavor"] = type === (:md) ? DocumenterFlavor() : DefaultFlavor() cfg["credit"] = true + cfg["mdstrings"] = false cfg["keep_comments"] = false cfg["execute"] = type === :md ? false : true cfg["codefence"] = get(user_config, "flavor", cfg["flavor"]) isa DocumenterFlavor && @@ -439,7 +448,7 @@ function script(inputfile, outputdir=pwd(); config::Dict=Dict(), kwargs...) write(ioscript, '\n') # add a newline between each chunk elseif isa(chunk, MDChunk) && config["keep_comments"]::Bool for line in chunk.lines - write(ioscript, rstrip(line.first * "# " * line.second * '\n')) + write(ioscript, rstrip(line.first * "# " * line.second) * '\n') end write(ioscript, '\n') # add a newline between each chunk end diff --git a/test/runtests.jl b/test/runtests.jl index 51fdb66..79d74c3 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -436,6 +436,58 @@ const GITLAB_ENV = Dict( @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) @@ -705,6 +757,11 @@ end end @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) + # execute write(inputfile, """ using DisplayAs