diff --git a/docs/configuration.rst b/docs/configuration.rst index fbbe730b..c55299ba 100644 --- a/docs/configuration.rst +++ b/docs/configuration.rst @@ -80,7 +80,10 @@ Top level keys ``""`` by default. - Formatted titles are appended a line of ``=`` on the following line (reStructuredText title format) unless the template has an ``.md`` suffix, in which case the title will instead be prefixed with ``#`` (markdown title format). + When using reStructuredText, formatted titles are underlined using the ``underlines`` configuration. + For titles, the first value from ``underlines`` is used to create the underline (which is inserted on the line following the title). + If the template has an ``.md`` suffix, we assume we are looking at markdown format and the title is applied as, i.e. full control over the title format is given to the user. + This choice is made because setting the correct markdown header level automatically is non-trivial (mainly because you don't know what context the generated CHANGELOG entries are being written into). ``issue_format`` A format string for rendering the issue/ticket number in newsfiles. diff --git a/src/towncrier/build.py b/src/towncrier/build.py index 546ef113..3d183925 100644 --- a/src/towncrier/build.py +++ b/src/towncrier/build.py @@ -232,7 +232,7 @@ def __main( name=project_name, version=project_version, project_date=project_date ) if is_markdown: - parts = [f"# {top_line}"] + parts = [top_line] else: parts = [top_line, config.underlines[0] * len(top_line)] parts.append(rendered) diff --git a/src/towncrier/newsfragments/651.bugfix.md b/src/towncrier/newsfragments/651.bugfix.md new file mode 100644 index 00000000..3b3f4c0e --- /dev/null +++ b/src/towncrier/newsfragments/651.bugfix.md @@ -0,0 +1 @@ +Control of the header formatting is once again completely up to the user when they are writing markdown files (fixes a regression introduced in [#610](https://github.com/twisted/towncrier/pull/610)). diff --git a/src/towncrier/test/test_build.py b/src/towncrier/test/test_build.py index 4556cca3..f97fa91d 100644 --- a/src/towncrier/test/test_build.py +++ b/src/towncrier/test/test_build.py @@ -15,7 +15,7 @@ from .._shell import cli from ..build import _main -from .helpers import read, with_git_project, with_project, write +from .helpers import read, read_pkg_resource, with_git_project, with_project, write class TestCli(TestCase): @@ -1050,7 +1050,15 @@ def test_title_format_custom(self, runner): def test_title_format_custom_markdown(self, runner): """ A non-empty title format adds the specified title, and if the target filename is - markdown then the title is added as a markdown header. + markdown then the title is added as given by the config. + In this way, full control is given to the user. + We make this choice for markdown files + because markdown header levels depend on where in the file + the section is being written and require modifications in the same line, + hence there is no easy way to know what to do to get the header to be at the right level. + This avoids a repeat of the regression introduced in + [#610](https://github.com/twisted/towncrier/pull/610), + which mistakenly assumed that starting the line with '# ' would work in all use cases. """ with open("foo/newsfragments/123.feature", "w") as f: f.write("Adds levitation") @@ -1075,7 +1083,7 @@ def test_title_format_custom_markdown(self, runner): Draft only -- nothing has been written. What is seen below is what would be written. - # [20-01-2001] CUSTOM RELEASE for FooBarBaz version 7.8.9 + [20-01-2001] CUSTOM RELEASE for FooBarBaz version 7.8.9 ### Features @@ -1089,6 +1097,87 @@ def test_title_format_custom_markdown(self, runner): self.assertEqual(0, result.exit_code) self.assertEqual(expected_output, result.output) + @with_project( + config=""" + [tool.towncrier] + package = "foo" + filename = "NEWS.md" + title_format = "### [{project_date}] CUSTOM RELEASE for {name} version {version}" + template = "custom_template.md" + """ + ) + def test_markdown_injected_after_header(self, runner): + """ + Test that we can inject markdown after some fixed header + and have the injected markdown header levels set at the desired level. + This avoids a repeat of the regression introduced in + [#610](https://github.com/twisted/towncrier/pull/610), + which mistakenly assumed that starting the line with '# ' would work in all use cases. + """ + write("foo/newsfragments/123.feature", "Adds levitation") + write( + "NEWS.md", + contents=""" + # Top title + + ## Section title + + Some text explaining something + + another line + + ## Release notes + + + + a footer! + """, + dedent=True, + ) + + default_template = read_pkg_resource("templates/default.md") + write( + "custom_template.md", + contents=default_template.replace( + "### {{ definitions", "#### {{ definitions" + ), + ) + + result = runner.invoke(_main, ["--date", "01-01-2001"], catch_exceptions=False) + + with open("foo/newsfragments/123.feature", "w") as f: + f.write("Adds levitation") + + self.assertEqual(0, result.exit_code, result.output) + output = read("NEWS.md") + + expected_output = dedent( + """ + # Top title + + ## Section title + + Some text explaining something + + another line + + ## Release notes + + + + ### [01-01-2001] CUSTOM RELEASE for Foo version 1.2.3 + + #### Features + + - Adds levitation (#123) + + + a footer! + """ + ) + + self.assertEqual(expected_output, output) + @with_project( config=""" [tool.towncrier]