From 981350053e8faf63937ccc985b38a47d0d4f029e Mon Sep 17 00:00:00 2001 From: Thibaut Lienart Date: Mon, 20 May 2019 14:36:57 +1000 Subject: [PATCH] close 151 --- docs/src/lib/design.md | 4 ++-- src/parser/ocblocks.jl | 37 +++++++++++++++++++++++++++++++++-- src/parser/tokens.jl | 2 +- src/parser/tokens_md.jl | 8 ++++++++ test/_dummies/151.md | 19 ++++++++++++++++++ test/converter/integration.jl | 5 +++++ test/runtests.jl | 1 + 7 files changed, 71 insertions(+), 5 deletions(-) create mode 100644 test/_dummies/151.md diff --git a/docs/src/lib/design.md b/docs/src/lib/design.md index e3892725c..be6d22c1f 100644 --- a/docs/src/lib/design.md +++ b/docs/src/lib/design.md @@ -64,7 +64,7 @@ julia> JuDoc.from(t[1]) julia> ocb, _ = JuDoc.find_all_ocblocks(t, JuDoc.MD_OCB_ALL); julia> ocb 1-element Array{JuDoc.OCBlock,1}: - JuDoc.OCBlock(:MATH_A, JuDoc.Token(:MATH_A, "\$") => JuDoc.Token(:MATH_A, "\$"), "\$x=5\$") + JuDoc.OCBlock(:MATH_A, JuDoc.Token(:MATH_A, "\$") => JuDoc.Token(:MATH_A, "\$"), "\$x=5\$", false) julia> JuDoc.from(ocb[1]) 8 @@ -185,7 +185,7 @@ JuDoc.LxCom( "\\foo{hello}", Base.RefArray{...}(...), JuDoc.OCBlock[JuDoc.OCBlock(:LXB, JuDoc.Token(:LXB_OPEN, "{") => JuDoc.Token(:LXB_CLOSE, "}"), - "{hello}")]) + "{hello}", true)]) ``` diff --git a/src/parser/ocblocks.jl b/src/parser/ocblocks.jl index 8cff16d7b..d20afa1b8 100644 --- a/src/parser/ocblocks.jl +++ b/src/parser/ocblocks.jl @@ -72,11 +72,44 @@ function find_all_ocblocks(tokens::Vector{Token}, inmath=false) where S <: Symbol ocbs_all = Vector{OCBlock}() - for (name, (ocpair, nest)) ∈ ocblist + for (name, (ocpair, nestable)) ∈ ocblist ocbs, tokens = find_ocblocks(tokens, name, ocpair; - nestable=nest, inmath=inmath) + nestable=nestable, inmath=inmath) append!(ocbs_all, ocbs) end + + # it may happen that a block is contained in a larger escape block. + # For instance this can happen if there is a code block in an escape block (see e.g. #151). + # To fix this, we browse the escape blocks in backwards order and check if there is any other + # block within it. + i = length(ocbs_all) + ignore = Int[] + while i > 1 + cur_ocb = ocbs_all[i] + if cur_ocb.name ∈ MD_OCB_ESC + cur_head, cur_tail = from(cur_ocb), to(cur_ocb) + # find the first block before the ith one which has its head after the current head + # this will often be nothing but if it itsn't, then it should be ignored + kf = findfirst(k -> cur_head < from(ocbs_all[k]) < cur_tail, 1:i-1) + if !isnothing(kf) + append!(ignore, kf:i-1) + i = kf - 1 + else + i -= 1 + end + else + i -= 1 + end + end + # for (i,ocbi) ∈ enumerate(ocbs_all) + # @show i + # @show ocbi + # @show from(ocbi) + # @show to(ocbi) + # end + # @show ignore + deleteat!(ocbs_all, ignore) + return ocbs_all, tokens end diff --git a/src/parser/tokens.jl b/src/parser/tokens.jl index 1e0432161..fb1d261fe 100644 --- a/src/parser/tokens.jl +++ b/src/parser/tokens.jl @@ -49,7 +49,7 @@ $(SIGNATURES) Shorthand constructor to instantiate an `OCBlock` inferring the associated substring from the `ocpair` (since it's the substring in between the tokens). """ -OCBlock(η::Symbol, ω::Pair{Token,Token}) = +OCBlock(η::Symbol, ω::Pair{Token,Token}, nestable::Bool=false) = OCBlock(η, ω, subs(str(ω.first), from(ω.first), to(ω.second))) diff --git a/src/parser/tokens_md.jl b/src/parser/tokens_md.jl index cdb33d3bb..3beb7372a 100644 --- a/src/parser/tokens_md.jl +++ b/src/parser/tokens_md.jl @@ -120,6 +120,14 @@ def are allowed. * ordering matters! =# +""" +MD_OCB_ESC + +Blocks that will be escaped (their content will not be further processed). +Corresponds to the non-nestable elements of `MD_OCB`. +""" +const MD_OCB_ESC = [e.first for e ∈ MD_OCB if !e.second[2]] + """ MD_OCB_MATH diff --git a/test/_dummies/151.md b/test/_dummies/151.md new file mode 100644 index 000000000..c74a1c420 --- /dev/null +++ b/test/_dummies/151.md @@ -0,0 +1,19 @@ +aaa +~~~ +

+"""
+    A
+
+B
+
+# C
+```jldoctest
+D
+```
+"""
+function bar(x, y)
+E
+end
+
+~~~ +bbb diff --git a/test/converter/integration.jl b/test/converter/integration.jl index 509777c05..8ad3102ee 100644 --- a/test/converter/integration.jl +++ b/test/converter/integration.jl @@ -150,3 +150,8 @@ end """ * J.EOS st |> conv == "
\n
\n" end + +@testset "HTML escape" begin # see #151 + st = read(joinpath(D, "151.md"), String) + st |> conv == "

aaa \n

\n\"\"\"\n    A\n\nB\n\n# C\n```jldoctest\nD\n```\n\"\"\"\nfunction bar(x, y)\nE\nend\n
\n bbb

\n" +end diff --git a/test/runtests.jl b/test/runtests.jl index 6b53bf0b7..07d4cae8b 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,5 +1,6 @@ using JuDoc, Random, Test const J = JuDoc +const D = joinpath(dirname(dirname(pathof(JuDoc))), "test", "_dummies") # NOTE this first file MUST be included before running the rest of the tests # otherwise you may get an error like "key 0x099191234..." was not found or