diff --git a/CHANGELOG b/CHANGELOG
index 4adf623..f142155 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,7 +1,8 @@
dev
---
-*
+* Add detailed-message-style option to specify the style of details.
+ (amedama41)
v11.0.0
-------
diff --git a/docs/using.rst b/docs/using.rst
index d0b94f0..c927e63 100644
--- a/docs/using.rst
+++ b/docs/using.rst
@@ -99,23 +99,65 @@ will produce the list of commits that modified documentation content.
selected (number of) revisions.
-Preformatted Output for Detailed Messages
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Changing Detailed Messages Output Style
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If you would prefer for the detailed commit messages to be output as
-preformatted text (e.g. if you include code samples in your commit messages),
-then you can specify this preference using the ``:detailed-message-pre:``
-argument. So::
+non plain text format, then you can specify the style using the
+``detailed-message-style`` argument. The styles you can specify are 'pre',
+'rst', or, 'md'.
+
+If you would prefer for the messages to be output as preformatted text
+(e.g. if you include code samples in your commit messages),
+then you can specify 'pre' (This is same as specifying deprecated
+``detailed-message-pre``). So::
.. git_changelog::
:rev-list: 3669419^..3669419
- :detailed-message-pre: True
+ :detailed-message-style: pre
becomes:
.. git_changelog::
:rev-list: 3669419^..3669419
- :detailed-message-pre: True
+ :detailed-message-style: pre
+
+If you would prefer for the messages to be parsed as reStructuredText,
+then you can specify 'rst'. So::
+
+ .. git_changelog::
+ :rev-list: d888873^..d888873
+ :detailed-message-style: rst
+
+becomes:
+
+ .. git_changelog::
+ :rev-list: d888873^..d888873
+ :detailed-message-style: rst
+
+If you would prefer for the messages to be parsed as Markdown (CommonMark),
+then you can specify 'md'. So::
+
+ .. git_changelog::
+ :rev-list: 0de9cd1^..0de9cd1
+ :detailed-message-style: md
+
+becomes:
+
+ .. git_changelog::
+ :rev-list: 0de9cd1^..0de9cd1
+ :detailed-message-style: md
+
+.. note::
+
+ The feature to output the messages as Markdown requires recommonmark package.
+ recommonmark is enable to be installed by pip::
+
+ pip install recommonmark
+
+ You can also install sphinx-git with recommonmark simultaneously::
+
+ pip install sphinx-git[markdown]
.. _the man page: https://www.kernel.org/pub/software/scm/git/docs/git-rev-parse.html
diff --git a/requirements.txt b/requirements.txt
index f399564..bba0d44 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -5,3 +5,4 @@ mock
nose
pycodestyle
pylint
+recommonmark
diff --git a/setup.py b/setup.py
index ae1756b..b571791 100644
--- a/setup.py
+++ b/setup.py
@@ -12,6 +12,9 @@
author='Daniel Watkins',
author_email='daniel@daniel-watkins.co.uk',
install_requires=['six', 'sphinx', 'GitPython>=0.3.6'],
+ extras_require={
+ 'markdown': ['recommonmark>=0.4.0'],
+ },
url="https://github.com/OddBloke/sphinx-git",
packages=['sphinx_git'],
)
diff --git a/sphinx_git/__init__.py b/sphinx_git/__init__.py
index 958e189..ee957ba 100644
--- a/sphinx_git/__init__.py
+++ b/sphinx_git/__init__.py
@@ -19,7 +19,14 @@
import six
from docutils import nodes
from docutils.parsers.rst import Directive, directives
+from docutils.statemachine import StringList
from git import Repo
+from sphinx.util.docutils import new_document
+
+try:
+ from recommonmark.parser import CommonMarkParser
+except ImportError:
+ CommonMarkParser = None
# pylint: disable=too-few-public-methods, abstract-method
@@ -106,12 +113,17 @@ def _commit_text_node(self):
return nodes.emphasis(text=self.commit.hexsha[:self.sha_length])
+def get_details_style(argument):
+ return directives.choice(argument, ['pre', 'rst', 'md'])
+
+
# pylint: disable=too-few-public-methods
class GitChangelog(GitDirectiveBase):
option_spec = {
'revisions': directives.nonnegative_int,
'rev-list': six.text_type,
+ 'detailed-message-style': get_details_style,
'detailed-message-pre': bool,
'detailed-message-strong': bool,
'filename_filter': six.text_type,
@@ -128,6 +140,19 @@ def run(self):
' only rev-list.',
line=self.lineno
)
+ detailed_message_style = self.options.get('detailed-message-style')
+ if detailed_message_style == 'md' and CommonMarkParser is None:
+ detailed_message_style = None
+ self.state.document.reporter.warning(
+ 'detailed-message-style is md but recommonmark is not'
+ ' installed; processing ignoring detailed-message-style.')
+ if detailed_message_style is not None and \
+ 'detailed-message-pre' in self.options:
+ self.state.document.reporter.warning(
+ 'Both detailed-message-style and detailed-message-pre options'
+ ' given; proceeding using only detailed-message-style.',
+ line=self.lineno)
+
commits = self._commits_to_display()
markup = self._build_markup(commits)
return markup
@@ -165,6 +190,34 @@ def _filter_commits_on_filenames(self, commits):
break
return filtered_commits
+ def _build_detailed_message(self, detailed_message):
+ detailed_message_style = self.options.get('detailed-message-style')
+ if detailed_message_style == 'md' and CommonMarkParser is None:
+ detailed_message_style = None
+ if detailed_message_style is None:
+ if self.options.get('detailed-message-pre'):
+ detailed_message_style = 'pre'
+
+ detailed_message = detailed_message.strip()
+ if detailed_message_style == 'pre':
+ return [nodes.literal_block(text=detailed_message)]
+ try:
+ if detailed_message_style == 'rst':
+ node = nodes.Element()
+ lines = detailed_message.splitlines()
+ self.state.nested_parse(StringList(lines), 0, node)
+ return node.children
+ if detailed_message_style == 'md':
+ document = new_document('', self.state.document.settings)
+ parser = CommonMarkParser()
+ parser.parse(detailed_message, document)
+ return document.children
+ # pylint: disable=broad-except
+ except Exception as error:
+ self.state.document.reporter.warning(
+ 'Could not parse as %s: %s' % (detailed_message_style, error))
+ return [nodes.paragraph(text=detailed_message)]
+
def _build_markup(self, commits):
list_node = nodes.bullet_list()
for commit in commits:
@@ -191,12 +244,7 @@ def _build_markup(self, commits):
nodes.emphasis(text=str(date_str))]
item.append(par)
if detailed_message and not self.options.get('hide_details'):
- detailed_message = detailed_message.strip()
- if self.options.get('detailed-message-pre', False):
- item.append(
- nodes.literal_block(text=detailed_message))
- else:
- item.append(nodes.paragraph(text=detailed_message))
+ item.extend(self._build_detailed_message(detailed_message))
list_node.append(item)
return [list_node]
diff --git a/tests/test_git_changelog.py b/tests/test_git_changelog.py
index fd92774..0c0c9d9 100644
--- a/tests/test_git_changelog.py
+++ b/tests/test_git_changelog.py
@@ -134,6 +134,89 @@ def test_single_commit_preformmated_detail_lines(self):
'more info'
)
+ def test_single_commit_rst_style_detail_lines(self):
+ self.repo.index.commit(
+ 'my root commit\n\nadditional information\n\n'
+ '* item1: **description1**\n'
+ '* item2: *description2*'
+ )
+ self.changelog.options.update({'detailed-message-style': 'rst'})
+
+ def handle_nested_parse(lines, offset, node):
+ from docutils import nodes
+ node.append(nodes.paragraph(text='additional information'))
+ bullet_list = nodes.bullet_list()
+ p = nodes.paragraph(
+ '', 'item1: ', nodes.strong(text='description1'))
+ bullet_list.append(nodes.list_item('', p))
+ p = nodes.paragraph(
+ '', 'item2: ', nodes.emphasis(text='description2'))
+ bullet_list.append(nodes.list_item('', p))
+ node.append(bullet_list)
+
+ self.changelog.state.nested_parse.side_effect = handle_nested_parse
+ nodes = self.changelog.run()
+ list_markup = BeautifulSoup(str(nodes[0]), features='xml')
+ item = list_markup.bullet_list.list_item
+ children = list(item.childGenerator())
+ assert_equal(3, len(children))
+ assert_equal(
+ str(children[1]),
+ 'additional information'
+ )
+ assert_equal(
+ str(children[2]),
+ ''
+ 'item1: description1'
+ ''
+ 'item2: description2'
+ ''
+ )
+
+ def test_single_commit_md_style_detail_lines(self):
+ self.repo.index.commit(
+ 'my root commit\n\nadditional information\n'
+ '* item1: **description1**\n'
+ '* item2: *description2*'
+ )
+ self.changelog.options.update({'detailed-message-style': 'md'})
+
+ config = self.changelog.state.document.settings.env.config
+ config.recommonmark_config = {}
+ nodes = self.changelog.run()
+ list_markup = BeautifulSoup(str(nodes[0]), features='xml')
+ item = list_markup.bullet_list.list_item
+ children = list(item.childGenerator())
+ assert_equal(3, len(children))
+ assert_equal(
+ str(children[1]),
+ 'additional information'
+ )
+ assert_equal(
+ str(children[2]),
+ ''
+ 'item1: description1'
+ ''
+ 'item2: description2'
+ ''
+ )
+
+ def test_single_commit_pre_style_detail_lines(self):
+ self.repo.index.commit(
+ 'my root commit\n\nadditional information\nmore info'
+ )
+ self.changelog.options.update({'detailed-message-style': 'pre'})
+ nodes = self.changelog.run()
+ list_markup = BeautifulSoup(str(nodes[0]), features='xml')
+ item = list_markup.bullet_list.list_item
+ children = list(item.childGenerator())
+ assert_equal(2, len(children))
+ assert_equal(
+ str(children[1]),
+ 'additional information\n'
+ 'more info'
+ )
+
def test_more_than_ten_commits(self):
for n in range(15):
self.repo.index.commit('commit #{0}'.format(n))