Skip to content

Commit

Permalink
Html tokens (#416)
Browse files Browse the repository at this point in the history
  • Loading branch information
tlienart authored Mar 19, 2020
1 parent c0f59dd commit 1caa099
Show file tree
Hide file tree
Showing 11 changed files with 330 additions and 48 deletions.
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "Franklin"
uuid = "713c75ef-9fc9-4b05-94a9-213340da978e"
authors = ["Thibaut Lienart <[email protected]>"]
version = "0.6.8"
version = "0.6.9"

This comment has been minimized.

Copy link
@tlienart

tlienart Mar 19, 2020

Author Owner

[deps]
Dates = "ade2ca70-3891-5945-98fb-dc099432e06a"
Expand Down
2 changes: 2 additions & 0 deletions src/Franklin.jl
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,8 @@ const MESSAGE_FILE_GEN_FMD = "# $MESSAGE_FILE_GEN # hide\n"

include("build.jl") # check if user has Node/minify

include("regexes.jl")

# UTILS
include("utils/paths.jl")
include("utils/vars.jl")
Expand Down
42 changes: 36 additions & 6 deletions src/converter/html/blocks.jl
Original file line number Diff line number Diff line change
Expand Up @@ -167,11 +167,10 @@ function process_html_for(hs::AS, qblocks::Vector{AbstractBlock},
iname = β_open.iname
if !haskey(LOCAL_VARS, iname)
throw(HTMLBlockError("The iterable '$iname' is not recognised. " *
"Make sure it's defined."))
"Please make sure it's defined."))
end

# try to close the for loop

if i == length(qblocks)
throw(HTMLBlockError("Could not close the conditional block " *
"starting with '$(qblocks[i].ss)'."))
Expand All @@ -197,17 +196,48 @@ function process_html_for(hs::AS, qblocks::Vector{AbstractBlock},
β_close = qblocks[i]
i_close = i

isempty(locvar(iname)) && @goto final_step

# is vname a single variable or multiple variables?
# --> {{for v in iterate}}
# --> {{for (v1, v2) in iterate }}
vnames = [vname]
if startswith(vname, "(")
vnames = strip.(split(vname[2:end-1], ","))
end
# check that the first element of the iterate has the same length
el1 = first(locvar(iname))
length(vnames) in (1, length(el1)) ||
throw(HTMLBlockError("In a {{for ...}}, the first element of" *
"the iterate has length $(length(el1)) but tried to unpack" *
"it as $(length(vnames)) variables."))

# so now basically we have to simply copy-paste the content replacing
# variable `vname` when it appears in a html block {{...}}
# users should try not to be dumb about this... if vname or iname
# corresponds to something they shouldn't touch, they'll crash things.

# content of the for block
inner = subs(hs, nextind(hs, to(β_open)), prevind(hs, from(β_close)))
isempty(strip(inner)) && @goto final_step
content = ""
for value in locvar(iname)
# at the moment we only consider {{fill ...}}
content *= replace(inner,
Regex("({{\\s*fill\\s+$vname\\s*}})") => "$value")
if length(vnames) == 1
for value in locvar(iname)
# at the moment we only consider {{fill ...}}
content *= replace(inner,
Regex("({{\\s*fill\\s+$vname\\s*}})") => "$value")
end
else
for value in locvar(iname)
temp = inner
for (vname, value) in zip(vnames, value)
temp = replace(temp,
Regex("({{\\s*fill\\s+$vname\\s*}})") => "$value")
end
content *= temp
end
end
@label final_step
head = nextind(hs, to(β_close))
return convert_html(content), head, i_close
end
8 changes: 1 addition & 7 deletions src/converter/html/link_fixer.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,7 @@ Direct inline-style links are properly processed by Julia's Markdown processor b
"""
function find_and_fix_md_links(hs::String)::String
# 1. find all occurences of -- [...]: link

# here we're looking for [id] or [id][] or [stuff][id] or ![stuff][id] but not [id]:
# 1 > (&#33;)? == either ! or nothing
# 2 > &#91;(.*?)&#93; == [...] inside of the brackets
# 3 > (?:&#91;(.*?)&#93;)? == [...] inside of second brackets if there is such
rx = r"(&#33;)?&#91;(.*?)&#93;(?!:)(?:&#91;(.*?)&#93;)?"
m_link_refs = collect(eachmatch(rx, hs))
m_link_refs = collect(eachmatch(ESC_LINK_PAT, hs))

# recuperate the appropriate id which has a chance to match def_names
ref_names = [
Expand Down
7 changes: 6 additions & 1 deletion src/parser/html/blocks.jl
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,12 @@ function qualify_html_hblocks(blocks::Vector{OCBlock})::Vector{AbstractBlock}
# ---
# for block
m = match(HBLOCK_FOR_PAT, β.ss)
isnothing(m) || (qb[i] = HFor.ss, m.captures[1], m.captures[2]); continue)
if !isnothing(m)
v, iter = m.captures
check_for_pat(v)
qb[i] = HFor.ss, v, iter);
continue
end
# ---
# function block {{ fname v1 v2 ... }}
m = match(HBLOCK_FUN_PAT, β.ss)
Expand Down
31 changes: 0 additions & 31 deletions src/parser/html/tokens.jl
Original file line number Diff line number Diff line change
Expand Up @@ -48,29 +48,6 @@ at this point. This second point might fix the first one by making sure that
HElse -> HEnd
=#

"""
HBLOCK_IF_PAT # {{if v1}}
HBLOCK_ELSE_PAT # {{else}}
HBLOCK_ELSEIF_PAT # {{elseif v1}}
HBLOCK_END_PAT # {{end}}
HBLOCK_ISDEF_PAT # {{isdef v1}} alias: ifdef
HBLOCK_ISNOTDEF_PAT # {{isnotdef v1}} alias: ifnotdef,isndef,ifndef
HBLOCK_ISPAGE_PAT # {{ispage p1 p2}}
HBLOCK_ISNOTPAGE_PAT # {{isnotpage p1 p2}}
HBLOCK_FOR_PAT # {{for x in iterable}}
Regex for the different HTML tokens.
"""
const HBLOCK_IF_PAT = r"{{\s*if\s+([a-zA-Z_]\S*)\s*}}"
const HBLOCK_ELSE_PAT = r"{{\s*else\s*}}"
const HBLOCK_ELSEIF_PAT = r"{{\s*else\s*if\s+([a-zA-Z_]\S*)\s*}}"
const HBLOCK_END_PAT = r"{{\s*end\s*}}"
const HBLOCK_ISDEF_PAT = r"{{\s*i(?:s|f)def\s+([a-zA-Z_]\S*)\s*}}"
const HBLOCK_ISNOTDEF_PAT = r"{{\s*i(?:s|f)n(?:ot)?def\s+([a-zA-Z_]\S*)\s*}}"
const HBLOCK_ISPAGE_PAT = r"{{\s*ispage\s+((.|\n)+?)}}"
const HBLOCK_ISNOTPAGE_PAT = r"{{\s*isnotpage\s+((.|\n)+?)}}"
const HBLOCK_FOR_PAT = r"{{\s*for\s+([a-zA-Z_]\S*)\s+in\s+([a-zA-Z_]\S*)\s*}}"

"""
$(TYPEDEF)
Expand Down Expand Up @@ -217,14 +194,6 @@ struct HFun <: AbstractBlock
end


"""
HBLOCK_TOC_PAT
Insertion for a table of contents.
"""
const HBLOCK_TOC_PAT = r"{{\s*toc\s*}}"


"""
$(TYPEDEF)
Expand Down
47 changes: 47 additions & 0 deletions src/regexes.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#= =====================================================
LINK patterns, see html link fixer
===================================================== =#
# here we're looking for [id] or [id][] or [stuff][id] or ![stuff][id] but not [id]:
# 1 > (&#33;)? == either ! or nothing
# 2 > &#91;(.*?)&#93; == [...] inside of the brackets
# 3 > (?:&#91;(.*?)&#93;)? == [...] inside of second brackets if there is such
const ESC_LINK_PAT = r"(&#33;)?&#91;(.*?)&#93;(?!:)(?:&#91;(.*?)&#93;)?"

#= =====================================================
HBLOCK patterns, see html blocks
NOTE: the for block needs verification (matching parens)
===================================================== =#

const HBLOCK_IF_PAT = r"{{\s*if\s+([a-zA-Z_]\S*)\s*}}"
const HBLOCK_ELSE_PAT = r"{{\s*else\s*}}"
const HBLOCK_ELSEIF_PAT = r"{{\s*else\s*if\s+([a-zA-Z_]\S*)\s*}}"
const HBLOCK_END_PAT = r"{{\s*end\s*}}"

const HBLOCK_ISDEF_PAT = r"{{\s*i(?:s|f)def\s+([a-zA-Z_]\S*)\s*}}"
const HBLOCK_ISNOTDEF_PAT = r"{{\s*i(?:s|f)n(?:ot)?def\s+([a-zA-Z_]\S*)\s*}}"
const HBLOCK_ISPAGE_PAT = r"{{\s*ispage\s+((.|\n)+?)}}"
const HBLOCK_ISNOTPAGE_PAT = r"{{\s*isnotpage\s+((.|\n)+?)}}"

const HBLOCK_FOR_PAT = r"{{\s*for\s+(\(?(?:\s*[a-zA-Z_][^\r\n\t\f\v,]*,\s*)*[a-zA-Z_]\S*\s*\)?)\s+in\s+([a-zA-Z_]\S*)\s*}}"

const HBLOCK_TOC_PAT = r"{{\s*toc\s*}}"

#= =====================================================
Pattern checkers
===================================================== =#

"""
check_for_pat(v)
Check that we have something like `{{for v in iterate}}` or
`{for (v1,v2) in iterate}}` but not something with unmached parens.
"""
function check_for_pat(v)
op = startswith(v, "(")
cp = endswith(v, ")")
xor(op, cp) &&
throw(HTMLBlockError("Unbalanced expression in {{for ...}}"))
!op && occursin(",", v) &&
throw(HTMLBlockError("Missing parens in {{for ...}}"))
return nothing
end
43 changes: 43 additions & 0 deletions test/converter/html_for.jl
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,46 @@ end
path/to/badge2.png
""")
end

@testset "h-for3" begin
F.def_LOCAL_VARS!()
s = """
@def iter = (("a", 1), ("b", 2), ("c", 3))
""" |> fd2html_td
h = raw"""
ABC
{{for (n, v) in iter}}
name:{{fill n}}
value:{{fill v}}
{{end}}
""" |> F.convert_html
@test isapproxstr(h, """
ABC
name:a
value:1
name:b
value:2
name:c
value:3
""")

s = """
@def iter2 = ("a"=>10, "b"=>7, "c"=>3)
""" |> fd2html_td
h = raw"""
ABC
{{for (n, v) in iter2}}
name:{{fill n}}
value:{{fill v}}
{{end}}
""" |> F.convert_html
@test isapproxstr(h, """
ABC
name:a
value:10
name:b
value:7
name:c
value:3
""")
end
Loading

1 comment on commit 1caa099

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registration pull request created: JuliaRegistries/General/11191

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if Julia TagBot is installed, or can be done manually through the github interface, or via:

git tag -a v0.6.9 -m "<description of version>" 1caa0993220593568265c3483656aa3e96e38d1d
git push origin v0.6.9

Please sign in to comment.