Skip to content

Commit

Permalink
Fix syntax of generated CSS
Browse files Browse the repository at this point in the history
Quoting and consistent semicolon separation weren't quite right, but
should be now.
  • Loading branch information
tecosaur committed Sep 8, 2024
1 parent c82409c commit cfcfe8c
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 46 deletions.
53 changes: 31 additions & 22 deletions src/io.jl
Original file line number Diff line number Diff line change
Expand Up @@ -361,17 +361,26 @@ const HTML_WEIGHT_MAP = Dict{Symbol, Int}(
:extrabold => 800,
:black => 900)

function htmlstyle(io::IO, face::Face, lastface::Face=getface())
print(io, "<span style=\"")
function cssattrs(io::IO, face::Face, lastface::Face=getface(), escapequotes::Bool=true)
priorattr = false
function printattr(io, attr, valparts...)
if priorattr
print(io, "; ")
else
priorattr = true
end
print(io, attr, ": ", valparts...)
end
face.font == lastface.font ||
print(io, "font-family: \"",
replace(face.font, '"' => "&quot;", ''' => "&#39;"), '"')
printattr(io, "font-family", ifelse(escapequotes, "&quot;", "\""),
replace(face.font, '"' => "\\&quot;", ''' => "&#39;"),
ifelse(escapequotes, "&quot;", "\""))
face.height == lastface.height ||
print(io, "font-size: ", string(face.height ÷ 10), "pt;")
printattr(io, "font-size", string(face.height ÷ 10), "pt")
face.weight == lastface.weight ||
print(io, "font-weight: ", get(HTML_WEIGHT_MAP, face.weight, 400), ';')
printattr(io, "font-weight", get(HTML_WEIGHT_MAP, face.weight, 400))
face.slant == lastface.slant ||
print(io, "font-style: ", String(face.slant), ';')
printattr(io, "font-style", String(face.slant))
foreground, background =
ifelse(face.inverse === true,
(face.background, face.foreground),
Expand All @@ -381,19 +390,17 @@ function htmlstyle(io::IO, face::Face, lastface::Face=getface())
(lastface.background, lastface.foreground),
(lastface.foreground, lastface.background))
if foreground != lastforeground
print(io, "color: ")
printattr(io, "color")
htmlcolor(io, foreground)
print(io, ';')
end
if background != lastbackground
print(io, "background-color: ")
printattr(io, "background-color")
htmlcolor(io, background)
print(io, ';')
end
face.underline == lastface.underline ||
if face.underline isa Tuple # Color and style
color, style = face.underline
print(io, "text-decoration: ")
printattr(io, "text-decoration")
if !isnothing(color)
htmlcolor(io, color)
print(io, ' ')
Expand All @@ -403,17 +410,16 @@ function htmlstyle(io::IO, face::Face, lastface::Face=getface())
elseif style == :curly "wavy "
elseif style == :dotted "dotted "
elseif style == :dashed "dashed "
else "" end)
print(io, "underline;")
else "" end, "underline")
elseif face.underline isa SimpleColor
print(io, "text-decoration: ")
printattr(io, "text-decoration")
htmlcolor(io, face.underline)
if lastface.underline isa Tuple && last(lastface.underline) != :straight
print(io, " solid")
end
print(io, " underline;")
print(io, " underline")
else # must be a Bool
print(io, "text-decoration: ")
printattr(io, "text-decoration")
if lastface.underline isa SimpleColor
print(io, "currentcolor ")
elseif lastface.underline isa Tuple
Expand All @@ -422,13 +428,16 @@ function htmlstyle(io::IO, face::Face, lastface::Face=getface())
last(lastface.underline) != :straight &&
print(io, "straight ")
end
print(io, ifelse(face.underline, "underline;", "none;"))
print(io, ifelse(face.underline, "underline", "none"))
end
face.strikethrough == lastface.strikethrough ||
print(io, ifelse(face.strikethrough,
"text-decoration: line-through",
ifelse(face.underline === false,
"text-decoration: none", "")))
!face.strikethrough && face.underline !== false ||
printattr(io, "text-decoration", ifelse(face.strikethrough, "line-through", "none"))
end

function htmlstyle(io::IO, face::Face, lastface::Face=getface())
print(io, "<span style=\"")
cssattrs(io, face, lastface, true)
print(io, "\">")
end

Expand Down
48 changes: 24 additions & 24 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -609,39 +609,39 @@ end
face = getface(Face(; attrs...))
sprint(StyledStrings.htmlstyle, face)
end
@test html_change(foreground=:cyan) == "<span style=\"color: #0097a7;\">"
@test html_change(background=:cyan) == "<span style=\"background-color: #0097a7;\">"
@test html_change(weight=:bold) == "<span style=\"font-weight: 700;\">"
@test html_change(weight=:extrabold) == "<span style=\"font-weight: 800;\">"
@test html_change(weight=:light) == "<span style=\"font-weight: 300;\">"
@test html_change(foreground=:cyan) == "<span style=\"color: #0097a7\">"
@test html_change(background=:cyan) == "<span style=\"background-color: #0097a7\">"
@test html_change(weight=:bold) == "<span style=\"font-weight: 700\">"
@test html_change(weight=:extrabold) == "<span style=\"font-weight: 800\">"
@test html_change(weight=:light) == "<span style=\"font-weight: 300\">"
@test html_change(foreground=:blue, background=:red, inverse=true) ==
"<span style=\"color: #a51c2c;background-color: #195eb3;\">"
@test html_change(slant=:italic) == "<span style=\"font-style: italic;\">"
@test html_change(height=180) == "<span style=\"font-size: 18pt;\">"
@test html_change(underline=true) == "<span style=\"text-decoration: underline;\">"
@test html_change(underline=:green) == "<span style=\"text-decoration: #25a268 underline;\">"
@test html_change(underline=:straight) == "<span style=\"text-decoration: solid underline;\">"
@test html_change(underline=:double) == "<span style=\"text-decoration: double underline;\">"
@test html_change(underline=:curly) == "<span style=\"text-decoration: wavy underline;\">"
@test html_change(underline=:dotted) == "<span style=\"text-decoration: dotted underline;\">"
@test html_change(underline=:dashed) == "<span style=\"text-decoration: dashed underline;\">"
@test html_change(underline=(:cyan, :double)) == "<span style=\"text-decoration: #0097a7 double underline;\">"
"<span style=\"color: #a51c2c; background-color: #195eb3\">"
@test html_change(slant=:italic) == "<span style=\"font-style: italic\">"
@test html_change(height=180) == "<span style=\"font-size: 18pt\">"
@test html_change(underline=true) == "<span style=\"text-decoration: underline\">"
@test html_change(underline=:green) == "<span style=\"text-decoration: #25a268 underline\">"
@test html_change(underline=:straight) == "<span style=\"text-decoration: solid underline\">"
@test html_change(underline=:double) == "<span style=\"text-decoration: double underline\">"
@test html_change(underline=:curly) == "<span style=\"text-decoration: wavy underline\">"
@test html_change(underline=:dotted) == "<span style=\"text-decoration: dotted underline\">"
@test html_change(underline=:dashed) == "<span style=\"text-decoration: dashed underline\">"
@test html_change(underline=(:cyan, :double)) == "<span style=\"text-decoration: #0097a7 double underline\">"
@test html_change(strikethrough=true) == "<span style=\"text-decoration: line-through\">"
# Might as well put everything together for a final test
fancy_string = styled"The {magenta:`{green:StyledStrings}`} package {italic:builds}\
{bold: on top} of the {magenta:`{green:AnnotatedString}`} {link={https://en.wikipedia.org/wiki/Type_system}:type} \
to provide a {(underline=(red,curly)):full-fledged} textual {(bg=#4063d8,fg=#adbdf8,inherit=[bold,strikethrough]):styling} \
system, suitable for {inverse:terminal} and graphical displays."
@test sprint(show, MIME("text/html"), fancy_string[1:27]) ==
"The <span style=\"color: #803d9b;\">`</span><span style=\"color: #25a268;\">StyledStrings</span>\
<span style=\"color: #803d9b;\">`</span> package"
"The <span style=\"color: #803d9b\">`</span><span style=\"color: #25a268\">StyledStrings</span>\
<span style=\"color: #803d9b\">`</span> package"
@test sprint(show, MIME("text/html"), fancy_string) ==
"The <span style=\"color: #803d9b;\">`</span><span style=\"color: #25a268;\">StyledStrings</span><span style=\"color: #803d9b;\">\
`</span> package <span style=\"font-style: italic;\">builds<span style=\"font-weight: 700;font-style: normal;\"> on top</span></span> \
of the <span style=\"color: #803d9b;\">`</span><span style=\"color: #25a268;\">AnnotatedString</span><span style=\"color: #803d9b;\">\
`</span> <a href=\"https://en.wikipedia.org/wiki/Type_system\">type</a> to provide a <span style=\"text-decoration: #a51c2c wavy underline;\">\
full-fledged</span> textual <span style=\"font-weight: 700;color: #adbdf8;background-color: #4063d8;text-decoration: line-through\">styling</span> \
system, suitable for <span style=\"\">terminal</span> and graphical displays."
"The <span style=\"color: #803d9b\">`</span><span style=\"color: #25a268\">StyledStrings</span><span style=\"color: #803d9b\">`</span> \
package <span style=\"font-style: italic\">builds<span style=\"font-weight: 700; font-style: normal\"> on top</span></span> of the \
<span style=\"color: #803d9b\">`</span><span style=\"color: #25a268\">AnnotatedString</span><span style=\"color: #803d9b\">`</span> \
<a href=\"https://en.wikipedia.org/wiki/Type_system\">type</a> to provide a <span style=\"text-decoration: #a51c2c wavy underline\">\
full-fledged</span> textual <span style=\"font-weight: 700; color: #adbdf8; background-color: #4063d8; text-decoration: line-through\">\
styling</span> system, suitable for <span style=\"\">terminal</span> and graphical displays."
end

@testset "Legacy" begin
Expand Down

0 comments on commit cfcfe8c

Please sign in to comment.