From 65ee64aa4fc260c2ec359917150993ae81348129 Mon Sep 17 00:00:00 2001 From: Joris Kraak Date: Tue, 19 Jul 2022 09:03:09 +0200 Subject: [PATCH 01/12] docs: add note regarding SVG support for all `Diagram`s This was already included as a comment, but makes more sense to include in the docstring. Especially as it is the intention to make the content of this constant more visible to end-users. --- src/Kroki.jl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Kroki.jl b/src/Kroki.jl index d8be3a7..23071a5 100644 --- a/src/Kroki.jl +++ b/src/Kroki.jl @@ -179,6 +179,9 @@ render( Some MIME types are not supported by all diagram types, this constant contains all these limitations. The union of all values corresponds to all supported [`Diagram`](@ref) `type`s. + +Note that SVG output is supported by all diagram types. Those specifically +included here are those that _only_ support SVG output. """ const LIMITED_DIAGRAM_SUPPORT = Dict{MIME, Tuple{Symbol, Vararg{Symbol}}}( MIME"application/pdf"() => ( @@ -213,8 +216,6 @@ const LIMITED_DIAGRAM_SUPPORT = Dict{MIME, Tuple{Symbol, Vararg{Symbol}}}( :vega, :vegalite, ), - # Although all diagram types support SVG, these _only_ support SVG so are - # included separately MIME"image/svg+xml"() => (:bpmn, :bytefield, :excalidraw, :nomnoml, :pikchr, :svgbob, :wavedrom), # Diagrams that can be rendered to plain text support both ASCII and Unicode From fb1a3ecd253d54b6c83e0881765bf2edc44944b9 Mon Sep 17 00:00:00 2001 From: Joris Kraak Date: Tue, 19 Jul 2022 09:06:23 +0200 Subject: [PATCH 02/12] docs: add note regarding MIME types for plain text rendering This information was already included as a comment. However, this information makes sense to surface to end-users as well. Especially given that it ties in to the `SUPPORTED_TEXT_PLAIN_SHOW_MIME_TYPES` configuration variable. --- src/Kroki.jl | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Kroki.jl b/src/Kroki.jl index 23071a5..9ac7c13 100644 --- a/src/Kroki.jl +++ b/src/Kroki.jl @@ -182,6 +182,11 @@ all these limitations. The union of all values corresponds to all supported Note that SVG output is supported by all diagram types. Those specifically included here are those that _only_ support SVG output. + +Those diagram types that support plain text output, i.e. not just rendering +their `specification`, support both ASCII and Unicode character sets for +rendering. This is expressed using two different `text/plain` MIME types. See +also [`SUPPORTED_TEXT_PLAIN_SHOW_MIME_TYPES`](@ref). """ const LIMITED_DIAGRAM_SUPPORT = Dict{MIME, Tuple{Symbol, Vararg{Symbol}}}( MIME"application/pdf"() => ( @@ -218,8 +223,6 @@ const LIMITED_DIAGRAM_SUPPORT = Dict{MIME, Tuple{Symbol, Vararg{Symbol}}}( ), MIME"image/svg+xml"() => (:bpmn, :bytefield, :excalidraw, :nomnoml, :pikchr, :svgbob, :wavedrom), - # Diagrams that can be rendered to plain text support both ASCII and Unicode - # rendering MIME"text/plain"() => (:c4plantuml, :plantuml, :structurizr), MIME"text/plain; charset=utf-8"() => (:c4plantuml, :plantuml, :structurizr), ) From b0cd390fa98c49fd15d072b5325b679949122378 Mon Sep 17 00:00:00 2001 From: Joris Kraak Date: Tue, 19 Jul 2022 13:57:55 +0200 Subject: [PATCH 03/12] docs: add a support matrix to the `LIMITED_DIAGRAM_SUPPORT` docstring Although this information is also available on Kroki's website, it's convenient to have the information as it is encoded in this library readily available through Julia's help system. --- src/Kroki.jl | 43 ++++++++++++++++++++++++++++++++++++++++--- test/runtests.jl | 31 ++++++++++++++++++++++++++++++- 2 files changed, 70 insertions(+), 4 deletions(-) diff --git a/src/Kroki.jl b/src/Kroki.jl index 9ac7c13..59f1a6a 100644 --- a/src/Kroki.jl +++ b/src/Kroki.jl @@ -175,20 +175,57 @@ render( throw(RenderError(diagram, exception)) end +# Helper constant to type a map from MIME to `Diagram` types more easily +const MIMEToDiagramTypeMap = Dict{MIME, Tuple{Symbol, Vararg{Symbol}}} + +# Helper function to render a support matrix for inclusion in Markdown +# documentation, e.g. `LIMITED_DIAGRAM_SUPPORT`'s docstring +function renderDiagramSupportAsMarkdown(support::MIMEToDiagramTypeMap) + # SVG support should always be included for all diagram types, even if it is + # not in the support map + mime_types = MIME.(sort(unique([string.(keys(support))..., "image/svg+xml"]))) + + header = """ + | | `$(join(mime_types, "` | `"))` | + | --: $(repeat("| :-: ", length(mime_types)))| + """ + + diagram_types = sort(unique(Iterators.flatten(values(support)))) + diagram_types_with_support = map(diagram_types) do diagram_type + [ + diagram_type, + map( + mime -> mime === MIME"image/svg+xml"() || diagram_type ∈ support[mime] ? "✅" : "", + mime_types, + )..., + ] + end + + diagram_support_markdown_rows = + string.("| ", join.(diagram_types_with_support, " | "), " |") + + return header * join(diagram_support_markdown_rows, '\n') +end + """ Some MIME types are not supported by all diagram types, this constant contains all these limitations. The union of all values corresponds to all supported [`Diagram`](@ref) `type`s. -Note that SVG output is supported by all diagram types. Those specifically -included here are those that _only_ support SVG output. +Note that SVG output is supported by all diagram types, as is reflected in the +support matrix below. Only those diagram types that explicitly _only_ support +SVG output are included in this constant. Those diagram types that support plain text output, i.e. not just rendering their `specification`, support both ASCII and Unicode character sets for rendering. This is expressed using two different `text/plain` MIME types. See also [`SUPPORTED_TEXT_PLAIN_SHOW_MIME_TYPES`](@ref). + +# Support Matrix + +$(renderDiagramSupportAsMarkdown(LIMITED_DIAGRAM_SUPPORT)) """ -const LIMITED_DIAGRAM_SUPPORT = Dict{MIME, Tuple{Symbol, Vararg{Symbol}}}( +const LIMITED_DIAGRAM_SUPPORT = MIMEToDiagramTypeMap( MIME"application/pdf"() => ( :blockdiag, :seqdiag, diff --git a/test/runtests.jl b/test/runtests.jl index 4e6cb17..343de36 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -2,7 +2,7 @@ module KrokiTest using Test: @testset, @test, @test_nowarn, @test_throws -using Kroki: Diagram, Kroki, render +using Kroki: Diagram, Kroki, MIMEToDiagramTypeMap, render, renderDiagramSupportAsMarkdown using Kroki.Exceptions: InvalidOutputFormatError, UnsupportedMIMETypeError function testShowMethodRenders( @@ -255,6 +255,35 @@ end end end + @testset "`renderDiagramSupportAsMarkdown`" begin + @testset "includes defined support and `image/svg+xml`" begin + # Strip newlines that are introduced by writing the string markers on + # their own lines + expected_markdown_table = chomp(""" + | | `A` | `B` | `image/svg+xml` | + | --: | :-: | :-: | :-: | + | bar | | ✅ | ✅ | + | foo | ✅ | | ✅ | + """) + + support_definition = MIMEToDiagramTypeMap(MIME"B"() => (:bar,), MIME"A"() => (:foo,)) + + @test renderDiagramSupportAsMarkdown(support_definition) == expected_markdown_table + end + + @testset "does not include `image/svg+xml` again if included" begin + expected_markdown_table = chomp(""" + | | `image/svg+xml` | + | --: | :-: | + | foo | ✅ | + """) + + support_definition = MIMEToDiagramTypeMap(MIME"image/svg+xml"() => (:foo,)) + + @test renderDiagramSupportAsMarkdown(support_definition) == expected_markdown_table + end + end + # Include the test suites for all submodules include.(readdir(joinpath(@__DIR__, "kroki"); join = true)) end From 1b1cbce6b4b9e7ffaa6595cfc4c8c453f85c8259 Mon Sep 17 00:00:00 2001 From: Joris Kraak Date: Tue, 19 Jul 2022 13:58:10 +0200 Subject: [PATCH 04/12] docs(TEXT_PLAIN_SHOW_MIME_TYPE): add additional reference concerning `text/plain` MIME types Ths `LIMITED_DIAGRAM_SUPPORT` lists all the known `text/plain` MIME types and links them to the diagram types that support that form of rendering. `SUPPORTED_TEXT_PLAIN_SHOW_MIME_TYPES` only lists the MIME types themselves. --- src/Kroki.jl | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Kroki.jl b/src/Kroki.jl index 59f1a6a..6c136b9 100644 --- a/src/Kroki.jl +++ b/src/Kroki.jl @@ -317,8 +317,11 @@ for the `text/plain` MIME type. Should be set to a variation of the `text/plain` MIME type. For instance, `text/plain; charset=utf-8` to enable Unicode rendering for certain diagrams, -e.g. PlantUML and Structurizr. Only a select number of variations are -supported, see [`LIMITED_DIAGRAM_SUPPORT`](@ref) for details. +e.g. PlantUML and Structurizr. + +Only a select number of variations are supported, see +[`LIMITED_DIAGRAM_SUPPORT`](@ref) and +[`SUPPORTED_TEXT_PLAIN_SHOW_MIME_TYPES`](@ref) for details. Defaults to `$(TEXT_PLAIN_SHOW_MIME_TYPE[])`. """ From 2840907edca827bad21173f2e9464b3b261f8005 Mon Sep 17 00:00:00 2001 From: Joris Kraak Date: Tue, 19 Jul 2022 13:59:45 +0200 Subject: [PATCH 05/12] docs(SUPPORTED_TEXT_PLAIN_SHOW_MIME_TYPES): list the supported MIME types in the docstring This makes the information more readily available through Julia's help system, instead of requiring people to look up the variable. --- src/Kroki.jl | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Kroki.jl b/src/Kroki.jl index 6c136b9..09619e5 100644 --- a/src/Kroki.jl +++ b/src/Kroki.jl @@ -327,7 +327,10 @@ Defaults to `$(TEXT_PLAIN_SHOW_MIME_TYPE[])`. """ const TEXT_PLAIN_SHOW_MIME_TYPE = Ref{MIME}(MIME"text/plain; charset=utf-8"()) -"All values that can be used to configure [`TEXT_PLAIN_SHOW_MIME_TYPE`](@ref)." +""" +The values that can be used to configure [`TEXT_PLAIN_SHOW_MIME_TYPE`](@ref): +$(join(string.(" * `", SUPPORTED_TEXT_PLAIN_SHOW_MIME_TYPES), "`\n"))` +""" const SUPPORTED_TEXT_PLAIN_SHOW_MIME_TYPES = Set([ mime for mime in keys(Kroki.LIMITED_DIAGRAM_SUPPORT) if startswith(string(mime), "text/plain") From 882c54f92f4cd81fee9b8b2d4d61e28c719bdbbe Mon Sep 17 00:00:00 2001 From: Joris Kraak Date: Wed, 20 Jul 2022 23:41:04 +0200 Subject: [PATCH 06/12] test: move "rendering" tests into dedicated file This declutters the main `runtests` file a bit and makes it easier to test only this particular piece of functionality (and to ignore it while testing other pieces of the package). --- test/kroki/rendering_test.jl | 185 +++++++++++++++++++++++++++++++++++ test/runtests.jl | 180 +--------------------------------- 2 files changed, 187 insertions(+), 178 deletions(-) create mode 100644 test/kroki/rendering_test.jl diff --git a/test/kroki/rendering_test.jl b/test/kroki/rendering_test.jl new file mode 100644 index 0000000..df02732 --- /dev/null +++ b/test/kroki/rendering_test.jl @@ -0,0 +1,185 @@ +module RenderingTest + +using Test: @test, @testset, @test_throws + +using Kroki: Diagram, Kroki, render +using Kroki.Exceptions: InvalidOutputFormatError, UnsupportedMIMETypeError + +function testShowMethodRenders( + diagram::Diagram, + mime_type::MIME, + render_output_format::AbstractString, +) + @test sprint(show, mime_type, diagram) == String(render(diagram, render_output_format)) +end + +@testset "Rendering" begin + @testset "`render`" begin + # This is not an exhaustive list of supported diagram types or output + # formats, but serves to verify generic rendering logic is available for at + # least the specified types and output formats + DIAGRAM_EXAMPLES = [ + :PlantUML => "Kroki -> Julia: Hello", + :Graphviz => "digraph D { Hello->World }", + :ditaa => """ + +--------+ +---------+ + | | | | + | User | <-> | Another | + | | | User | + | | | | + +--------+ +---------+ + """, + # The specification of the diagram type is case-insensitive + :plantuml => "Kroki <- Julia: Hello", + ] + + # The PNG specification defines the structure of PNG files (see + # http://www.libpng.org/pub/png/spec/1.2/PNG-Structure.html). The most + # straight-forward parts to test for are the header and the end-of-file + # marker (i.e. the 'IEND image trailer'), both consisting of 8 bytes + PNG_HEADER = [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a] + PNG_EOF = [0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82] + @testset "$(diagram_format) to PNG" for (diagram_format, specification) in + DIAGRAM_EXAMPLES + rendered = render(Diagram(diagram_format, specification), "png") + + @test rendered[1:length(PNG_HEADER)] == PNG_HEADER + @test rendered[(end - length(PNG_EOF) + 1):end] == PNG_EOF + end + + @testset "$(diagram_format) to SVG" for (diagram_format, specification) in + DIAGRAM_EXAMPLES + rendered = String(render(Diagram(diagram_format, specification), "svg")) + + @test startswith(rendered, "\s?") + end + + # Vega (and Vega Lite) are some of the diagram types with working PDF + # support. They don't match the generic SVG expectations exactly, so they + # are not included in the overall test set of diagrams for SVG and PNG + # above + @testset "Vega Lite to PDF" begin + # The PDF specification defines the structure of PDF files (see + # https://opensource.adobe.com/dc-acrobat-sdk-docs/pdfstandards/PDF32000_2008.pdf). + # The most straight-forward ways to test for a rendered PDF are verifying + # the 'file header' (defined in section 7.5.2) and the 'file trailer' EOF + # marker (defined in section 7.5.5). In plain text these are respectively + # `%PDF-x.y.%` and `%%EOF.`. + # + # Due to the variability of the version numbers in the file header the + # following only checks for `%PDF-` in the rendered result + PDF_HEADER = [0x25, 0x50, 0x44, 0x46, 0x2d] + PDF_EOF = [0x25, 0x25, 0x45, 0x4f, 0x46, 0x0a] + + vegalite_specification = """ + { + "data": { "values": [ {"a": 28}, {"a": 55}, {"a": 23 } ] }, + "mark": "circle", + "encoding": { "y": { "field": "a", "type": "nominal" } } + } + """ + + rendered = render(Diagram(:vegalite, vegalite_specification), "pdf") + + @test rendered[1:length(PDF_HEADER)] == PDF_HEADER + @test rendered[(end - length(PDF_EOF) + 1):end] == PDF_EOF + end + + @testset "takes `options` into account" begin + expected_theme_name = "materia" + options = Dict{String, String}("theme" => expected_theme_name) + diagram = Diagram(:plantuml, "A -> B: C"; options) + + @testset "defaults to `Diagram` options" begin + rendered = String(render(diagram, "svg")) + + @test occursin("!theme $(expected_theme_name)", rendered) + end + + @testset "allows definition at render-time" begin + expected_overridden_theme = "sketchy" + rendered = String( + render(diagram, "svg"; options = Dict("theme" => expected_overridden_theme)), + ) + + @test occursin("!theme $(expected_overridden_theme)", rendered) + end + end + end + + @testset "`Base.show`" begin + # Svgbob diagrams only support SVG output. Any other formats should throw + # `InvalidOutputFormatError`s when called directly. + # + # To prevent compatible `AbstractDisplay`s from trying to render + # incompatible diagram types to unsuppored output formats, `Base.showable` + # should be overridden to indicate the diagram cannot be rendered in the + # specified MIME type + svgbob_diagram = Diagram(:svgbob, "-->[_...__... ]") + @test_throws( + InvalidOutputFormatError, + show(IOBuffer(), MIME"application/pdf"(), svgbob_diagram) + ) + @test !showable("application/pdf", svgbob_diagram) + @test_throws(InvalidOutputFormatError, sprint(show, MIME"image/png"(), svgbob_diagram)) + @test !showable(MIME"image/png"(), svgbob_diagram) + @test_throws( + InvalidOutputFormatError, + show(IOBuffer(), MIME"image/jpeg"(), svgbob_diagram) + ) + @test !showable("image/jpeg", svgbob_diagram) + testShowMethodRenders(svgbob_diagram, MIME"image/svg+xml"(), "svg") + @test !showable("non-existent/mime-type", svgbob_diagram) + + plantuml_diagram = Diagram(:PlantUML, "A -> B: C") + testShowMethodRenders(plantuml_diagram, MIME"image/png"(), "png") + # PlantUML diagrams support SVG, but are not part of the + # `LIMITED_DIAGRAM_SUPPORT` as they support more output formats. + # + # Given that `show` is tested directly, through `testShowMethodRenders`, it + # is necessary to make sure a `showable` method is available to indicate + # SVG is always supported to those enviroments that need to query that + # information + @test showable(MIME"image/svg+xml"(), plantuml_diagram) + testShowMethodRenders(plantuml_diagram, MIME"image/svg+xml"(), "svg") + + @testset "`text/plain`" begin + @testset "without ASCII/Unicode rendering support" begin + # These diagram types should simply display their `specification` + @test sprint(show, MIME"text/plain"(), svgbob_diagram) == + svgbob_diagram.specification + end + + @testset "with ASCII/Unicode rendering support" begin + # PlantUML and Structurizr diagrams can be rendered nicely in + # text/plain based environments. Their exact appearance can be + # controlled using the `TEXT_PLAIN_SHOW_MIME_TYPE` variable by + # indicating adding a `charset` to the MIME type indicating Unicode + # support + original_text_plain_mimetype = Kroki.TEXT_PLAIN_SHOW_MIME_TYPE[] + + Kroki.TEXT_PLAIN_SHOW_MIME_TYPE[] = MIME"text/plain; charset=utf-8"() + testShowMethodRenders(plantuml_diagram, MIME"text/plain"(), "utxt") + + Kroki.TEXT_PLAIN_SHOW_MIME_TYPE[] = MIME"text/plain"() + testShowMethodRenders(plantuml_diagram, MIME"text/plain"(), "txt") + + @testset "generates an error if an invalid `text/plain` MIME type is configured" begin + Kroki.TEXT_PLAIN_SHOW_MIME_TYPE[] = MIME"image/png"() + + @test_throws( + UnsupportedMIMETypeError, + show(IOBuffer(), MIME"text/plain"(), plantuml_diagram) + ) + end + + Kroki.TEXT_PLAIN_SHOW_MIME_TYPE[] = original_text_plain_mimetype + end + end + end +end + +end diff --git a/test/runtests.jl b/test/runtests.jl index 343de36..161c0db 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,17 +1,8 @@ module KrokiTest -using Test: @testset, @test, @test_nowarn, @test_throws +using Test: @testset, @test -using Kroki: Diagram, Kroki, MIMEToDiagramTypeMap, render, renderDiagramSupportAsMarkdown -using Kroki.Exceptions: InvalidOutputFormatError, UnsupportedMIMETypeError - -function testShowMethodRenders( - diagram::Diagram, - mime_type::MIME, - render_output_format::AbstractString, -) - @test sprint(show, mime_type, diagram) == String(render(diagram, render_output_format)) -end +using Kroki: Diagram, MIMEToDiagramTypeMap, renderDiagramSupportAsMarkdown @testset "Kroki" begin @testset "`Diagram` instantiation" begin @@ -88,173 +79,6 @@ end end end - @testset "`render`" begin - # This is not an exhaustive list of supported diagram types or output - # formats, but serves to verify generic rendering logic is available for at - # least the specified types and output formats - DIAGRAM_EXAMPLES = [ - :PlantUML => "Kroki -> Julia: Hello", - :Graphviz => "digraph D { Hello->World }", - :ditaa => """ - +--------+ +---------+ - | | | | - | User | <-> | Another | - | | | User | - | | | | - +--------+ +---------+ - """, - # The specification of the diagram type is case-insensitive - :plantuml => "Kroki <- Julia: Hello", - ] - - # The PNG specification defines the structure of PNG files (see - # http://www.libpng.org/pub/png/spec/1.2/PNG-Structure.html). The most - # straight-forward parts to test for are the header and the end-of-file - # marker (i.e. the 'IEND image trailer'), both consisting of 8 bytes - PNG_HEADER = [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a] - PNG_EOF = [0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82] - @testset "$(diagram_format) to PNG" for (diagram_format, specification) in - DIAGRAM_EXAMPLES - rendered = render(Diagram(diagram_format, specification), "png") - - @test rendered[1:length(PNG_HEADER)] == PNG_HEADER - @test rendered[(end - length(PNG_EOF) + 1):end] == PNG_EOF - end - - @testset "$(diagram_format) to SVG" for (diagram_format, specification) in - DIAGRAM_EXAMPLES - rendered = String(render(Diagram(diagram_format, specification), "svg")) - - @test startswith(rendered, "\s?") - end - - # Vega (and Vega Lite) are some of the diagram types with working PDF - # support. They don't match the generic SVG expectations exactly, so they - # are not included in the overall test set of diagrams for SVG and PNG - # above - @testset "Vega Lite to PDF" begin - # The PDF specification defines the structure of PDF files (see - # https://opensource.adobe.com/dc-acrobat-sdk-docs/pdfstandards/PDF32000_2008.pdf). - # The most straight-forward ways to test for a rendered PDF are verifying - # the 'file header' (defined in section 7.5.2) and the 'file trailer' EOF - # marker (defined in section 7.5.5). In plain text these are respectively - # `%PDF-x.y.%` and `%%EOF.`. - # - # Due to the variability of the version numbers in the file header the - # following only checks for `%PDF-` in the rendered result - PDF_HEADER = [0x25, 0x50, 0x44, 0x46, 0x2d] - PDF_EOF = [0x25, 0x25, 0x45, 0x4f, 0x46, 0x0a] - - vegalite_specification = """ - { - "data": { "values": [ {"a": 28}, {"a": 55}, {"a": 23 } ] }, - "mark": "circle", - "encoding": { "y": { "field": "a", "type": "nominal" } } - } - """ - - rendered = render(Diagram(:vegalite, vegalite_specification), "pdf") - - @test rendered[1:length(PDF_HEADER)] == PDF_HEADER - @test rendered[(end - length(PDF_EOF) + 1):end] == PDF_EOF - end - - @testset "takes `options` into account" begin - expected_theme_name = "materia" - options = Dict{String, String}("theme" => expected_theme_name) - diagram = Diagram(:plantuml, "A -> B: C"; options) - - @testset "defaults to `Diagram` options" begin - rendered = String(render(diagram, "svg")) - - @test occursin("!theme $(expected_theme_name)", rendered) - end - - @testset "allows definition at render-time" begin - expected_overridden_theme = "sketchy" - rendered = String( - render(diagram, "svg"; options = Dict("theme" => expected_overridden_theme)), - ) - - @test occursin("!theme $(expected_overridden_theme)", rendered) - end - end - end - - @testset "`Base.show`" begin - # Svgbob diagrams only support SVG output. Any other formats should throw - # `InvalidOutputFormatError`s when called directly. - # - # To prevent compatible `AbstractDisplay`s from trying to render - # incompatible diagram types to unsuppored output formats, `Base.showable` - # should be overridden to indicate the diagram cannot be rendered in the - # specified MIME type - svgbob_diagram = Diagram(:svgbob, "-->[_...__... ]") - @test_throws( - InvalidOutputFormatError, - show(IOBuffer(), MIME"application/pdf"(), svgbob_diagram) - ) - @test !showable("application/pdf", svgbob_diagram) - @test_throws(InvalidOutputFormatError, sprint(show, MIME"image/png"(), svgbob_diagram)) - @test !showable(MIME"image/png"(), svgbob_diagram) - @test_throws( - InvalidOutputFormatError, - show(IOBuffer(), MIME"image/jpeg"(), svgbob_diagram) - ) - @test !showable("image/jpeg", svgbob_diagram) - testShowMethodRenders(svgbob_diagram, MIME"image/svg+xml"(), "svg") - @test !showable("non-existent/mime-type", svgbob_diagram) - - plantuml_diagram = Diagram(:PlantUML, "A -> B: C") - testShowMethodRenders(plantuml_diagram, MIME"image/png"(), "png") - # PlantUML diagrams support SVG, but are not part of the - # `LIMITED_DIAGRAM_SUPPORT` as they support more output formats. - # - # Given that `show` is tested directly, through `testShowMethodRenders`, it - # is necessary to make sure a `showable` method is available to indicate - # SVG is always supported to those enviroments that need to query that - # information - @test showable(MIME"image/svg+xml"(), plantuml_diagram) - testShowMethodRenders(plantuml_diagram, MIME"image/svg+xml"(), "svg") - - @testset "`text/plain`" begin - @testset "without ASCII/Unicode rendering support" begin - # These diagram types should simply display their `specification` - @test sprint(show, MIME"text/plain"(), svgbob_diagram) == - svgbob_diagram.specification - end - - @testset "with ASCII/Unicode rendering support" begin - # PlantUML and Structurizr diagrams can be rendered nicely in - # text/plain based environments. Their exact appearance can be - # controlled using the `TEXT_PLAIN_SHOW_MIME_TYPE` variable by - # indicating adding a `charset` to the MIME type indicating Unicode - # support - original_text_plain_mimetype = Kroki.TEXT_PLAIN_SHOW_MIME_TYPE[] - - Kroki.TEXT_PLAIN_SHOW_MIME_TYPE[] = MIME"text/plain; charset=utf-8"() - testShowMethodRenders(plantuml_diagram, MIME"text/plain"(), "utxt") - - Kroki.TEXT_PLAIN_SHOW_MIME_TYPE[] = MIME"text/plain"() - testShowMethodRenders(plantuml_diagram, MIME"text/plain"(), "txt") - - @testset "generates an error if an invalid `text/plain` MIME type is configured" begin - Kroki.TEXT_PLAIN_SHOW_MIME_TYPE[] = MIME"image/png"() - - @test_throws( - UnsupportedMIMETypeError, - show(IOBuffer(), MIME"text/plain"(), plantuml_diagram) - ) - end - - Kroki.TEXT_PLAIN_SHOW_MIME_TYPE[] = original_text_plain_mimetype - end - end - end - @testset "`renderDiagramSupportAsMarkdown`" begin @testset "includes defined support and `image/svg+xml`" begin # Strip newlines that are introduced by writing the string markers on From de6e0d37ca90729d3d3a4952a76de135c1b52393 Mon Sep 17 00:00:00 2001 From: Joris Kraak Date: Wed, 20 Jul 2022 23:45:02 +0200 Subject: [PATCH 07/12] test: move "`Diagram` instantiation" tests into dedicated file This declutters the main `runtests` file a bit and makes it easier to test only this particular piece of functionality (and to ignore it while testing other pieces of the package). --- test/kroki/diagram_instantiation_test.jl | 80 ++++++++++++++++++++++++ test/runtests.jl | 78 +---------------------- 2 files changed, 82 insertions(+), 76 deletions(-) create mode 100644 test/kroki/diagram_instantiation_test.jl diff --git a/test/kroki/diagram_instantiation_test.jl b/test/kroki/diagram_instantiation_test.jl new file mode 100644 index 0000000..6357b83 --- /dev/null +++ b/test/kroki/diagram_instantiation_test.jl @@ -0,0 +1,80 @@ +module DiagramInstantiationTest + +using Test: @test, @testset + +using Kroki: Diagram + +@testset "`Diagram` instantiation" begin + @testset "through keyword arguments" begin + expected_specification = "[...]--[...]" + expected_type = :svgbob + + diagram = Diagram(specification = expected_specification, type = expected_type) + + @test diagram.specification === expected_specification + @test diagram.type === expected_type + + @testset "optionally accepts `options`" begin + expected_options = Dict("key" => "value") + + diagram = Diagram( + options = expected_options, + specification = expected_specification, + type = expected_type, + ) + + @test diagram.options === expected_options + @test diagram.specification === expected_specification + @test diagram.type === expected_type + end + end + + @testset "through `type` and `specification` positional arguments" begin + expected_specification = "A -> B: C" + expected_type = :plantuml + + diagram = Diagram(expected_type, expected_specification) + + @test diagram.specification === expected_specification + @test diagram.type === expected_type + + @testset "optionally accepts `options`" begin + expected_options = Dict("foo" => "bar") + + diagram = Diagram(expected_type, expected_specification; options = expected_options) + + @test diagram.options === expected_options + @test diagram.specification === expected_specification + @test diagram.type === expected_type + end + end + + @testset "through `type` positional argument with keyword arguments" begin + @testset "providing the `path` keyword argument loads a file as the `specification" begin + diagram_path = joinpath(@__DIR__, "..", "assets", "plantuml-example.puml") + expected_specification = read(diagram_path, String) + + diagram = Diagram(:plantuml; path = diagram_path) + + @test diagram.specification === expected_specification + end + + @testset "optionally accepts `options`" begin + expected_options = Dict("key" => "value") + + diagram = Diagram(:plantuml; options = expected_options, specification = "A -> B: C") + + @test diagram.options === expected_options + end + + @testset "providing the `specification` keyword argument stores it" begin + expected_specification = "A -> B: C" + + diagram = Diagram(:plantuml; specification = expected_specification) + + @test diagram.specification === expected_specification + end + end +end + +end diff --git a/test/runtests.jl b/test/runtests.jl index 161c0db..fd2a295 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,84 +1,10 @@ module KrokiTest -using Test: @testset, @test +using Test: @test, @testset -using Kroki: Diagram, MIMEToDiagramTypeMap, renderDiagramSupportAsMarkdown +using Kroki: MIMEToDiagramTypeMap, renderDiagramSupportAsMarkdown @testset "Kroki" begin - @testset "`Diagram` instantiation" begin - @testset "through keyword arguments" begin - expected_specification = "[...]--[...]" - expected_type = :svgbob - - diagram = Diagram(specification = expected_specification, type = expected_type) - - @test diagram.specification === expected_specification - @test diagram.type === expected_type - - @testset "optionally accepts `options`" begin - expected_options = Dict("key" => "value") - - diagram = Diagram( - options = expected_options, - specification = expected_specification, - type = expected_type, - ) - - @test diagram.options === expected_options - @test diagram.specification === expected_specification - @test diagram.type === expected_type - end - end - - @testset "through `type` and `specification` positional arguments" begin - expected_specification = "A -> B: C" - expected_type = :plantuml - - diagram = Diagram(expected_type, expected_specification) - - @test diagram.specification === expected_specification - @test diagram.type === expected_type - - @testset "optionally accepts `options`" begin - expected_options = Dict("foo" => "bar") - - diagram = Diagram(expected_type, expected_specification; options = expected_options) - - @test diagram.options === expected_options - @test diagram.specification === expected_specification - @test diagram.type === expected_type - end - end - - @testset "through `type` positional argument with keyword arguments" begin - @testset "providing the `path` keyword argument loads a file as the `specification" begin - diagram_path = joinpath(@__DIR__, "assets", "plantuml-example.puml") - expected_specification = read(diagram_path, String) - - diagram = Diagram(:plantuml; path = diagram_path) - - @test diagram.specification === expected_specification - end - - @testset "optionally accepts `options`" begin - expected_options = Dict("key" => "value") - - diagram = - Diagram(:plantuml; options = expected_options, specification = "A -> B: C") - - @test diagram.options === expected_options - end - - @testset "providing the `specification` keyword argument stores it" begin - expected_specification = "A -> B: C" - - diagram = Diagram(:plantuml; specification = expected_specification) - - @test diagram.specification === expected_specification - end - end - end - @testset "`renderDiagramSupportAsMarkdown`" begin @testset "includes defined support and `image/svg+xml`" begin # Strip newlines that are introduced by writing the string markers on From eb94fb0c3127bdbb256fbc90058a033c6122a01f Mon Sep 17 00:00:00 2001 From: Joris Kraak Date: Thu, 21 Jul 2022 00:08:35 +0200 Subject: [PATCH 08/12] feat(string-literal): show 'friendly' names in docstrings Instead of simply reusing the symbols used to track the different types of diagrams, it is nicer if the documentation refers to the different diagram types by their actual names. The intention is to use this information elsewhere as well. --- src/kroki/string_literals.jl | 72 ++++++++++++++++++++++-------------- 1 file changed, 45 insertions(+), 27 deletions(-) diff --git a/src/kroki/string_literals.jl b/src/kroki/string_literals.jl index 991e08f..1df135f 100644 --- a/src/kroki/string_literals.jl +++ b/src/kroki/string_literals.jl @@ -68,33 +68,47 @@ function shouldInterpolate(stream::IO) return iseven(n_escape_characters) end +"A container to associate metadata with diagram type, e.g. for documentation." +struct DiagramTypeMetadata + "A more readable name for the diagram type, if applicable." + name::String + + "The URL to the website/documentation of the diagram type." + url::String +end + # Links to the main documentation for each diagram type for inclusion in the # string literal docstrings -DIAGRAM_DOCUMENTATION_URLS = Dict{Symbol, String}( - :actdiag => "http://blockdiag.com/en/actdiag", - :blockdiag => "http://blockdiag.com/en/blockdiag", - :bpmn => "https://www.omg.org/spec/BPMN", - :bytefield => "https://bytefield-svg.deepsymmetry.org", - :c4plantuml => "https://github.com/plantuml-stdlib/C4-PlantUML", - :diagramsnet => "https://diagrams.net", - :ditaa => "http://ditaa.sourceforge.net", - :erd => "https://github.com/BurntSushi/erd", - :excalidraw => "https://excalidraw.com", - :graphviz => "https://graphviz.org", - :mermaid => "https://mermaid-js.github.io", - :nomnoml => "https://www.nomnoml.com", - :nwdiag => "http://blockdiag.com/en/nwdiag", - :packetdiag => "http://blockdiag.com/en/nwdiag", - :pikchr => "https://pikchr.org", - :plantuml => "https://plantuml.com", - :rackdiag => "http://blockdiag.com/en/nwdiag", - :seqdiag => "http://blockdiag.com/en/seqdiag", - :structurizr => "https://structurizr.com", - :svgbob => "https://ivanceras.github.io/content/Svgbob.html", - :umlet => "https://github.com/umlet/umlet", - :vega => "https://vega.github.io/vega", - :vegalite => "https://vega.github.io/vega-lite", - :wavedrom => "https://wavedrom.com", +DIAGRAM_TYPE_METADATA = Dict{Symbol, DiagramTypeMetadata}( + :actdiag => DiagramTypeMetadata("actdiag", "http://blockdiag.com/en/actdiag"), + :blockdiag => DiagramTypeMetadata("blockdiag", "http://blockdiag.com/en/blockdiag"), + :bpmn => DiagramTypeMetadata("BPMN", "https://www.omg.org/spec/BPMN"), + :bytefield => + DiagramTypeMetadata("Byte Field", "https://bytefield-svg.deepsymmetry.org"), + :c4plantuml => DiagramTypeMetadata( + "C4 with PlantUML", + "https://github.com/plantuml-stdlib/C4-PlantUML", + ), + :diagramsnet => DiagramTypeMetadata("diagrams.net", "https://diagrams.net"), + :ditaa => DiagramTypeMetadata("ditaa", "http://ditaa.sourceforge.net"), + :erd => DiagramTypeMetadata("erd", "https://github.com/BurntSushi/erd"), + :excalidraw => DiagramTypeMetadata("Excalidraw", "https://excalidraw.com"), + :graphviz => DiagramTypeMetadata("Graphviz", "https://graphviz.org"), + :mermaid => DiagramTypeMetadata("Mermaid", "https://mermaid-js.github.io"), + :nomnoml => DiagramTypeMetadata("nomnoml", "https://www.nomnoml.com"), + :nwdiag => DiagramTypeMetadata("nwdiag", "http://blockdiag.com/en/nwdiag"), + :packetdiag => DiagramTypeMetadata("packetdiag", "http://blockdiag.com/en/nwdiag"), + :pikchr => DiagramTypeMetadata("Pikchr", "https://pikchr.org"), + :plantuml => DiagramTypeMetadata("PlantUML", "https://plantuml.com"), + :rackdiag => DiagramTypeMetadata("rackdiag", "http://blockdiag.com/en/nwdiag"), + :seqdiag => DiagramTypeMetadata("seqdiag", "http://blockdiag.com/en/seqdiag"), + :structurizr => DiagramTypeMetadata("Structurizr", "https://structurizr.com"), + :svgbob => + DiagramTypeMetadata("Svgbob", "https://ivanceras.github.io/content/Svgbob.html"), + :umlet => DiagramTypeMetadata("UMLet", "https://github.com/umlet/umlet"), + :vega => DiagramTypeMetadata("Vega", "https://vega.github.io/vega"), + :vegalite => DiagramTypeMetadata("Vega-Lite", "https://vega.github.io/vega-lite"), + :wavedrom => DiagramTypeMetadata("WaveDrom", "https://wavedrom.com"), ) # The union of the values of `LIMITED_DIAGRAM_SUPPORT` corresponds to all @@ -109,9 +123,13 @@ for diagram_type in unique(Iterators.flatten(values(LIMITED_DIAGRAM_SUPPORT))) # variable. First for `@eval`, then for the macro itself macro_diagram_type = QuoteNode(QuoteNode(diagram_type)) - diagram_url = get(DIAGRAM_DOCUMENTATION_URLS, diagram_type, "https://kroki.io/#support") + diagram_type_metadata = get( + DIAGRAM_TYPE_METADATA, + diagram_type, + DiagramTypeMetadata("$(diagram_type)", "https://kroki.io/#support"), + ) - docstring = "String literal for instantiating [`$diagram_type`]($diagram_url) [`Diagram`](@ref)s." + docstring = "String literal for instantiating [`$(diagram_type_metadata.name)`]($(diagram_type_metadata.url)) [`Diagram`](@ref)s." @eval begin export $macro_signature From fcf9c9eafd229abb6d1505753cc4d5a9f54f5124 Mon Sep 17 00:00:00 2001 From: Joris Kraak Date: Fri, 22 Jul 2022 22:55:27 +0200 Subject: [PATCH 09/12] refactor: move diagram type metadata facilities into main module This metadata has more uses than just supporting the docstrings of the string literals, e.g. in the `LIMITED_DIAGRAM_SUPPORT` table. Therefore it makes sense to put it in a more centralized location and formalize retrieval of the metadata more. --- docs/src/api.md | 3 ++ src/Kroki.jl | 59 ++++++++++++++++++++++++++++++++++++ src/kroki/string_literals.jl | 51 ++----------------------------- 3 files changed, 64 insertions(+), 49 deletions(-) diff --git a/docs/src/api.md b/docs/src/api.md index 9d9e73c..c7df6bb 100644 --- a/docs/src/api.md +++ b/docs/src/api.md @@ -36,9 +36,12 @@ Modules = [ Kroki.StringLiterals ] ## Private ```@docs +DiagramTypeMetadata +DIAGRAM_TYPE_METADATA LIMITED_DIAGRAM_SUPPORT MIME_TO_RENDER_ARGUMENT_MAP UriSafeBase64Payload +getDiagramTypeMetadata ``` ### Documentation diff --git a/src/Kroki.jl b/src/Kroki.jl index 09619e5..30a742e 100644 --- a/src/Kroki.jl +++ b/src/Kroki.jl @@ -207,6 +207,65 @@ function renderDiagramSupportAsMarkdown(support::MIMEToDiagramTypeMap) return header * join(diagram_support_markdown_rows, '\n') end +""" +A container to associate metadata with a specific diagram type, e.g. for +documentation purposes. +""" +struct DiagramTypeMetadata + "A more readable name for the diagram type, if applicable." + name::String + + "The URL to the website/documentation of the diagram type." + url::String +end + +""" +An overview of metadata for the different [`Diagram`](@ref) `type`s that can be +rendered, e.g. links to the main documentation, friendly names, etc. +""" +DIAGRAM_TYPE_METADATA = Dict{Symbol, DiagramTypeMetadata}( + :actdiag => DiagramTypeMetadata("actdiag", "http://blockdiag.com/en/actdiag"), + :blockdiag => DiagramTypeMetadata("blockdiag", "http://blockdiag.com/en/blockdiag"), + :bpmn => DiagramTypeMetadata("BPMN", "https://www.omg.org/spec/BPMN"), + :bytefield => + DiagramTypeMetadata("Byte Field", "https://bytefield-svg.deepsymmetry.org"), + :c4plantuml => DiagramTypeMetadata( + "C4 with PlantUML", + "https://github.com/plantuml-stdlib/C4-PlantUML", + ), + :diagramsnet => DiagramTypeMetadata("diagrams.net", "https://diagrams.net"), + :ditaa => DiagramTypeMetadata("ditaa", "http://ditaa.sourceforge.net"), + :erd => DiagramTypeMetadata("erd", "https://github.com/BurntSushi/erd"), + :excalidraw => DiagramTypeMetadata("Excalidraw", "https://excalidraw.com"), + :graphviz => DiagramTypeMetadata("Graphviz", "https://graphviz.org"), + :mermaid => DiagramTypeMetadata("Mermaid", "https://mermaid-js.github.io"), + :nomnoml => DiagramTypeMetadata("nomnoml", "https://www.nomnoml.com"), + :nwdiag => DiagramTypeMetadata("nwdiag", "http://blockdiag.com/en/nwdiag"), + :packetdiag => DiagramTypeMetadata("packetdiag", "http://blockdiag.com/en/nwdiag"), + :pikchr => DiagramTypeMetadata("Pikchr", "https://pikchr.org"), + :plantuml => DiagramTypeMetadata("PlantUML", "https://plantuml.com"), + :rackdiag => DiagramTypeMetadata("rackdiag", "http://blockdiag.com/en/nwdiag"), + :seqdiag => DiagramTypeMetadata("seqdiag", "http://blockdiag.com/en/seqdiag"), + :structurizr => DiagramTypeMetadata("Structurizr", "https://structurizr.com"), + :svgbob => + DiagramTypeMetadata("Svgbob", "https://ivanceras.github.io/content/Svgbob.html"), + :umlet => DiagramTypeMetadata("UMLet", "https://github.com/umlet/umlet"), + :vega => DiagramTypeMetadata("Vega", "https://vega.github.io/vega"), + :vegalite => DiagramTypeMetadata("Vega-Lite", "https://vega.github.io/vega-lite"), + :wavedrom => DiagramTypeMetadata("WaveDrom", "https://wavedrom.com"), +) + +""" +Retrieves the metadata for a given `diagram_type` from +[`DIAGRAM_TYPE_METADATA`](@ref), with a fallback to a generic +[`DiagramTypeMetadata`](@ref). +""" +getDiagramTypeMetadata(diagram_type::Symbol)::DiagramTypeMetadata = get( + DIAGRAM_TYPE_METADATA, + diagram_type, + DiagramTypeMetadata("$(diagram_type)", "https://kroki.io/#support"), +) + """ Some MIME types are not supported by all diagram types, this constant contains all these limitations. The union of all values corresponds to all supported diff --git a/src/kroki/string_literals.jl b/src/kroki/string_literals.jl index 1df135f..5e08d57 100644 --- a/src/kroki/string_literals.jl +++ b/src/kroki/string_literals.jl @@ -1,6 +1,6 @@ module StringLiterals -using ..Kroki: Diagram, LIMITED_DIAGRAM_SUPPORT +using ..Kroki: Diagram, LIMITED_DIAGRAM_SUPPORT, getDiagramTypeMetadata # Helper function implementing string interpolation to be used in conjunction # with macros defining diagram specification string literals, as they do not @@ -68,49 +68,6 @@ function shouldInterpolate(stream::IO) return iseven(n_escape_characters) end -"A container to associate metadata with diagram type, e.g. for documentation." -struct DiagramTypeMetadata - "A more readable name for the diagram type, if applicable." - name::String - - "The URL to the website/documentation of the diagram type." - url::String -end - -# Links to the main documentation for each diagram type for inclusion in the -# string literal docstrings -DIAGRAM_TYPE_METADATA = Dict{Symbol, DiagramTypeMetadata}( - :actdiag => DiagramTypeMetadata("actdiag", "http://blockdiag.com/en/actdiag"), - :blockdiag => DiagramTypeMetadata("blockdiag", "http://blockdiag.com/en/blockdiag"), - :bpmn => DiagramTypeMetadata("BPMN", "https://www.omg.org/spec/BPMN"), - :bytefield => - DiagramTypeMetadata("Byte Field", "https://bytefield-svg.deepsymmetry.org"), - :c4plantuml => DiagramTypeMetadata( - "C4 with PlantUML", - "https://github.com/plantuml-stdlib/C4-PlantUML", - ), - :diagramsnet => DiagramTypeMetadata("diagrams.net", "https://diagrams.net"), - :ditaa => DiagramTypeMetadata("ditaa", "http://ditaa.sourceforge.net"), - :erd => DiagramTypeMetadata("erd", "https://github.com/BurntSushi/erd"), - :excalidraw => DiagramTypeMetadata("Excalidraw", "https://excalidraw.com"), - :graphviz => DiagramTypeMetadata("Graphviz", "https://graphviz.org"), - :mermaid => DiagramTypeMetadata("Mermaid", "https://mermaid-js.github.io"), - :nomnoml => DiagramTypeMetadata("nomnoml", "https://www.nomnoml.com"), - :nwdiag => DiagramTypeMetadata("nwdiag", "http://blockdiag.com/en/nwdiag"), - :packetdiag => DiagramTypeMetadata("packetdiag", "http://blockdiag.com/en/nwdiag"), - :pikchr => DiagramTypeMetadata("Pikchr", "https://pikchr.org"), - :plantuml => DiagramTypeMetadata("PlantUML", "https://plantuml.com"), - :rackdiag => DiagramTypeMetadata("rackdiag", "http://blockdiag.com/en/nwdiag"), - :seqdiag => DiagramTypeMetadata("seqdiag", "http://blockdiag.com/en/seqdiag"), - :structurizr => DiagramTypeMetadata("Structurizr", "https://structurizr.com"), - :svgbob => - DiagramTypeMetadata("Svgbob", "https://ivanceras.github.io/content/Svgbob.html"), - :umlet => DiagramTypeMetadata("UMLet", "https://github.com/umlet/umlet"), - :vega => DiagramTypeMetadata("Vega", "https://vega.github.io/vega"), - :vegalite => DiagramTypeMetadata("Vega-Lite", "https://vega.github.io/vega-lite"), - :wavedrom => DiagramTypeMetadata("WaveDrom", "https://wavedrom.com"), -) - # The union of the values of `LIMITED_DIAGRAM_SUPPORT` corresponds to all # supported `Diagram` types. The `values` call returns an array of arrays that # may contain duplicate diagram types due to some types supporting rendering to @@ -123,11 +80,7 @@ for diagram_type in unique(Iterators.flatten(values(LIMITED_DIAGRAM_SUPPORT))) # variable. First for `@eval`, then for the macro itself macro_diagram_type = QuoteNode(QuoteNode(diagram_type)) - diagram_type_metadata = get( - DIAGRAM_TYPE_METADATA, - diagram_type, - DiagramTypeMetadata("$(diagram_type)", "https://kroki.io/#support"), - ) + diagram_type_metadata = getDiagramTypeMetadata(diagram_type) docstring = "String literal for instantiating [`$(diagram_type_metadata.name)`]($(diagram_type_metadata.url)) [`Diagram`](@ref)s." From 8451329beda5c8a5da69e75739838179434547dc Mon Sep 17 00:00:00 2001 From: Joris Kraak Date: Fri, 22 Jul 2022 23:18:18 +0200 Subject: [PATCH 10/12] docs: improve headers in diagram type support matrix This uses friendlier names if they're available and ensures links to documentation are easily accessible. --- src/Kroki.jl | 6 ++++-- test/runtests.jl | 18 ++++++++++++------ 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/Kroki.jl b/src/Kroki.jl index 30a742e..c8cdd90 100644 --- a/src/Kroki.jl +++ b/src/Kroki.jl @@ -192,8 +192,10 @@ function renderDiagramSupportAsMarkdown(support::MIMEToDiagramTypeMap) diagram_types = sort(unique(Iterators.flatten(values(support)))) diagram_types_with_support = map(diagram_types) do diagram_type - [ - diagram_type, + diagram_type_metadata = getDiagramTypeMetadata(diagram_type) + + return [ + "[$(diagram_type_metadata.name)]($(diagram_type_metadata.url))", map( mime -> mime === MIME"image/svg+xml"() || diagram_type ∈ support[mime] ? "✅" : "", mime_types, diff --git a/test/runtests.jl b/test/runtests.jl index fd2a295..bef5f93 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -2,33 +2,39 @@ module KrokiTest using Test: @test, @testset -using Kroki: MIMEToDiagramTypeMap, renderDiagramSupportAsMarkdown +using Kroki: MIMEToDiagramTypeMap, getDiagramTypeMetadata, renderDiagramSupportAsMarkdown @testset "Kroki" begin @testset "`renderDiagramSupportAsMarkdown`" begin @testset "includes defined support and `image/svg+xml`" begin + plantuml_metadata = getDiagramTypeMetadata(:plantuml) + svgbob_metadata = getDiagramTypeMetadata(:svgbob) + # Strip newlines that are introduced by writing the string markers on # their own lines expected_markdown_table = chomp(""" | | `A` | `B` | `image/svg+xml` | | --: | :-: | :-: | :-: | - | bar | | ✅ | ✅ | - | foo | ✅ | | ✅ | + | [$(plantuml_metadata.name)]($(plantuml_metadata.url)) | | ✅ | ✅ | + | [$(svgbob_metadata.name)]($(svgbob_metadata.url)) | ✅ | | ✅ | """) - support_definition = MIMEToDiagramTypeMap(MIME"B"() => (:bar,), MIME"A"() => (:foo,)) + support_definition = + MIMEToDiagramTypeMap(MIME"B"() => (:plantuml,), MIME"A"() => (:svgbob,)) @test renderDiagramSupportAsMarkdown(support_definition) == expected_markdown_table end @testset "does not include `image/svg+xml` again if included" begin + vegalite_metadata = getDiagramTypeMetadata(:vegalite) + expected_markdown_table = chomp(""" | | `image/svg+xml` | | --: | :-: | - | foo | ✅ | + | [$(vegalite_metadata.name)]($(vegalite_metadata.url)) | ✅ | """) - support_definition = MIMEToDiagramTypeMap(MIME"image/svg+xml"() => (:foo,)) + support_definition = MIMEToDiagramTypeMap(MIME"image/svg+xml"() => (:vegalite,)) @test renderDiagramSupportAsMarkdown(support_definition) == expected_markdown_table end From 1d76f2e90642c07fe95c79f02f9c528c348e1bf3 Mon Sep 17 00:00:00 2001 From: Joris Kraak Date: Fri, 22 Jul 2022 23:58:50 +0200 Subject: [PATCH 11/12] docs: add diagram type support table The information in this table is mostly a mirror of the information available on Kroki's website, and the docstring of `LIMITED_DIAGRAM_SUPPORT`. Having this information visible directly on the landing page of the documentation provides a convenient reference for anyone skimming the documentation. --- docs/src/index.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/docs/src/index.md b/docs/src/index.md index 3d12bfd..0b1098a 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -63,6 +63,26 @@ Kroki.Service.start!), [`status`](@ref Kroki.Service.status), [`stop!`](@ref Kroki.Service.stop!), etc. are included to help with the self-hosting scenario, provided [Docker Compose](https://docs.docker.com/compose) is available. +## [Supported Diagram Types](@id diagram-support) + +The table below provides an overview of the different diagram types this +package supports, with links to their documentation, and the output formats +they can be rendered to. + +```@eval +using Kroki, Markdown +Markdown.parse(Kroki.renderDiagramSupportAsMarkdown(Kroki.LIMITED_DIAGRAM_SUPPORT)) +``` + +The information in this table should correspond to the one on [Kroki's +website](https://kroki.io/#support), but is directly derived from the support +as it is encoded in [this +package](https://bauglir.github.io/Kroki.jl/stable/api/#Kroki.LIMITED_DIAGRAM_SUPPORT). +Given that this information is a mirror of the information available on +[Kroki's website](https://kroki.io/#support), it may not be entirely accurate +with regards to supported output formats. Support for output formats needs to +be addressed within the Kroki service. + ## Contents ```@contents From c92dd036a4eac63df60a03c35f81cd5de1071d24 Mon Sep 17 00:00:00 2001 From: Joris Kraak Date: Sat, 23 Jul 2022 00:09:17 +0200 Subject: [PATCH 12/12] docs: refer to "local" support table throughout the codebase This makes adding caveats, e.g. with regards to supported output formats, easier by having one central location to document them before referring to Kroki's website. --- README.md | 6 +++--- docs/src/examples.md | 4 ++-- docs/src/index.md | 9 ++++----- src/Kroki.jl | 11 +++++++---- 4 files changed, 16 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 994abea..804f9fa 100644 --- a/README.md +++ b/README.md @@ -13,9 +13,9 @@ Enables a wide array of textual diagramming tools, such as [Graphviz](https://www.graphviz.org), [Mermaid](https://mermaidjs.github.io), [PlantUML](https://plantuml.com), [svgbob](https://ivanceras.github.io/content/Svgbob.html) and [many -more](https://kroki.io/#support) within Julia through the -[Kroki](https://kroki.io) service. It works in environments capable of -rendering images: +more](https://bauglir.github.io/Kroki.jl/stable/#diagram-support) within Julia +through the [Kroki](https://kroki.io) service. It works in environments capable +of rendering images: ![Kroki Pluto Demo](./docs/src/kroki-demo-pluto.gif) diff --git a/docs/src/examples.md b/docs/src/examples.md index 7c56e8c..0ab234e 100644 --- a/docs/src/examples.md +++ b/docs/src/examples.md @@ -239,8 +239,8 @@ on a [`Diagram`](@ref), specifying the desired output format. !!! warning "Output format support" All diagram types support SVG output, other supported output formats vary - per diagram type. See [Kroki's website](https://kroki.io/#support) for a, - not entirely accurate, overview. + per diagram type. See [the support table](@ref diagram-support) for an + overview. ```@example diagrams mermaid_diagram = mermaid""" diff --git a/docs/src/index.md b/docs/src/index.md index 0b1098a..b68d139 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -3,9 +3,8 @@ Enables a wide array of textual diagramming tools, such as [Graphviz](https://www.graphviz.org), [Mermaid](https://mermaidjs.github.io), [PlantUML](https://plantuml.com), -[svgbob](https://ivanceras.github.io/content/Svgbob.html) and [many -more](https://kroki.io/#support) within Julia through the -[Kroki](https://kroki.io) service. +[svgbob](https://ivanceras.github.io/content/Svgbob.html) and [many more](@ref +diagram-support) within Julia through the [Kroki](https://kroki.io) service. ![Kroki REPL Demo](./kroki-demo-repl.gif) @@ -80,8 +79,8 @@ as it is encoded in [this package](https://bauglir.github.io/Kroki.jl/stable/api/#Kroki.LIMITED_DIAGRAM_SUPPORT). Given that this information is a mirror of the information available on [Kroki's website](https://kroki.io/#support), it may not be entirely accurate -with regards to supported output formats. Support for output formats needs to -be addressed within the Kroki service. +with regards to actually supported output formats. Support for output formats +needs to be addressed within the Kroki service. ## Contents diff --git a/src/Kroki.jl b/src/Kroki.jl index c8cdd90..b1c6f06 100644 --- a/src/Kroki.jl +++ b/src/Kroki.jl @@ -141,9 +141,9 @@ a known type of error occurs. Other errors (e.g. `HTTP.ExceptionRequest.StatusError` for connection errors) are propagated if they occur. -_SVG output is supported for all [`Diagram`](@ref) types_. See [Kroki's -website](https://kroki.io/#support) for an overview of other supported output -formats per diagram type. Note that this list may not be entirely up-to-date. +_SVG output is supported for all [`Diagram`](@ref) types_. See the [support +table](@ref diagram-support) for an overview of other supported output formats +per diagram type. """ render( diagram::Diagram, @@ -265,7 +265,10 @@ Retrieves the metadata for a given `diagram_type` from getDiagramTypeMetadata(diagram_type::Symbol)::DiagramTypeMetadata = get( DIAGRAM_TYPE_METADATA, diagram_type, - DiagramTypeMetadata("$(diagram_type)", "https://kroki.io/#support"), + DiagramTypeMetadata( + "$(diagram_type)", + "https://bauglir.github.io/Kroki.jl/stable/#diagram-support", + ), ) """