diff --git a/Project.toml b/Project.toml index 7fba92c2d..802502f84 100644 --- a/Project.toml +++ b/Project.toml @@ -10,12 +10,11 @@ Highlights = "eafb193a-b7ab-5a9e-9068-77385905fa72" JuDocTemplates = "6793090a-55ae-11e9-0511-73b91164f4ea" LiveServer = "16fef848-5104-11e9-1b77-fb7a48bbb589" Markdown = "d6f4376e-aef5-505a-96c1-9c027394607a" -Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" [compat] -DocStringExtensions = "^0.7.0" -Highlights = "^0.3.0" +DocStringExtensions = ">= 0.7.0" +Highlights = ">= 0.3.0" JuDocTemplates = ">= 0.1.0" -LiveServer = "^0.1.0" +LiveServer = ">= 0.1.0" julia = "^1.0.0" diff --git a/src/JuDoc.jl b/src/JuDoc.jl index 427ffd488..99a1235cc 100644 --- a/src/JuDoc.jl +++ b/src/JuDoc.jl @@ -4,7 +4,6 @@ using JuDocTemplates using Markdown using Dates # see jd_vars -using Random using Highlights import LiveServer @@ -12,7 +11,6 @@ import LiveServer using DocStringExtensions: SIGNATURES, TYPEDEF const BIG_INT = typemax(Int) -const JD_LEN_RANDSTRING = 4 # make this longer if you think you'll collide... const JD_SERVE_FIRSTCALL = Ref(true) const JD_DEBUG = Ref(false) diff --git a/src/converter/lx.jl b/src/converter/lx.jl index 1ca9ac32e..5fb43a87a 100644 --- a/src/converter/lx.jl +++ b/src/converter/lx.jl @@ -57,7 +57,7 @@ JD_LOC_EQDICT_COUNTER Counter to keep track of equation numbers as they appear along the page, this helps with equation referencing. """ -const JD_LOC_EQDICT_COUNTER = "COUNTER_" * randstring(JD_LEN_RANDSTRING) +const JD_LOC_EQDICT_COUNTER = "COUNTER_XC0q" """ $(SIGNATURES) diff --git a/src/converter/md_blocks.jl b/src/converter/md_blocks.jl index 526085d09..3753dbba6 100644 --- a/src/converter/md_blocks.jl +++ b/src/converter/md_blocks.jl @@ -74,9 +74,9 @@ function convert_mathblock(β::OCBlock, lxdefs::Vector{LxDef})::String # check if there's a label, if there is, add that to the dictionary matched = match(r"\\label{(.*?)}", inner) - + if !isnothing(matched) - name = refstring(strip(matched.captures[1])) + name = refstring(matched.captures[1]) write(htmls, "") inner = replace(inner, r"\\label{.*?}" => "") # store the label name and associated number diff --git a/src/converter/md_utils.jl b/src/converter/md_utils.jl index bf395585e..14a09ee32 100644 --- a/src/converter/md_utils.jl +++ b/src/converter/md_utils.jl @@ -9,8 +9,8 @@ processor, this is relevant for things that are parsed within latex commands etc function md2html(ss::AbstractString, stripp::Bool=false)::AbstractString isempty(ss) && return ss - # Use the base Markdown -> Html converter - partial = Markdown.html(Markdown.parse(ss)) + # Use the base Markdown -> Html converter and post process headers + partial = ss |> Markdown.parse |> Markdown.html |> make_header_refs # In some cases, base converter adds

...

\n which we might not want stripp || return partial @@ -47,3 +47,26 @@ function deactivate_divs(blocks::Vector{OCBlock})::Vector{OCBlock} end return blocks[active_blocks] end + + +""" +$(SIGNATURES) + +By default the Base Markdown to HTML converter simply converts `## ...` into headers but not +linkable ones; this is annoying for generation of table of contents etc (and references in +general) so this function does just that. +""" +function make_header_refs(h::String)::String + io = IOBuffer() + head = 1 + for m ∈ eachmatch(r"(.*?)", h) + write(io, subs(h, head:m.offset-1)) + level = m.captures[1] + name = m.captures[2] + ref = refstring(name) + write(io, "$name") + head = m.offset + lastindex(m.match) + end + write(io, subs(h, head:lastindex(h))) + return String(take!(io)) +end diff --git a/src/misc_utils.jl b/src/misc_utils.jl index a9b4cc30b..74cb9c370 100644 --- a/src/misc_utils.jl +++ b/src/misc_utils.jl @@ -123,8 +123,15 @@ mathenv(s::AbstractString)::String = "_\$>_$(s)_\$<_" """ $(SIGNATURES) -Creates a random string pegged to `s` that we can use for hyper-references. We could just use the -hash but it's quite long, here the length of the output is controlled by `JD_LEN_RANDSTRING` which -is set to 4 by default. -""" -refstring(s::AbstractString)::String = randstring(MersenneTwister(hash(s)), JD_LEN_RANDSTRING) +Takes a string `s` and replace spaces by underscores so that that we can use it +for hyper-references. So for instance `"aa bb"` will become `aa-bb`. +It also defensively removes any non-word character so for instance `"aa bb !"` will be `"aa-bb"` +""" +function refstring(s::AbstractString)::String + # remove non-word characters + st = replace(s, r"&#[0-9]+;" => "") + st = replace(st, r"[^a-zA-Z0-9_\-\s]" => "") + st = replace(lowercase(strip(st)), r"\s+" => "-") + isempty(st) && return string(hash(s)) + return st +end diff --git a/test/converter/markdown.jl b/test/converter/markdown.jl index 4d7ba7f34..752ff4064 100644 --- a/test/converter/markdown.jl +++ b/test/converter/markdown.jl @@ -111,3 +111,18 @@ end hstring = J.convert_inter_html(inter_html, blocks2insert, lxcontext) @test hstring == "

text A1 text A2 blah and \nescape B1\n text C1 \\(\\mathrm{ b}\\) text C2 then part1: AA and part2: BB.

\n" end + + +@testset "headers" begin + st = """ + # Title + and then + ## Subtitle cool! + done + """ + h = st |> Markdown.parse |> Markdown.html + r = J.make_header_refs(h) + @test occursin("

Title

", r) + @test occursin("

Subtitle cool!

", r) + @test occursin("

done

", r) +end diff --git a/test/misc.jl b/test/misc.jl index ef5856882..d1eb2a263 100644 --- a/test/misc.jl +++ b/test/misc.jl @@ -74,3 +74,14 @@ end m = match(r"\[done\s*(.*?)ms\]", r) @test parse(Float64, m.captures[1]) ≥ 500 end + + +@testset "refstring" begin + @test J.refstring("aa bb") == "aa-bb" + @test J.refstring("aa bb !") == "aa-bb" + @test J.refstring("aa-bb-!") == "aa-bb-" + @test J.refstring("aa 🔺 bb") == "aa-bb" + @test J.refstring("aaa 0 bb s:2 df") == "aaa-0-bb-s2-df" + @test J.refstring("🔺🔺") == string(hash("🔺🔺")) + @test J.refstring("blah!") == "blah" +end diff --git a/test/runtests.jl b/test/runtests.jl index 07d4cae8b..5eaab2c79 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,4 +1,4 @@ -using JuDoc, Random, Test +using JuDoc, Test, Markdown const J = JuDoc const D = joinpath(dirname(dirname(pathof(JuDoc))), "test", "_dummies")