Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Provide command to render an Enterprise Architect diagram from XMI #128

Merged
merged 3 commits into from
Jul 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 21 additions & 1 deletion README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,26 @@ diagram MyView {
....
----

=== Rendering a LutaML Enterprise Architect diagram from XMI: `lutaml_ea_diagram`

This command allows to quickly render a LutaML diagram as an image file by
specifying the name of diagram.

[source,adoc]
-----
lutaml_ea_diagram::[name="name_of_diagram",base_path="/path/to/xmi-images",format="png"]
-----

The code will search the diagram with name `name_of_diagram` and then
render it as:

[source,adoc]
-----
[[figure-{{ diagram.xmi_id }}]]
.{{ diagram.name }}
image::{{ image_base_path }}/{{ diagram.xmi_id }}.{{ format | default: 'png' }}[]
-----

=== Generating UML class and attributes: `lutaml_uml_class`

This command allows rendering a definition clause for a UML class.
Expand Down Expand Up @@ -490,7 +510,7 @@ Where:

* `[.after, package="Another"]` - block text to be inserted before(after in case of `.before` name) the package

* `[.package_text, position="after", package="Another"]` - include custom adoc code into package rendered body, `position` is a arequired attribute which tells where to insert the code.
* `[.package_text, position="after", package="Another"]` - include custom adoc code into package rendered body, `position` is a a required attribute which tells where to insert the code.

* `[.package_text, package="Another"]` - same as above, but include block will be included only for supplied package name

Expand Down
1 change: 1 addition & 0 deletions lib/metanorma-plugin-lutaml.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
require "metanorma/plugin/lutaml/lutaml_diagram_block_macro"
require "metanorma/plugin/lutaml/lutaml_figure_inline_macro"
require "metanorma/plugin/lutaml/lutaml_table_inline_macro"
require "metanorma/plugin/lutaml/lutaml_ea_diagram_block_macro"

module Metanorma
module Plugin
Expand Down
56 changes: 56 additions & 0 deletions lib/metanorma/plugin/lutaml/lutaml_ea_diagram_block_macro.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# frozen_string_literal: true

require "metanorma/plugin/lutaml/lutaml_diagram_base"

module Metanorma
module Plugin
module Lutaml
class LutamlEaDiagramBlockMacro < ::Asciidoctor::Extensions::BlockMacroProcessor
include LutamlDiagramBase

use_dsl
named :lutaml_ea_diagram

def process(parent, _target, attrs)
orig_doc = parent.document.attributes["lutaml_xmi_cache"]
.values.first.original_document
diagram = fetch_diagram_by_name(orig_doc, attrs["name"])
return if diagram.nil?

through_attrs = generate_attrs(attrs)
through_attrs["target"] =
img_src_path(parent.document, attrs, diagram)
through_attrs["title"] = diagram.name

create_image_block(parent, through_attrs)
end

private

def img_src_path(document, attrs, diagram)
base_path = attrs["base_path"]
format = attrs["format"] || "png"
img_path = Utils.relative_file_path(document, base_path)

"#{img_path}/#{diagram.xmi_id}.#{format}"
end

def fetch_diagram_by_name(orig_doc, name)
found_diagrams = []
loop_sub_packages(orig_doc.packages.first, name, found_diagrams)
found_diagrams.first
end

def loop_sub_packages(package, name, found_diagrams)
found_diagram = package.diagrams.find { |diag| diag.name == name }

found_diagrams << found_diagram if found_diagram

package.packages.each do |sub_package|
loop_sub_packages(sub_package, name, found_diagrams)
end
end
end
end
end
end
2 changes: 1 addition & 1 deletion lib/metanorma/plugin/lutaml/version.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
module Metanorma
module Plugin
module Lutaml
VERSION = "0.7.0".freeze
VERSION = "0.7.1".freeze
end
end
end
1 change: 1 addition & 0 deletions metanorma-plugin-lutaml.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,5 @@ Gem::Specification.new do |spec|
spec.add_development_dependency "timecop", "~> 0.9"
spec.add_development_dependency "vcr", "~> 5.0.0"
spec.add_development_dependency "webmock"
spec.add_development_dependency "xml-c14n"
end
Binary file not shown.
41 changes: 41 additions & 0 deletions spec/metanorma/plugin/lutaml/lutaml_ea_diagram_block_macro_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
require "spec_helper"

RSpec.describe Metanorma::Plugin::Lutaml::LutamlEaDiagramBlockMacro do
describe "#process" do
context "when package referenced" do
let(:example_file) do
# fixtures_path("plateau_uml_20240708_all_packages_export.xmi")
fixtures_path("test.xmi")
end
let(:input) do
<<~TEXT
= Document title
Author
:nodoc:
:novalid:
:no-isobib:
:imagesdir: spec/assets

[lutaml_uml_datamodel_description,#{example_file}]
--
--

lutaml_ea_diagram::[name="Fig B1 Full model",base_path="./xmi-images",format="png"]
TEXT
end
let(:output) do
[
"<name>Fig B1 Full model</name>",
"<image src=\"_\" mimetype=\"image/png\" " \
"id=\"_4c0bc330-4360-7c06-2130-27690748fb69\" " \
"height=\"auto\" width=\"auto\"/>",
]
end

it "correctly renders input" do
expect(strip_src(metanorma_process(input)))
.to(include(output.join("\n")))
end
end
end
end
29 changes: 5 additions & 24 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,13 @@
preprocessor Metanorma::Plugin::Lutaml::LutamlUmlClassPreprocessor
block_macro Metanorma::Plugin::Lutaml::LutamlDiagramBlockMacro
block Metanorma::Plugin::Lutaml::LutamlDiagramBlock
block_macro Metanorma::Plugin::Lutaml::LutamlEaDiagramBlockMacro
end

require "metanorma-standoc"
require "rspec/matchers"
require "equivalent-xml"
require "xml-c14n"

Dir[File.expand_path("./support/**/**/*.rb", __dir__)].sort.each do |f|
require f
Expand Down Expand Up @@ -80,10 +82,12 @@ def strip_guid(xml)
xml
.gsub(%r{ id="_[^"]+"}, ' id="_"')
.gsub(%r{ target="_[^"]+"}, ' target="_"')
.gsub(%r{<fetched>[^<]+</fetched>}, "<fetched/>")
.gsub(%r{ schema-version="[^"]+"}, "")
end

def xml_string_content(xml)
strip_guid(xmlpp(Nokogiri::XML(xml).to_s))
strip_guid(Xml::C14n.format(Nokogiri::XML(xml).to_s))
end

def metanorma_process(input)
Expand All @@ -102,26 +106,3 @@ def strip_src(xml)
xml.gsub(/\ssrc="[^"]+"/, ' src="_"')
end

XSL = Nokogiri::XSLT(<<~XSL.freeze)
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<xsl:copy-of select="."/>
</xsl:template>
</xsl:stylesheet>
XSL

def xmlpp(xml)
c = HTMLEntities.new
xml &&= xml.split(/(&\S+?;)/).map do |n|
if /^&\S+?;$/.match?(n)
c.encode(c.decode(n), :hexadecimal)
else n
end
end.join
XSL.transform(Nokogiri::XML(xml, &:noblanks))
.to_xml(indent: 2, encoding: "UTF-8")
.gsub(%r{<fetched>[^<]+</fetched>}, "<fetched/>")
.gsub(%r{ schema-version="[^"]+"}, "")
end
Loading