diff --git a/CHANGELOG.md b/CHANGELOG.md index 1019a9afdd..2b936249cd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed +* Fixed display of inline LaTeX math `$ ... $` from `show` methods in HTMLWriter. ([#2280], [#2281]) * Fixed a crash in GitHub remote link checking when `remotes = nothing`. ([#2274], [#2285]) ## Version [v1.0.1] - 2023-09-18 @@ -1689,6 +1690,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 [#2259]: https://github.com/JuliaDocs/Documenter.jl/issues/2259 [#2260]: https://github.com/JuliaDocs/Documenter.jl/issues/2260 [#2269]: https://github.com/JuliaDocs/Documenter.jl/issues/2269 +[#2281]: https://github.com/JuliaDocs/Documenter.jl/issues/2281 [JuliaLang/julia#29344]: https://github.com/JuliaLang/julia/issues/29344 [JuliaLang/julia#36953]: https://github.com/JuliaLang/julia/issues/36953 [JuliaLang/julia#38054]: https://github.com/JuliaLang/julia/issues/38054 diff --git a/src/html/HTMLWriter.jl b/src/html/HTMLWriter.jl index 1510cc033e..5c293b8f20 100644 --- a/src/html/HTMLWriter.jl +++ b/src/html/HTMLWriter.jl @@ -2389,17 +2389,15 @@ function domify(dctx::DCtx, node::Node, d::Dict{MIME,Any}) end # Check for some 'fallback' MIMEs, defaulting to 'text/plain' if we can't find any of them. return if haskey(d, MIME"text/latex"()) - # If the show(io, ::MIME"text/latex", x) output is already wrapped in \[ ... \] or $$ ... $$, we - # unwrap it first, since when we output Markdown.LaTeX objects we put the correct - # delimiters around it anyway. latex = d[MIME"text/latex"()] - # Make sure to match multiline strings! - m_bracket = match(r"\s*\\\[(.*)\\\]\s*"s, latex) - m_dollars = match(r"\s*\$\$(.*)\$\$\s*"s, latex) - out = if m_bracket === nothing && m_dollars === nothing + # If the show(io, ::MIME"text/latex", x) output is already wrapped in + # \[ ... \] or $$ ... $$, we unwrap it first, since when we output + # Markdown.LaTeX objects we put the correct delimiters around it anyway. + has_math, latex = _strip_latex_math_delimiters(latex) + out = if !has_math Documenter.mdparse(latex; mode = :single) else - [MarkdownAST.@ast MarkdownAST.DisplayMath(m_bracket !== nothing ? m_bracket[1] : m_dollars[1])] + [MarkdownAST.@ast MarkdownAST.DisplayMath(latex)] end domify(dctx, out) elseif haskey(d, MIME"text/markdown"()) @@ -2415,6 +2413,21 @@ function domify(dctx::DCtx, node::Node, d::Dict{MIME,Any}) end end +function _strip_latex_math_delimiters(latex::AbstractString) + # Make sure to match multiline strings! + m_bracket = match(r"\s*\\\[(.*)\\\]\s*"s, latex) + if m_bracket !== nothing + return true, m_bracket[1] + end + # This regex matches the strings "$ ... $" and "$$ ... $$", but not + # strings with miss-matched dollar signs such as "$ ... $$" or "$$ ... $" + m_dollars = match(r"^\s*(\${1,2})([^\$]*)\1\s*$"s, latex) + if m_dollars !== nothing + return true, m_dollars[2] + end + return false, latex +end + function domify_show_image_binary(dctx::DCtx, filetype::AbstractString, d::Dict{MIME,Any}) @tags img mime_name = "image/$filetype" diff --git a/test/examples/src/man/tutorial.md b/test/examples/src/man/tutorial.md index 31d2d1bf49..3e26e46824 100644 --- a/test/examples/src/man/tutorial.md +++ b/test/examples/src/man/tutorial.md @@ -551,6 +551,12 @@ LaTeXEquation("\\[\\left[\\begin{array}{rr} x & 2x \\\\ \n y & y \\end{array}\\r LaTeXEquation("\$\$\\begin{bmatrix} 1 & 2 \\\\ \n 3 & 4 \\end{bmatrix}\$\$") ``` +Inline-ish `text/latex` bytes: + +```@example showablelatex +LaTeXEquation("\$ x_{1} + x_{2} \$") +``` + ## Videos ![](https://dl8.webmfiles.org/big-buck-bunny_trailer.webm) diff --git a/test/htmlwriter.jl b/test/htmlwriter.jl index 954d959dc4..f514e54046 100644 --- a/test/htmlwriter.jl +++ b/test/htmlwriter.jl @@ -4,7 +4,7 @@ using Test import MarkdownAST using Documenter using Documenter: DocSystem -using Documenter.HTMLWriter: HTMLWriter, generate_version_file, generate_redirect_file, expand_versions +using Documenter.HTMLWriter: HTMLWriter, generate_version_file, generate_redirect_file, expand_versions, _strip_latex_math_delimiters function verify_version_file(versionfile, entries) @test isfile(versionfile) @@ -295,5 +295,51 @@ end @test html.size_threshold == 12345 @test html.size_threshold_warn == 1234 end + + @testset "HTML: _strip_latex_math_delimiters" begin + for content in [ + "a", + "x_1", + "x_{1} + x_{2}", + "\\begin{array}x_1\\\nx_2\\end{array}", + ] + for (left, right) in [("\\[", "\\]"), ("\$", "\$"), ("\$\$", "\$\$")] + for (input, output) in [ + content => (false, content), + "$left$content$right" => (true, content), + " $left$content$right" => (true, content), + "$left$content$right " => (true, content), + "\t$left$content$right " => (true, content), + " \t$left$content$right\t\t" => (true, content), + ] + @test _strip_latex_math_delimiters(input) == output + end + end + # Test that miss-matched delimiters are not treated as math + # delimiters + for (left, right) in [ + ("\\[", ""), + ("\$", ""), + ("\$\$", ""), + ("", "\\]"), + ("", "\$"), + ("", "\$\$"), + ("\$", "\\]"), + ("\$\$", "\$"), + ("\$", "\$\$"), + ] + for input in [ + content, + "$left$content$right", + " $left$content$right", + "$left$content$right ", + "\t$left$content$right ", + " \t$left$content$right\t\t", + ] + @test _strip_latex_math_delimiters(input) == (false, input) + end + end + end + end end end