From 846380decdee9c974757544f6d7aa75df93aa68e Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Fri, 26 Feb 2021 11:35:06 +0100 Subject: [PATCH 1/9] put svg with xmlns in img src tag --- Project.toml | 2 ++ src/Writers/HTMLWriter.jl | 13 ++++++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index dee18a3060..381255d223 100644 --- a/Project.toml +++ b/Project.toml @@ -14,12 +14,14 @@ Logging = "56ddb016-857b-54e1-b83d-db4d58db5568" Markdown = "d6f4376e-aef5-505a-96c1-9c027394607a" REPL = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" +URIs = "5c2747f8-b7ea-4ff2-ba2e-563bfd36b1d4" Unicode = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5" [compat] DocStringExtensions = "0.4, 0.5, 0.6, 0.7, 0.8" IOCapture = "0.1" JSON = "0.19, 0.20, 0.21" +URIs = "1.2" julia = "1" [extras] diff --git a/src/Writers/HTMLWriter.jl b/src/Writers/HTMLWriter.jl index 427e1032ef..51109915df 100644 --- a/src/Writers/HTMLWriter.jl +++ b/src/Writers/HTMLWriter.jl @@ -43,6 +43,7 @@ module HTMLWriter using Dates: Dates, @dateformat_str, now import Markdown import JSON +import URIs import ...Documenter: Anchors, @@ -1748,7 +1749,17 @@ function mdconvert(d::Dict{MIME,Any}, parent; kwargs...) if haskey(d, MIME"text/html"()) out = Documents.RawHTML(d[MIME"text/html"()]) elseif haskey(d, MIME"image/svg+xml"()) - out = Documents.RawHTML(d[MIME"image/svg+xml"()]) + svg = d[MIME"image/svg+xml"()] + # the xmlns attribute has to be present for data:image/svg+xml + # to work (https://stackoverflow.com/questions/18467982) + # URIs.escapeuri is needed to replace all special characters from the SVG string + # which could break the HTML + out = if occursin("xmlns=", svg) + escaped_svg = URIs.escapeuri(svg) + Documents.RawHTML(string("")) + else + Documents.RawHTML(d[MIME"image/svg+xml"()]) + end elseif haskey(d, MIME"image/png"()) out = Documents.RawHTML(string("")) elseif haskey(d, MIME"image/webp"()) From a9a52ef0b274e5c697f1942025c3d49699ca942e Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Sun, 28 Feb 2021 09:45:10 +0100 Subject: [PATCH 2/9] remove URIs, use utf8 with minor modifications --- Project.toml | 2 -- src/Writers/HTMLWriter.jl | 26 ++++++++++++++++++++------ 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/Project.toml b/Project.toml index 381255d223..dee18a3060 100644 --- a/Project.toml +++ b/Project.toml @@ -14,14 +14,12 @@ Logging = "56ddb016-857b-54e1-b83d-db4d58db5568" Markdown = "d6f4376e-aef5-505a-96c1-9c027394607a" REPL = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" -URIs = "5c2747f8-b7ea-4ff2-ba2e-563bfd36b1d4" Unicode = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5" [compat] DocStringExtensions = "0.4, 0.5, 0.6, 0.7, 0.8" IOCapture = "0.1" JSON = "0.19, 0.20, 0.21" -URIs = "1.2" julia = "1" [extras] diff --git a/src/Writers/HTMLWriter.jl b/src/Writers/HTMLWriter.jl index 51109915df..70c33c9794 100644 --- a/src/Writers/HTMLWriter.jl +++ b/src/Writers/HTMLWriter.jl @@ -43,7 +43,6 @@ module HTMLWriter using Dates: Dates, @dateformat_str, now import Markdown import JSON -import URIs import ...Documenter: Anchors, @@ -1750,13 +1749,28 @@ function mdconvert(d::Dict{MIME,Any}, parent; kwargs...) out = Documents.RawHTML(d[MIME"text/html"()]) elseif haskey(d, MIME"image/svg+xml"()) svg = d[MIME"image/svg+xml"()] - # the xmlns attribute has to be present for data:image/svg+xml + # The xmlns attribute has to be present for data:image/svg+xml # to work (https://stackoverflow.com/questions/18467982) - # URIs.escapeuri is needed to replace all special characters from the SVG string - # which could break the HTML out = if occursin("xmlns=", svg) - escaped_svg = URIs.escapeuri(svg) - Documents.RawHTML(string("")) + # We can leave the svg as utf8, but the minimum safety precaution we need + # is to ensure the src string separator is not in the svg. + # That can be either " or ', and the svg will most likely use only one of them + # so we check which one occurs more often and use the other as the separator. + # This should leave most svg basically intact. + singles = count(==('\''), svg) + doubles = count(==('"'), svg) + if singles > doubles + # Replace every " with %22 because it terminates the src=" string otherwise + svg = replace(svg, "\"" => "%22") + sep = "\"" + else + # Replace every ' with %27 because it terminates the src=' string otherwise + svg = replace(svg, "\'" => "%27") + sep = "'" + end + # Replace # with %23 https://github.com/jakubpawlowicz/clean-css/issues/763#issuecomment-215283553 + svg = replace(svg, "#" => "%23") + Documents.RawHTML(string("")) else Documents.RawHTML(d[MIME"image/svg+xml"()]) end From 88e92a262217076e65229725024370f6e7e46178 Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Sun, 28 Feb 2021 10:16:40 +0100 Subject: [PATCH 3/9] splice in xmlns if not present --- src/Writers/HTMLWriter.jl | 49 ++++++++++++++++++++++----------------- 1 file changed, 28 insertions(+), 21 deletions(-) diff --git a/src/Writers/HTMLWriter.jl b/src/Writers/HTMLWriter.jl index 70c33c9794..747bc3578b 100644 --- a/src/Writers/HTMLWriter.jl +++ b/src/Writers/HTMLWriter.jl @@ -1749,31 +1749,38 @@ function mdconvert(d::Dict{MIME,Any}, parent; kwargs...) out = Documents.RawHTML(d[MIME"text/html"()]) elseif haskey(d, MIME"image/svg+xml"()) svg = d[MIME"image/svg+xml"()] + # The xmlns attribute has to be present for data:image/svg+xml # to work (https://stackoverflow.com/questions/18467982) - out = if occursin("xmlns=", svg) - # We can leave the svg as utf8, but the minimum safety precaution we need - # is to ensure the src string separator is not in the svg. - # That can be either " or ', and the svg will most likely use only one of them - # so we check which one occurs more often and use the other as the separator. - # This should leave most svg basically intact. - singles = count(==('\''), svg) - doubles = count(==('"'), svg) - if singles > doubles - # Replace every " with %22 because it terminates the src=" string otherwise - svg = replace(svg, "\"" => "%22") - sep = "\"" - else - # Replace every ' with %27 because it terminates the src=' string otherwise - svg = replace(svg, "\'" => "%27") - sep = "'" - end - # Replace # with %23 https://github.com/jakubpawlowicz/clean-css/issues/763#issuecomment-215283553 - svg = replace(svg, "#" => "%23") - Documents.RawHTML(string("")) + svg_tag = match(r"]*>", svg).match + + # If it doesn't exist, we splice it into the first svg tag. + # This should never invalidate otherwise valid svg. + xmlns_present = occursin("xmlns", svg_tag) + if !xmlns_present + svg = replace(svg, " " doubles + # Replace every " with %22 because it terminates the src=" string otherwise + svg = replace(svg, "\"" => "%22") + sep = "\"" else - Documents.RawHTML(d[MIME"image/svg+xml"()]) + # Replace every ' with %27 because it terminates the src=' string otherwise + svg = replace(svg, "\'" => "%27") + sep = "'" end + # Replace # with %23 https://github.com/jakubpawlowicz/clean-css/issues/763#issuecomment-215283553 + svg = replace(svg, "#" => "%23") + out = Documents.RawHTML(string("")) + elseif haskey(d, MIME"image/png"()) out = Documents.RawHTML(string("")) elseif haskey(d, MIME"image/webp"()) From 8a01e74ccfa3b8a021ff57edeaa97b6d989ebe9b Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Sun, 28 Feb 2021 10:32:03 +0100 Subject: [PATCH 4/9] add test cases --- test/examples/src/man/tutorial.md | 77 +++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/test/examples/src/man/tutorial.md b/test/examples/src/man/tutorial.md index 01c0bceaaf..9c920a0eb1 100644 --- a/test/examples/src/man/tutorial.md +++ b/test/examples/src/man/tutorial.md @@ -182,6 +182,8 @@ Base.show(io, ::MIME"image/svg+xml", svg::SVG) = write(io, svg.code) end # module ``` +Without xmlns tag: + ```@example inlinesvg using .InlineSVG SVG(""" @@ -195,6 +197,81 @@ SVG(""" """) ``` +With xmlns tag: + +```@example inlinesvg +using .InlineSVG +SVG(""" + + + + + + + +""") +``` + +With single quotes: + +```@example inlinesvg +using .InlineSVG +SVG(""" + + + + + + + +""") +``` + +With a mixture of single and double quotes: + +```@example inlinesvg +using .InlineSVG +SVG(""" + + + + + + + +""") +``` + +With viewBox and without xmlns, making the svg really large to test that it is resized correctly: + +```@example inlinesvg +using .InlineSVG +SVG(""" + + + + + + + +""") +``` + +Without viewBox and without xmlns, making the svg really large to test that it is resized correctly: + +```@example inlinesvg +using .InlineSVG +SVG(""" + + + + + + + +""") +``` + _Note: we can't define the `show` method in the `@example` block due to the world age counter in Julia 0.6 (Documenter's `makedocs` is not aware of any of the new method definitions happening in `eval`s)._ From 1ce12338123e2e1adb76fa833459f14d84be2e2f Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Sun, 28 Feb 2021 12:30:13 +0100 Subject: [PATCH 5/9] replace % also --- src/Writers/HTMLWriter.jl | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/Writers/HTMLWriter.jl b/src/Writers/HTMLWriter.jl index 747bc3578b..f12c4e9704 100644 --- a/src/Writers/HTMLWriter.jl +++ b/src/Writers/HTMLWriter.jl @@ -1766,6 +1766,11 @@ function mdconvert(d::Dict{MIME,Any}, parent; kwargs...) # That can be either " or ', and the svg will most likely use only one of them # so we check which one occurs more often and use the other as the separator. # This should leave most svg basically intact. + + # Replace % with %25 and # with %23 https://github.com/jakubpawlowicz/clean-css/issues/763#issuecomment-215283553 + svg = replace(svg, "%" => "%25") + svg = replace(svg, "#" => "%23") + singles = count(==('\''), svg) doubles = count(==('"'), svg) if singles > doubles @@ -1777,8 +1782,7 @@ function mdconvert(d::Dict{MIME,Any}, parent; kwargs...) svg = replace(svg, "\'" => "%27") sep = "'" end - # Replace # with %23 https://github.com/jakubpawlowicz/clean-css/issues/763#issuecomment-215283553 - svg = replace(svg, "#" => "%23") + out = Documents.RawHTML(string("")) elseif haskey(d, MIME"image/png"()) From 1c9bb22cb68cd30b5e783307f0fece536e6240a7 Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Sun, 14 Mar 2021 09:11:16 +0100 Subject: [PATCH 6/9] handle edge case where no svg tag is found --- src/Writers/HTMLWriter.jl | 71 ++++++++++++++++++++++----------------- 1 file changed, 40 insertions(+), 31 deletions(-) diff --git a/src/Writers/HTMLWriter.jl b/src/Writers/HTMLWriter.jl index f12c4e9704..f4668102a4 100644 --- a/src/Writers/HTMLWriter.jl +++ b/src/Writers/HTMLWriter.jl @@ -1750,41 +1750,50 @@ function mdconvert(d::Dict{MIME,Any}, parent; kwargs...) elseif haskey(d, MIME"image/svg+xml"()) svg = d[MIME"image/svg+xml"()] - # The xmlns attribute has to be present for data:image/svg+xml - # to work (https://stackoverflow.com/questions/18467982) - svg_tag = match(r"]*>", svg).match - - # If it doesn't exist, we splice it into the first svg tag. - # This should never invalidate otherwise valid svg. - xmlns_present = occursin("xmlns", svg_tag) - if !xmlns_present - svg = replace(svg, " " "%25") - svg = replace(svg, "#" => "%23") - - singles = count(==('\''), svg) - doubles = count(==('"'), svg) - if singles > doubles - # Replace every " with %22 because it terminates the src=" string otherwise - svg = replace(svg, "\"" => "%22") - sep = "\"" + svg_tag_match = match(r"]*>", svg) + + if isnothing(svg_tag_match) + # There is no svg tag so we don't do any more advanced + # processing and just return the svg as RawHTML. + # The svg string should be invalid but that's not our concern here. + out = Documents.RawHTML(svg) else - # Replace every ' with %27 because it terminates the src=' string otherwise - svg = replace(svg, "\'" => "%27") - sep = "'" + # The xmlns attribute has to be present for data:image/svg+xml + # to work (https://stackoverflow.com/questions/18467982). + # If it doesn't exist, we splice it into the first svg tag. + # This should never invalidate otherwise valid svg. + svg_tag = svg_tag_match.match + xmlns_present = occursin("xmlns", svg_tag) + if !xmlns_present + svg = replace(svg, " " "%25") + svg = replace(svg, "#" => "%23") + + singles = count(==('\''), svg) + doubles = count(==('"'), svg) + if singles > doubles + # Replace every " with %22 because it terminates the src=" string otherwise + svg = replace(svg, "\"" => "%22") + sep = "\"" + else + # Replace every ' with %27 because it terminates the src=' string otherwise + svg = replace(svg, "\'" => "%27") + sep = "'" + end + + out = Documents.RawHTML(string("")) end - out = Documents.RawHTML(string("")) - elseif haskey(d, MIME"image/png"()) out = Documents.RawHTML(string("")) elseif haskey(d, MIME"image/webp"()) From 6fe5e7e7f84355b1d0d6831216ad3c8ee614bc23 Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Sun, 14 Mar 2021 09:14:27 +0100 Subject: [PATCH 7/9] isnothing is not available in all julia versions --- src/Writers/HTMLWriter.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Writers/HTMLWriter.jl b/src/Writers/HTMLWriter.jl index f4668102a4..6c226cecf7 100644 --- a/src/Writers/HTMLWriter.jl +++ b/src/Writers/HTMLWriter.jl @@ -1753,7 +1753,7 @@ function mdconvert(d::Dict{MIME,Any}, parent; kwargs...) svg_tag_match = match(r"]*>", svg) - if isnothing(svg_tag_match) + if svg_tag_match === nothing # There is no svg tag so we don't do any more advanced # processing and just return the svg as RawHTML. # The svg string should be invalid but that's not our concern here. From 89b2d31e06df02ecbe84ef4804bcb44a3ff2247b Mon Sep 17 00:00:00 2001 From: jkrumbiegel <22495855+jkrumbiegel@users.noreply.github.com> Date: Mon, 15 Mar 2021 09:12:39 +0100 Subject: [PATCH 8/9] Update src/Writers/HTMLWriter.jl Co-authored-by: Morten Piibeleht --- src/Writers/HTMLWriter.jl | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/Writers/HTMLWriter.jl b/src/Writers/HTMLWriter.jl index 6c226cecf7..38c3c0968d 100644 --- a/src/Writers/HTMLWriter.jl +++ b/src/Writers/HTMLWriter.jl @@ -1749,10 +1749,7 @@ function mdconvert(d::Dict{MIME,Any}, parent; kwargs...) out = Documents.RawHTML(d[MIME"text/html"()]) elseif haskey(d, MIME"image/svg+xml"()) svg = d[MIME"image/svg+xml"()] - - svg_tag_match = match(r"]*>", svg) - if svg_tag_match === nothing # There is no svg tag so we don't do any more advanced # processing and just return the svg as RawHTML. From bcee49625bf00d646b2b9772f0b5a34f8f7f65b3 Mon Sep 17 00:00:00 2001 From: Morten Piibeleht Date: Tue, 16 Mar 2021 23:00:19 +1300 Subject: [PATCH 9/9] Update CHANGELOG.md --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a230e641b5..728ae78aa3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,8 @@ * ![Bugfix][badge-bugfix] A bad `repo` argument to `deploydocs` containing a protocol now throws an error instead of being misinterpreted. ([#1531][github-1531], [#1533][github-1533]) +* ![Bugfix][badge-bugfix] SVG images generated by `@example` blocks are now properly scaled to page width by URI-encoding the images, instead of directly embedding the SVG tags into the HTML. ([#1537][github-1537], [#1538][github-1538]) + ## Version `v0.26.3` * ![Maintenance][badge-maintenance] The internal naming of the temporary modules used to run doctests changed to accommodate upcoming printing changes in Julia. ([JuliaLang/julia#39841][julia-39841], [#1540][github-1540]) @@ -764,6 +766,8 @@ [github-1529]: https://github.com/JuliaDocs/Documenter.jl/pull/1529 [github-1531]: https://github.com/JuliaDocs/Documenter.jl/issues/1531 [github-1533]: https://github.com/JuliaDocs/Documenter.jl/pull/1533 +[github-1537]: https://github.com/JuliaDocs/Documenter.jl/issues/1537 +[github-1538]: https://github.com/JuliaDocs/Documenter.jl/pull/1538 [github-1540]: https://github.com/JuliaDocs/Documenter.jl/pull/1540 [github-1551]: https://github.com/JuliaDocs/Documenter.jl/pull/1551