Skip to content

Commit

Permalink
Merge branch 'release-3.3.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
Michele Tessaro committed Jun 18, 2020
2 parents 59148c0 + 7fe16e6 commit 566a02c
Show file tree
Hide file tree
Showing 9 changed files with 85 additions and 28 deletions.
7 changes: 4 additions & 3 deletions .gitchangelog.rc
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ ignore_regexps = [
r'@wip', r'!wip',
r'^([cC]hg|[fF]ix|[nN]ew)\s*:\s*[p|P]kg:',
r'^([cC]hg|[fF]ix|[nN]ew)\s*:\s*[d|D]ev:',
r'^([cC]hg|[fF]ix|[nN]ew)\s*:\s*[t|T]est:',
r'^(.{3,3}\s*:)?\s*[fF]irst commit.?\s*$',
r'^[Uu]pdating .*poms .*$',
r'^[mM]erging .*$',
Expand All @@ -79,15 +80,15 @@ ignore_regexps = [
##
section_regexps = [
('New', [
r'^[nN]ew\s*:\s*((dev|use?r|pkg|test|doc)\s*:\s*)?([^\n]*)$',
r'^[nN]ew\s*:\s*((dev|use?r|pkg|doc)\s*:\s*)?([^\n]*)$',
r'^[aA]dded\s+',
]),
('Changes', [
r'^[cC]hg\s*:\s*((dev|use?r|pkg|test|doc)\s*:\s*)?([^\n]*)$',
r'^[cC]hg\s*:\s*((dev|use?r|pkg|doc)\s*:\s*)?([^\n]*)$',
r'^[cC]hange[\w]\s+.*$',
]),
('Fix', [
r'^[fF]ix\s*:\s*((dev|use?r|pkg|test|doc)\s*:\s*)?([^\n]*)$',
r'^[fF]ix\s*:\s*((dev|use?r|pkg|doc)\s*:\s*)?([^\n]*)$',
r'\b[fF]ix(ed|es)?\b',
r'\b[cC]orrect\w*\b',
]),
Expand Down
31 changes: 16 additions & 15 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,22 @@
# Changelog


## development (2020-03-04)
## 3.3.0 (2020-06-18)

### New

* Added support for loading plantuml from external files (refs #42) [Chalmela, Ravi]

### Changes

* Updated documentation. [Michele Tessaro]

### Fix

* Fixed closing of object tag (fixes #44) [Michele Tessaro]


## 3.2.2 (2020-03-04)

### Fix

Expand Down Expand Up @@ -51,10 +66,6 @@

## 3.1.3 (2019-08-26)

### New

* Added a test for issue #31. [Michele Tessaro]

### Changes

* Updated changelog for the new release. [Michele Tessaro]
Expand Down Expand Up @@ -97,10 +108,6 @@

## 3.1.1 (2019-05-29)

### New

* Configured travis to test with multiple Markdown versions. [Michele Tessaro]

### Fix

* Fixed compatibility with Markdown 2 (refs #29) [Michele Tessaro]
Expand Down Expand Up @@ -144,10 +151,6 @@

## 2.0.2 (2019-03-16)

### New

* Added test to verify utf-8 character handling. [Michele Tessaro]

### Changes

* Updated documentation for new release. [Michele Tessaro]
Expand All @@ -167,8 +170,6 @@

* Fixed package contents. [Michele Tessaro]

* Fixed travis configuration. [Michele Tessaro]


## 2.0.0 (2019-03-02)

Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ plantuml_markdown:
server: http://www.plantuml.com/plantuml # PlantUML server, for remote rendering
# other global options
cachedir: /tmp # set a non-empty value to enable caching
base_dir: . # where to search for diagrams to include
format: png # default diagram image format
classes: class1,class2 # default diagram classes
title: UML diagram # default title (tooltip) for diagram images
Expand All @@ -167,6 +168,7 @@ The plugin has several configuration option:
* `server`: PlantUML server url, for remote rendering. Defaults to `''`, use local command
* `cachedir`: directory for caching of diagrams. Defaults to `''`, no caching
* `priority`: extension priority. Higher values means the extension is applied sooner than others. Defaults to `30`
* `base_dir`: path where to search for external diagrams files

For passing options to the `plantuml_plugin` see the documentation of the tool you are using.

Expand Down
23 changes: 19 additions & 4 deletions plantuml_markdown.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ class PlantUMLPreprocessor(markdown.preprocessors.Preprocessor):
\s*(title=(?P<quot3>"|')(?P<title>.*?)(?P=quot3))?
\s*(width=(?P<quot4>"|')(?P<width>[\w\s"']+%?)(?P=quot4))?
\s*(height=(?P<quot5>"|')(?P<height>[\w\s"']+%?)(?P=quot5))?
\s*(source=(?P<quot6>"|')(?P<source>.*?)(?P=quot6))?
\s*\n
(?P<code>.*?)(?<=\n)
\s*::end-uml::[ ]*$
Expand All @@ -98,6 +99,7 @@ class PlantUMLPreprocessor(markdown.preprocessors.Preprocessor):
\s*(title=(?P<quot3>"|')(?P<title>.*?)(?P=quot3))?
\s*(width=(?P<quot4>"|')(?P<width>[\w\s"']+%?)(?P=quot4))?
\s*(height=(?P<quot5>"|')(?P<height>[\w\s"']+%?)(?P=quot5))?
\s*(source=(?P<quot6>"|')(?P<source>.*?)(?P=quot6))?
[ ]*
}?[ ]*\n # Optional closing }
(?P<code>.*?)(?<=\n)
Expand Down Expand Up @@ -134,6 +136,8 @@ def _replace_block(self, text):
title = m.group('title') if m.group('title') else self.config['title']
width = m.group('width') if m.group('width') else None
height = m.group('height') if m.group('height') else None
source = m.group('source') if m.group('source') else None
base_dir = self.config['base_dir'] if self.config['base_dir'] else None

# Convert image type in PlantUML image format
if img_format == 'png':
Expand All @@ -146,9 +150,17 @@ def _replace_block(self, text):
# logger.error("Bad uml image format '"+imgformat+"', using png")
requested_format = "png"

# Extract diagram source end convert it
code = m.group('code')
if source and base_dir:
# Load diagram source from external file
with open(os.path.join(base_dir, source), 'r') as f:
code = f.read()
else:
# Extract diagram source from markdown text
code = m.group('code')

# Extract diagram source end convert it (if not external)
diagram = self._render_diagram(code, requested_format)
self_closed = True # tags are always self closing

if img_format == 'txt':
# logger.debug(diagram)
Expand All @@ -173,6 +185,7 @@ def _replace_block(self, text):
data = 'data:image/svg+xml;base64,{0}'.format(base64.b64encode(diagram).decode('ascii'))
img = etree.Element('object')
img.attrib['data'] = data
self_closed = False # object tag must be explicitly closed
else: # png format, explicitly set or as a default when format is not recognized
data = 'data:image/png;base64,{0}'.format(base64.b64encode(diagram).decode('ascii'))
img = etree.Element('img')
Expand All @@ -195,7 +208,8 @@ def _replace_block(self, text):
img.attrib['alt'] = alt
img.attrib['title'] = title

return text[:m.start()] + etree.tostring(img).decode() + text[m.end():], True
return text[:m.start()] + etree.tostring(img, short_empty_elements=self_closed).decode() \
+ text[m.end():], True

def _render_diagram(self, code, requested_format):
cached_diagram_file = None
Expand Down Expand Up @@ -258,7 +272,8 @@ def __init__(self, **kwargs):
'server': ["", "PlantUML server url, for remote rendering. Defaults to '', use local command."],
'cachedir': ["", "Directory for caching of diagrams. Defaults to '', no caching"],
'priority': ["30", "Extension priority. Higher values means the extension is applied sooner than others. "
"Defaults to 30"]
"Defaults to 30"],
'base_dir': [".", "Base directory for external files inclusion"]
}

# Fix to make links navigable in SVG diagrams
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

setuptools.setup(
name="plantuml-markdown",
version="3.2.2",
version="3.3.0",
author="Michele Tessaro",
author_email="[email protected]",
description="A PlantUML plugin for Markdown",
Expand Down
1 change: 1 addition & 0 deletions test/data/include_output.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<p><img alt="uml diagram" class="uml" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAE4AAABvCAIAAADNOGHZAAAAKXRFWHRjb3B5bGVmdABHZW5lcmF0ZWQgYnkgaHR0cDovL3BsYW50dW1sLmNvbREwORwAAAECelRYdHBsYW50dW1sAAB4nEWOy26DMBBF9yPxD7NMFkYG0Yp6UaV5VaWgRIWwrUxwkSWwKz9Q8/d1G0XZ3jvnzllZx43z0xgBRvCChDzjOoIIVkL1/zEcR67cqSpxFsZKrTCJU5rkMU0XeyOx4gbpEyY5SynLMtzsGvzrl7B4PZZotTdngb20zsjOuzCwhILPHD+8cnISDA/fQhXb91uAOzVLo9UklIOire4HjxlZS4e1MEEF2+q60161WPAKUp9plpKO5hAgw51UA9YX68TEsJTK/8ChvhMPcRZTYnnHL1rBVnxxP7rw/6z7ADI8NXuSQ8nV4PkQTKWDjQ6W5sLwrYFfMFlhTXahMB4AAAQ0SURBVHja7ZtfSFNRHMe3TB8ytKJZKhIk9KAPkg+ZlkpIiH+j6CGCKMpKKNAn/4E6kEnCVJTeJNoUxpzW1pIc1JwmThmu9SChe/EfYv5JXVNn/u1XN0Scebfde8/V7ffjMI7Dc7/3c849556dc76CLZ8Jga+jrs7/nDKYWUmrC3bamyAjtzcqlFEKLrGSpjvNtKhk5PZDHayVThmUHqfBGqlbqFzL7YcK5Tc3v3icvnco3ULlWo5zVF1Ng9FotFgsVqt1YmLCZrPxJcc5qkpcrdVq9Xq9yWQC+ZmZGb7kOEdtKq5UKBRqtRrkobKhpvmS4xy1sUgik8lAHiobHq3h4WG+5DhHbS6XgrZcLlepVFDT8FDxJYeoiLqdtNo6gUDQ1lbPNapgRwQFBaanXx0a0hBFzcpKysm5mZ2dTACVyqyv98/OGgoK7sfEXCCHOjbWHh4e4nD0RUScgTwZVCotLfUGBx8nh1pe/rSw8AFkiosfQp4M6saGeW6uSyzOrarKI4S6ttYPjUl1GPiEPHxDpq9CCIVCubyCEKpGU5uUFLv9J+RhiCLWqvX1hVFR5wmhZmQk7qrpzMxEYn3Vbu8JCPAngToy8oEakLa/WV7uCwsTjY62k0GdnPwYGnqaBGpp6WPnUUEieV5W9oQA6vR0R0nJo/z8u5yjwvATHR1ps3Xv0pif/wz9x3lwYndYggFJJDoJnIuLRpwYIiqiIiqiIiqiIuqBQB2skUJ5jxO1ieI6KtdynO/EuY7Ktdx/9lcX7NOdZirpahpU4uqm4srGIglcyO30upEWlYwc/a650WjUarUKhULGIPZf3ScjR49qsVigetRqNZSXexS0ezZk5OhR4RkwmUxQEupJ5VHQ7sSRkaNHhYqBMlBD8DzonUKWW6KnC9r9VTJy9Kjw31A3UAyee6tT1PnHWukCCkJxuAhcamVlhS85pod5YHwneSCHiRyiIqpzDIgbSKIykfP5g3eIiqg+gupDwxIrL5ul8anx1o51xy+feK8CqjoktSst74dpwPunEEDb7HcZLqg5mzZQ8WrPRvae2RLQvj11XRVw5c/SiV+8IeXZrkb2qtkS0GpEqS3HEv8tFwnjdjYyn8MSaMMNUXfAVv5TQs7OlbHWwGTlkTjoyVMGM5NbPXDv1Yl3Xc1H4ynI9ug7bZG33p+78e2F3DE561VTCIqzNeia7uI9+Oy5XTSp6/XC2RJwqvwTILHVjAd0WJrp/vrmRAptM3rDbMn6ssWVZsRVCERFVPwRhz/NERVRvQMV15YOz8vGdfP330M45LzmTOTQa45ec/Sao9ccveZ8yaHXHM8DIyp6zdFr7i4qes3Ra45e8y30mqPXHL3m6DVHrznOgREVUREVUREVUdFrjl5z9Jqj15yUHHrNdwR6zd0IFr3mTOSYes1dCRa95kzk8IgWoh7q+A3YYrvPERmJhwAAAABJRU5ErkJggg==" title="" /></p>
2 changes: 2 additions & 0 deletions test/data/included_diag.puml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@

A --> B
14 changes: 12 additions & 2 deletions test/markdown_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ def _reset_diagram(self):
self._diagram_buffer = ""
self._width = ""
self._height = ""
self._source = ""

def _emit_diagram(self):
"""
Expand All @@ -29,7 +30,7 @@ def _emit_diagram(self):
"""
if self._diagram_buffer:
delim = re.sub(r'(\W{3,})(\w+)', r'\1{\2', self._delimiter) if self._extended_syntax else self._delimiter
args = self._format + self._class + self._alt + self._title + self._width + self._height
args = self._format + self._class + self._alt + self._title + self._width + self._height + self._source
self._buffer += (' '*self._indent)+delim+args+('}' if self._extended_syntax else '')
self._buffer += "\n"+(' '*self._indent)+self._diagram_buffer+"\n"+(' '*self._indent)+self._end_delimiter+"\n"

Expand Down Expand Up @@ -92,12 +93,21 @@ def width(self, w):
def height(self, h):
"""
Define the maximum height of the diagram image.
:param w: Max width, with unit (ex: "120px")
:param h: Max width, with unit (ex: "120px")
:return: The object itself
"""
self._height = " height='%s'" % h
return self

def source(self, file_path):
"""
Sets inclusion of an external source diagram instead on an inline code.
:param file_path: Path of the file containing the diagram source
:return: The object itself
"""
self._source = " source='%s'" % file_path
return self

def text(self, txt):
"""
Adds a new text to the markdown source.
Expand Down
31 changes: 28 additions & 3 deletions test/test_plantuml.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,13 @@ def _load_file(self, filename):
return f.read()[:-1] # skip the last newline

FAKE_IMAGE = 'ABCDEF=='
IMAGE_REGEX = re.compile(r'<(?:img|.*object)(?:( alt=".*?")|( class=".*?")|( title=".*?")|( style=".*?")|( src=".*?")|(?:.*?))+/>')
IMAGE_REGEX = re.compile(r'<(?:img|.*object)'
r'(?:( alt=".*?")|'
r'( class=".*?")|'
r'( title=".*?")|'
r'( style=".*?")|'
r'( src=".*?")|'
r'(?:.*?))+(?:/>|></(?:img|.*object>))')
BASE64_REGEX = re.compile(
r'("data:image/[a-z+]+;base64,)(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?')

Expand All @@ -46,7 +52,6 @@ def sort_attributes(groups):
return cls.BASE64_REGEX.sub(r'\1%s' % cls.FAKE_IMAGE, html)

return cls.IMAGE_REGEX.sub(lambda x: sort_attributes(x.groups()), html)
#return cls.BASE64_REGEX.sub(r'\1%s' % cls.FAKE_IMAGE, html)

FAKE_SVG = '...svg-body...'
SVG_REGEX = re.compile(r'<(?:\w+:)?svg(?:( alt=".*?")|( class=".*?")|( title=".*?")|( style=".*?")|(?:.*?))+>.*</(?:\w+:)?svg>')
Expand Down Expand Up @@ -215,8 +220,11 @@ def test_arg_format_svg_object(self):
Test for the correct parsing of the format argument, generating a svg image
"""
text = self.text_builder.diagram("A --> B").format("svg_object").build()
html = self.md.convert(text)
self.assertEqual(self._stripImageData(self._load_file('svg_object_diag.html')),
self._stripImageData(self.md.convert(text)))
self._stripImageData(html))
# verify that the tag is explicitly closed
self.assertIsNotNone(re.match(r'.*<object .*?></object>.*', html))

def test_arg_format_svg_inline(self):
"""
Expand Down Expand Up @@ -303,6 +311,23 @@ def test_arg_format_width_and_height_svg_inline(self):
self.assertEqual(self._stripSvgData('<p><svg alt="uml diagram" title="" class="uml" style="max-width:120px;max-height:120px">...svg-body...</svg></p>'),
self._stripSvgData(self.md.convert(text)))

def test_arg_source(self):
"""
Test for the correct parsing of the source argument
"""
include_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'data')
self.md = markdown.Markdown(extensions=['markdown.extensions.fenced_code',
'pymdownx.snippets', 'plantuml_markdown'],
extension_configs={
'plantuml_markdown': {
'base_dir': include_path
}
})

text = self.text_builder.diagram("ignored text").source("included_diag.puml").build()
self.assertEqual(self._stripImageData(self._load_file('include_output.html')),
self._stripImageData(self.md.convert(text)))

def test_multidiagram(self):
"""
Test for the definition of multiple diagrams on the same document
Expand Down

0 comments on commit 566a02c

Please sign in to comment.