summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTakeshi KOMIYA <i.tkomiya@gmail.com>2022-01-16 02:00:40 +0900
committerGitHub <noreply@github.com>2022-01-16 02:00:40 +0900
commita55a765e797197cfdf8a3e5033efe8ed72191a62 (patch)
tree2b6317ca8377ffbdce0eeb7745c82a3a3fd2fd26
parent0938c193ea6f56dbb930bfb323602bc4e2b7b9c6 (diff)
parentff54f97aba881f31359d983d1e82c63199886768 (diff)
downloadsphinx-git-a55a765e797197cfdf8a3e5033efe8ed72191a62.tar.gz
Merge pull request #9661 from latosha-maltba/dedent
code-block: Fix handling of :dedent: and add unit tests
-rw-r--r--CHANGES2
-rw-r--r--doc/usage/restructuredtext/directives.rst1
-rw-r--r--sphinx/directives/code.py6
-rw-r--r--tests/roots/test-directive-code/dedent.rst64
-rw-r--r--tests/test_directive_code.py27
5 files changed, 96 insertions, 4 deletions
diff --git a/CHANGES b/CHANGES
index a1bb6dc82..ea5acc698 100644
--- a/CHANGES
+++ b/CHANGES
@@ -78,7 +78,7 @@ Bugs fixed
* #9979: Error level messages were displayed as warning messages
* #10057: Failed to scan documents if the project is placed onto the root
directory
-
+* #9636: code-block: ``:dedent:`` without argument did strip newlines
Testing
--------
diff --git a/doc/usage/restructuredtext/directives.rst b/doc/usage/restructuredtext/directives.rst
index bd1b1a3c6..d1877bca0 100644
--- a/doc/usage/restructuredtext/directives.rst
+++ b/doc/usage/restructuredtext/directives.rst
@@ -598,6 +598,7 @@ __ https://pygments.org/docs/lexers
are removed via :func:`textwrap.dedent()`. For example::
.. code-block:: ruby
+ :linenos:
:dedent: 4
some ruby code
diff --git a/sphinx/directives/code.py b/sphinx/directives/code.py
index 8bead7163..ddd47e1f8 100644
--- a/sphinx/directives/code.py
+++ b/sphinx/directives/code.py
@@ -57,7 +57,7 @@ class Highlight(SphinxDirective):
def dedent_lines(lines: List[str], dedent: int, location: Tuple[str, int] = None) -> List[str]:
- if not dedent:
+ if dedent is None:
return textwrap.dedent(''.join(lines)).splitlines(True)
if any(s[:dedent].strip() for s in lines):
@@ -138,9 +138,9 @@ class CodeBlock(SphinxDirective):
if 'dedent' in self.options:
location = self.state_machine.get_source_and_line(self.lineno)
- lines = code.split('\n')
+ lines = code.splitlines(True)
lines = dedent_lines(lines, self.options['dedent'], location=location)
- code = '\n'.join(lines)
+ code = ''.join(lines)
literal: Element = nodes.literal_block(code, code)
if 'linenos' in self.options or 'lineno-start' in self.options:
diff --git a/tests/roots/test-directive-code/dedent.rst b/tests/roots/test-directive-code/dedent.rst
new file mode 100644
index 000000000..f36e3e3ba
--- /dev/null
+++ b/tests/roots/test-directive-code/dedent.rst
@@ -0,0 +1,64 @@
+dedent option
+-------------
+
+.. code-block::
+
+ First line
+ Second line
+ Third line
+ Fourth line
+
+ReST has no fixed indent and only a change in indention is significant not the amount [1]_.
+Thus, the following code inside the code block is not indent even it looks so with respect to the previous block.
+
+.. code-block::
+
+ First line
+ Second line
+ Third line
+ Fourth line
+
+Having an option "fixates" the indent to be 3 spaces, thus the code inside the code block is indented by 4 spaces.
+
+.. code-block::
+ :class: dummy
+
+ First line
+ Second line
+ Third line
+ Fourth line
+
+The code has 6 spaces indent, minus 4 spaces dedent should yield a 2 space indented code in the output.
+
+.. code-block::
+ :dedent: 4
+
+ First line
+ Second line
+ Third line
+ Fourth line
+
+Dedenting by zero, should not strip any spaces and be a no-op.
+
+.. note::
+ This can be used as an alternative to ``:class: dummy`` above, to fixate the ReST indention of the block.
+
+.. code-block::
+ :dedent: 0
+
+ First line
+ Second line
+ Third line
+ Fourth line
+
+Dedent without argument should autostrip common whitespace at the beginning.
+
+.. code-block::
+ :dedent:
+
+ First line
+ Second line
+ Third line
+ Fourth line
+
+.. [1] https://docutils.sourceforge.io/docs/ref/rst/restructuredtext.html#indentation
diff --git a/tests/test_directive_code.py b/tests/test_directive_code.py
index d8244db6a..5f519d3b9 100644
--- a/tests/test_directive_code.py
+++ b/tests/test_directive_code.py
@@ -580,3 +580,30 @@ def test_linenothreshold(app, status, warning):
# literal include not using linenothreshold (no line numbers)
assert ('<span></span><span class="c1"># Very small literal include '
'(linenothreshold check)</span>' in html)
+
+
+@pytest.mark.sphinx('dummy', testroot='directive-code')
+def test_code_block_dedent(app, status, warning):
+ app.builder.build(['dedent'])
+ doctree = app.env.get_doctree('dedent')
+ codeblocks = list(doctree.traverse(nodes.literal_block))
+ # Note: comparison string should not have newlines at the beginning or end
+ text_0_indent = '''First line
+Second line
+ Third line
+Fourth line'''
+ text_2_indent = ''' First line
+ Second line
+ Third line
+ Fourth line'''
+ text_4_indent = ''' First line
+ Second line
+ Third line
+ Fourth line'''
+
+ assert codeblocks[0].astext() == text_0_indent
+ assert codeblocks[1].astext() == text_0_indent
+ assert codeblocks[2].astext() == text_4_indent
+ assert codeblocks[3].astext() == text_2_indent
+ assert codeblocks[4].astext() == text_4_indent
+ assert codeblocks[5].astext() == text_0_indent