Repository: tlienart/JuDoc.jl
Pull request #194 (2019-08-06 09:28:54)

Fr193
* adds `\textinput{...}` command



Patch:
diff --git a/LICENSE.md b/LICENSE.md
index e96b2a51..0a07d02c 100644
--- a/LICENSE.md
+++ b/LICENSE.md
@@ -1,6 +1,6 @@
 The JuDoc.jl package is licensed under the MIT "Expat" License:
 
-> Copyright (c) 2018: Thibaut Lienart.
+> Copyright (c) 2018-2019: Thibaut Lienart.
 >
 > Permission is hereby granted, free of charge, to any person obtaining a copy
 > of this software and associated documentation files (the "Software"), to deal
diff --git a/Project.toml b/Project.toml
index 0a7e93c4..23735177 100644
--- a/Project.toml
+++ b/Project.toml
@@ -10,10 +10,17 @@ JuDocTemplates = "6793090a-55ae-11e9-0511-73b91164f4ea"
 LiveServer = "16fef848-5104-11e9-1b77-fb7a48bbb589"
 Markdown = "d6f4376e-aef5-505a-96c1-9c027394607a"
 Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
-Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
 
 [compat]
 DocStringExtensions = ">= 0.7.0"
 JuDocTemplates = ">= 0.1.0"
 LiveServer = ">= 0.3.0"
 julia = "^1.0.0"
+
+[extras]
+LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
+Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
+Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
+
+[targets]
+test = ["Test", "Random", "LinearAlgebra"]
diff --git a/docs/src/man/syntax.md b/docs/src/man/syntax.md
index 274627ba..b0c0fa34 100644
--- a/docs/src/man/syntax.md
+++ b/docs/src/man/syntax.md
@@ -30,6 +30,9 @@ Most of what is presented here is also shown in that example.
     * [Plot output](#Plot-output-1)
     * [Slicing up](#Slicing-up-1)
 * [File insertions](#File-insertions-1)
+    * [Inserting a figure](#Inserting-a-figure-1)
+    * [Linking a file](#Linking-a-file-1)
+    * [Inserting markdown](#Inserting-markdown-1)
 * [Page variables](#Page-variables-1)
   * [Local page variables](#Local-page-variables-1)
     * [Default variables](#Default-variables-1)
@@ -652,6 +655,32 @@ The command
 is a convenient way to link to a local asset (e.g. a pdf file).
 Again, you could use the default markdown way `[name](full_path)` but, as for the fig commands, this allows the use of relative paths.
 
+### Inserting markdown
+
+In some situation, you may have some markdown in a file which you may want to include somewhere else.
+This can be achieved thanks to the  `\textoutput{path}` commmand.
+The path specification is as the other commands, and the text will be formatted.
+
+As an example you could have in `/assets/ccc/sidefile.md`:
+
+```judoc
+some **markdown** in a side file.
+```
+
+where in `/src/index.md`:
+
+```judoc
+This is the index then \textinput{ccc/sidefile}
+```
+
+and this will be equivalent to just having in `/src/index.md`:
+
+```judoc
+This is the index then some **markdown** in a side file.
+```
+
+**Note**: if you don't specify a file extension, `.md` is appended to the specified path.
+
 ## Page variables
 
 Page variables are a way to interact with the HTML templating.
diff --git a/src/converter/lx.jl b/src/converter/lx.jl
index 608e73b1..0fbcf18a 100644
--- a/src/converter/lx.jl
+++ b/src/converter/lx.jl
@@ -262,7 +262,23 @@ function resolve_lx_input_plainoutput(rpath::AbstractString, reproc::Bool=false)
     isfile(out_file) || throw(ErrorException("I found an \\input but no relevant output file."))
     # return the content in a pre block
     reproc || return html_code(read(out_file, String))
-    return read(out_file, String)
+    return read(out_file, String) * EOS
+end
+
+
+"""
+$(SIGNATURES)
+
+Internal function to read a file at a specified path and just plug it in. (Corresponds to what a
+simple `\\input` command does in LaTeX).
+See also [`resolve_lx_textinput`](@ref).
+"""
+function resolve_lx_input_textfile(rpath::AbstractString)::String
+    # find the full system path to the asset
+    fpath = resolve_assets_rpath(rpath; canonical=true)
+    isempty(splitext(fpath)[2]) && (fpath *= ".md")
+    isfile(fpath) || throw(ErrorException("I found a \\textinput but no relevant file."))
+    return read(fpath, String) * EOS
 end
 
 
@@ -351,8 +367,6 @@ function resolve_lx_input(lxc::LxCom)::String
             return resolve_lx_input_plainoutput(rpath)
         elseif qualifier == "plot"
             return resolve_lx_input_plotoutput(rpath)
-        # elseif qualifier == "table"
-        #     return resolve_lx_input_tableoutput(rpath)
         elseif qualifier ∈ ("julia", "fortran", "julia-repl", "matlab", "r", "toml")
             return resolve_lx_input_hlcode(rpath, qualifier)
         else # assume it's another language descriptor, let the user do that with highlights.js
diff --git a/src/converter/lx_simple.jl b/src/converter/lx_simple.jl
index 000f0501..7727eeaa 100644
--- a/src/converter/lx_simple.jl
+++ b/src/converter/lx_simple.jl
@@ -3,7 +3,7 @@
 """
 $SIGNATURES
 
-Internal function to resolve a `\\output{rpath}` (finds the output and shows it in a pre block).
+Internal function to resolve a `\\output{rpath}` (finds the output and shows it).
 The `reprocess` argument indicates whether the output should be processed as judoc markdown or
 inserted as is.
 """
@@ -22,6 +22,17 @@ Note: the output is re-processed (if there's any markdown in the output, it will
 resolve_lx_textoutput(lxc::LxCom) = resolve_lx_output(lxc, true)
 
 
+"""
+$SIGNATURES
+
+Internal function to resolve a `\\textinput{rpath}` (reads the file and show it after processing).
+"""
+function resolve_lx_textinput(lxc::LxCom, reprocess::Bool=false)::String
+    rpath = strip(content(lxc.braces[1]))
+    return resolve_lx_input_textfile(rpath)
+end
+
+
 """
 $SIGNATURES
 
@@ -93,4 +104,5 @@ Same as [`LXCOM_SIMPLE`](@ref) except the output is re-processed before being in
 """
 const LXCOM_SIMPLE_REPROCESS = Dict{String, Function}(
     "\\textoutput" => resolve_lx_textoutput, # include output generated by code and reproc
+    "\\textinput"  => resolve_lx_textinput,
     )
diff --git a/src/jd_vars.jl b/src/jd_vars.jl
index 7483d0cc..512b2121 100644
--- a/src/jd_vars.jl
+++ b/src/jd_vars.jl
@@ -112,6 +112,7 @@ the site. See [`resolve_lxcom`](@ref).
     GLOBAL_LXDEFS["\\input"]      = LxDef("\\input",      2, EMPTY_SS)
     GLOBAL_LXDEFS["\\output"]     = LxDef("\\output",     1, EMPTY_SS)
     GLOBAL_LXDEFS["\\textoutput"] = LxDef("\\textoutput", 1, EMPTY_SS)
+    GLOBAL_LXDEFS["\\textinput"]  = LxDef("\\textinput", 1, EMPTY_SS)
     GLOBAL_LXDEFS["\\figalt"]     = LxDef("\\figalt",     2, EMPTY_SS)
     GLOBAL_LXDEFS["\\fig"]        = LxDef("\\fig",        1, subs("\\figalt{}{#1}"))
     GLOBAL_LXDEFS["\\file"]       = LxDef("\\file",       2, subs("[#1]()"))
diff --git a/src/manager/judoc.jl b/src/manager/judoc.jl
index 8c474357..2ac9637c 100644
--- a/src/manager/judoc.jl
+++ b/src/manager/judoc.jl
@@ -38,8 +38,7 @@ function serve(; clear::Bool=true, verb::Bool=false, port::Int=8000, single::Boo
     start = time()
     sig = jd_fullpass(watched_files; clear=clear, verb=verb, prerender=prerender, isoptim=isoptim)
     sig < 0 && return sig
-    fmsg = rpad("✔ full pass...", 40)
-    verb && (println(""); print(fmsg); print_final(fmsg, start); println(""))
+    verb && (print(rpad("\n✔ full pass...", 40)); time_it_took(start); println(""))
 
     # start the continuous loop
     if !single
@@ -180,19 +179,16 @@ function jd_loop(cycle_counter::Int, ::LiveServer.FileWatcher, watched_files::Na
             cur_t = mtime(fpath)
             cur_t <= t && continue
             # if there was then the file has been modified and should be re-processed + copied
-            fmsg = rpad("→ file $(fpath[length(FOLDER_PATH[])+1:end]) was modified ", 30)
-            verb && print(fmsg)
+            verb && print(rpad("→ file $(fpath[length(FOLDER_PATH[])+1:end]) was modified ", 30))
             dict[fpair] = cur_t
             # if it's an infra_file
             if haskey(watched_files[:infra], fpair)
-                #TODO: couldn't test this branch
                 verb && println("→ full pass...")
                 start = time()
                 jd_fullpass(watched_files; clear=false, verb=false, prerender=false)
-                verb && (print_final(rpad("✔ full pass...", 15), start); println(""))
+                verb && (print(rpad("\n✔ full pass...", 15)); time_it_took(start); println(""))
             else
-                fmsg = fmsg * rpad("→ updating... ", 15)
-                verb && print("\r" * fmsg)
+                verb && print(rpad("→ updating... ", 15))
                 start = time()
                 # TODO, ideally these would only be read if they've changed. Not super important
                 # but just not necessary. (Fixing may be a bit of a pain though)
@@ -200,7 +196,7 @@ function jd_loop(cycle_counter::Int, ::LiveServer.FileWatcher, watched_files::Na
                 pg_foot = read(joinpath(PATHS[:src_html], "page_foot.html"), String)
                 foot    = read(joinpath(PATHS[:src_html], "foot.html"), String)
                 process_file(case, fpair, head, pg_foot, foot, cur_t; clear=false, prerender=false)
-                verb && print_final(fmsg, start)
+                verb && time_it_took(start)
             end
         end
     end
diff --git a/src/manager/post_processing.jl b/src/manager/post_processing.jl
index 14b120a9..84b3141e 100644
--- a/src/manager/post_processing.jl
+++ b/src/manager/post_processing.jl
@@ -31,12 +31,11 @@ function optimize(; prerender::Bool=true, minify::Bool=true, sig::Bool=false,
     end
     # re-do a (silent) full pass
     start = time()
-    fmsg = "\r→ Full pass"
-    print(fmsg)
-    withpre = fmsg * ifelse(prerender, rpad(" (with pre-rendering)", 24), rpad(" (no pre-rendering)", 24))
+    print("→ Full pass")
+    withpre = ifelse(prerender, rpad(" (with pre-rendering)", 24), rpad(" (no pre-rendering)", 24))
     print(withpre)
     succ = (serve(single=true, prerender=prerender, nomess=true, isoptim=true) === nothing)
-    print_final(withpre, start)
+    time_it_took(start)
 
     #
     # Minification
@@ -44,18 +43,17 @@ function optimize(; prerender::Bool=true, minify::Bool=true, sig::Bool=false,
     if minify && succ
         if JD_CAN_MINIFY
             start = time()
-            mmsg = rpad("→ Minifying *.[html|css] files...", 35)
-            print(mmsg)
+            print(rpad("→ Minifying *.[html|css] files...", 35))
             # copy the script to the current dir
             cp(joinpath(dirname(pathof(JuDoc)), "scripts", "minify.py"), JD_PY_MIN_NAME; force=true)
             # run it
             succ = success(`$([e for e in split(PY)]) $JD_PY_MIN_NAME`)
             # remove the script file
             rm(JD_PY_MIN_NAME)
-            print_final(mmsg, start)
+            time_it_took(start)
         else
-            @warn "I didn't find css_html_js_minify, you can install it via pip."*
-                  "The output will not be minified."
+            @warn "I didn't find css_html_js_minify, you can install it via pip the output will "*
+                  "not be minified."
         end
     end
     return ifelse(sig, succ, nothing)
@@ -75,23 +73,21 @@ In other scenarios you should probably do this manually.
 * `prerender=true`: prerender javascript before pushing see [`optimize`](@ref)
 * `minify=true`:    minify output before pushing see [`optimize`](@ref)
 * `nopass=false`:   set this to true if you have already run `optimize` manually.
-* `message="jd-update"`: add commit message.
 """
 function publish(; prerender::Bool=true, minify::Bool=true, nopass::Bool=false,
-                   prepath::String="", message::String="jd-update")::Nothing
+                   prepath::String="")::Nothing
     succ = true
     if !isempty(prepath) || !nopass
         succ = optimize(prerender=prerender, minify=minify, sig=true, prepath=prepath)
     end
     if succ
         start = time()
-        pubmsg = rpad("→ Pushing updates with git...", 35)
-        print(pubmsg)
+        print(rpad("→ Pushing updates with git...", 35))
         try
             run(`git add -A `)
-            run(`git commit -m "$message" --quiet`)
+            run(`git commit -m "jd-update" --quiet`)
             run(`git push --quiet`)
-            print_final(pubmsg, start)
+            time_it_took(start)
         catch e
             println("✘ Could not push updates, verify your connection and try manually.\n")
             @show e
@@ -113,16 +109,14 @@ function cleanpull()::Nothing
     FOLDER_PATH[] = pwd()
     set_paths!()
     if isdir(PATHS[:pub])
-        rmmsg = rpad("→ Removing local output dir...", 35)
-        print(rmmsg)
+        print(rpad("→ Removing local output dir...", 35))
         rm(PATHS[:pub], force=true, recursive=true)
-        println("\r" * rmmsg * " [done ✔ ]")
+        println(" [done ✔ ]")
     end
     try
-        pmsg = rpad("→ Retrieving updates from the repository...", 35)
-        print(pmsg)
+        print(rpad("→ Retrieving updates from the repository...", 35))
         run(`git pull --quiet`)
-        println("\r" * pmsg * " [done ✔ ]")
+        println(" [done ✔ ]")
     catch e
         println("✘ Could not pull updates, verify your connection and try manually.\n")
         @show e
diff --git a/src/misc_utils.jl b/src/misc_utils.jl
index 45ae2b1e..5b13b89a 100644
--- a/src/misc_utils.jl
+++ b/src/misc_utils.jl
@@ -88,22 +88,13 @@ $(SIGNATURES)
 
 Convenience function to display a time since `start`.
 """
-function time_it_took(start::Float64)
+function time_it_took(start::Float64)::Nothing
     comp_time = time() - start
     mess = comp_time > 60 ? "$(round(comp_time/60;   digits=1))m" :
            comp_time >  1 ? "$(round(comp_time;      digits=1))s" :
                             "$(round(comp_time*1000; digits=1))ms"
-    return "[done $(lpad(mess, 6))]"
-end
-
-```
-$(SIGNATURES)
-
-Nicer printing of processes.
-```
-function print_final(startmsg::AbstractString, starttime::Float64)::Nothing
-    tit = time_it_took(starttime)
-    println("\r$startmsg$tit")
+    println("[done $(lpad(mess, 6))]")
+    return nothing
 end
 
 
@@ -176,8 +167,7 @@ joinrp(rpath::AbstractString) = joinpath(split(rpath, '/')...)
 """
 $(SIGNATURES)
 
-Internal function to resolve a relative path. See [`convert_code_blo
-    ck`](@ref) and
+Internal function to resolve a relative path. See [`convert_code_block`](@ref) and
 [`resolve_lx_input`](@ref).
 As an example, let's say you have the path `./blah/blih.txt` somewhere in `src/pages/page1.md`.
 The `./` indicates that the path should be reproduced in `/assets/` and so it will lead to


Test patch:
diff --git a/test/converter/lx_input.jl b/test/converter/lx_input.jl
index 18a1ccac..36696e37 100644
--- a/test/converter/lx_input.jl
+++ b/test/converter/lx_input.jl
@@ -54,3 +54,14 @@ end
     @test occursin("Then maybe <pre><code>$(read(joinpath(J.PATHS[:assets], "output", "s1.out"), String))</code></pre>", h)
     @test occursin("Finally img: <img src=\"/assets/output/s1a.png\" alt=\"\"> done.", h)
 end
+
+@testset  "Input MD" begin
+    mkpath(joinpath(J.PATHS[:assets], "ccc"))
+    fp = joinpath(J.PATHS[:assets], "ccc", "asset1.md")
+    write(fp, "blah **blih**")
+    st = raw"""
+        Some string
+        \textinput{ccc/asset1}
+        """ * J.EOS;
+    @test isapproxstr(st |> conv, "<p>Some string blah <strong>blih</strong></p>")
+end
diff --git a/test/jd_paths_vars.jl b/test/jd_paths_vars.jl
index 05eccdb9..0abda5f4 100644
--- a/test/jd_paths_vars.jl
+++ b/test/jd_paths_vars.jl
@@ -36,7 +36,7 @@ cp(joinpath(dirname(dirname(pathof(JuDoc))), "test", "_libs", "katex"), joinpath
     J.set_vars!(d, ["a"=>"5", "b"=>"nothing"])
 
     @test d["a"].first == 5
-    @test d["b"].first == nothing
+    @test d["b"].first === nothing
 
     @test_logs (:warn, "Doc var 'a' (type(s): (Real,)) can't be set to value 'blah' (type: String). Assignment ignored.") J.set_vars!(d, ["a"=>"\"blah\""])
     @test_logs (:error, "I got an error (of type 'DomainError') trying to evaluate '__tmp__ = sqrt(-1)', fix the assignment.") J.set_vars!(d, ["a"=> "sqrt(-1)"])
diff --git a/test/misc.jl b/test/misc.jl
index f41b6e2c..ce55db3b 100644
--- a/test/misc.jl
+++ b/test/misc.jl
@@ -67,7 +67,7 @@ end
     f = joinpath(d, "a.txt")
     open(f, "w") do outf
         redirect_stdout(outf) do
-            J.print_final("elapsing",start)
+            J.time_it_took(start)
         end
     end
     r = read(f, String)