Skip to content

Commit

Permalink
HTML codegen
Browse files Browse the repository at this point in the history
  • Loading branch information
Klafyvel committed Sep 18, 2022
1 parent e3e7bab commit 19ece93
Show file tree
Hide file tree
Showing 7 changed files with 136 additions and 0 deletions.
1 change: 1 addition & 0 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ version = "0.1.0"
[deps]
AbstractTrees = "1520ce14-60c1-5f80-bbc7-55ef81b5835c"
Compat = "34da2185-b29b-5c13-b0c7-acf172513d20"
Hyperscript = "47d2ed2b-36de-50cf-bf87-49c2cf4b8b91"

[compat]
Compat = "3.46, 4"
Expand Down
4 changes: 4 additions & 0 deletions src/Norg.jl
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,15 @@ include("tokenize.jl")
include("ast.jl")
include("match.jl")
include("parser.jl")
include("codegen.jl")

using .Tokens
using .Scanners
using .Tokenize
using .AST
using .Parser
using .Codegen



end
14 changes: 14 additions & 0 deletions src/codegen.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
module Codegen
using ..AST

abstract type CodegenTarget end

function codegen end
codegen(t::Type{T}, ast) where T<:CodegenTarget = codegen(t(), ast)

include("codegen/html.jl")
using .HTMLCodegen

export codegen, HTMLTarget

end
67 changes: 67 additions & 0 deletions src/codegen/html.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
module HTMLCodegen
using AbstractTrees
using Hyperscript
using ..AST
import ..CodegenTarget
import ..codegen

struct HTMLTarget <: CodegenTarget end
codegen(t::HTMLTarget, node::AST.Node{AST.NorgDocument}) = m("div", class="norg", [codegen(t, c) for c children(node)])

function codegen(t::HTMLTarget, node::AST.Node{AST.Paragraph})
res = []
for c in children(node)
append!(res, codegen(t, c))
push!(res, m("br"))
end
if !isempty(res)
pop!(res) # remove last <br>
end
m("p", res)
end

function codegen(t::HTMLTarget, node::AST.Node{AST.ParagraphSegment})
res = []
for c in children(node)
push!(res, codegen(t, c))
end
res
end

html_node(::AST.Node{AST.Bold}) = "b"
html_node(::AST.Node{AST.Italic}) = "i"
html_node(::AST.Node{AST.Underline}) = "ins"
html_node(::AST.Node{AST.Strikethrough}) = "del"
html_node(::AST.Node{AST.Spoiler}) = "span"
html_node(::AST.Node{AST.Superscript}) = "sup"
html_node(::AST.Node{AST.Subscript}) = "sub"
html_node(::AST.Node{AST.InlineCode}) = "code"

html_class(::AST.Node{AST.Bold}) = []
html_class(::AST.Node{AST.Italic}) = []
html_class(::AST.Node{AST.Underline}) = []
html_class(::AST.Node{AST.Strikethrough}) = []
html_class(::AST.Node{AST.Spoiler}) = ["spoiler"]
html_class(::AST.Node{AST.Superscript}) = []
html_class(::AST.Node{AST.Subscript}) = []
html_class(::AST.Node{AST.InlineCode}) = []

function codegen(t::HTMLTarget, node::AST.Node{<:AST.AttachedModifier})
res = []
for c in children(node)
push!(res, codegen(t, c))
end
class = html_class(node)
if isempty(class)
m(html_node(node), res)
else
m(html_node(node), class=join(html_class(node), " "), res)
end
end

codegen(::HTMLTarget, node::AST.Node{AST.Word}) = node.data.value
codegen(::HTMLTarget, node::AST.Node{AST.Escape}) = node.data.value

export HTMLTarget

end
Empty file added src/codegen/julia_repl.jl
Empty file.
2 changes: 2 additions & 0 deletions src/tokenize.jl
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,6 @@ function tokenize(input::AbstractString)
result
end

export tokenize

end
48 changes: 48 additions & 0 deletions test/codegen_tests/html.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
@testset "Test paragraphs" begin
s = "Hi I am first paragraph.\n\nOh, hello there, I am second paragraph !"
html = Norg.codegen(Norg.HTMLTarget, Norg.parse_norg(Norg.tokenize(s)))
pars = getfield(html, :children)
@test getfield(pars[1], :tag) == "p"
@test getfield(pars[2], :tag) == "p"
end

simple_markups_nodes = [
('*', "b"),
('/', "i"),
('_', "ins"),
('-', "del"),
('!', "span"),
('^', "sup"),
(',', "sub"),
('`', "code"),
]

simple_markups_class = [
('*', nothing),
('/', nothing),
('_', nothing),
('-', nothing),
('!', "spoiler"),
('^', nothing),
(',', nothing),
('`', nothing)
]

@testset "Test correct markup for $m" for (m,html_node) in simple_markups_nodes
s = "$(m)inner$(m)"
html = Norg.codegen(Norg.HTMLTarget, Norg.parse_norg(Norg.tokenize(s)))
b = first(getfield(first(getfield(html, :children)), :children))
@test getfield(b, :tag) == html_node
end

@testset "Test correct class for $m" for (m,html_class) in simple_markups_class
s = "$(m)inner$(m)"
html = Norg.codegen(Norg.HTMLTarget, Norg.parse_norg(Norg.tokenize(s)))
b = first(getfield(first(getfield(html, :children)), :children))
if isnothing(html_class)
@test !haskey(getfield(b, :attrs), "class")
else
@test haskey(getfield(b, :attrs), "class")
@test getfield(b, :attrs)["class"] == html_class
end
end

0 comments on commit 19ece93

Please sign in to comment.