diff --git a/sphinxcontrib/spelling/builder.py b/sphinxcontrib/spelling/builder.py index ce51c9a..549834d 100644 --- a/sphinxcontrib/spelling/builder.py +++ b/sphinxcontrib/spelling/builder.py @@ -214,53 +214,60 @@ def _find_misspellings(self, docname, doctree): doc_filters.append(filters.IgnoreWordsFilterFactory(good_words)) self.checker.push_filters(doc_filters) - for node in doctree.traverse(docutils.nodes.Text): - if (node.tagname == '#text' and - node.parent and - node.parent.tagname in self.TEXT_NODES and - not hasattr(node, "spellingIgnore")): - - # Get the location of the text being checked so we can - # report it in the output file. Nodes from text that - # comes in via an 'include' directive does not include - # the full path, so convert all to relative path - # for consistency. - source, node_lineno = docutils.utils.get_source_line(node) - source = osutil.relpath(source) - - # Check the text of the node. - misspellings = self.checker.check(node.astext()) - for ( - word, - suggestions, + # Set up a filter for the types of nodes to ignore during + # traversal. + def filter(n): + if n.tagname != '#text': + return False + if (n.parent and n.parent.tagname not in self.TEXT_NODES): + return False + # Nodes marked by the spelling:ignore role + if hasattr(n, "spellingIgnore"): + return False + return True + + for node in doctree.findall(filter): + # Get the location of the text being checked so we can + # report it in the output file. Nodes from text that + # comes in via an 'include' directive does not include + # the full path, so convert all to relative path + # for consistency. + source, node_lineno = docutils.utils.get_source_line(node) + source = osutil.relpath(source) + + # Check the text of the node. + misspellings = self.checker.check(node.astext()) + for ( + word, + suggestions, + context_line, + line_offset + ) in misspellings: + + # Avoid TypeError on nodes lacking a line number + # This happens for some node originating from docstrings + lineno = node_lineno + if lineno is not None: + lineno += line_offset + + msg_parts = [ + f'{source}:{lineno}: ', + 'Spell check', + red(word), + ] + if self.format_suggestions(suggestions) != '': + msg_parts.append(self.format_suggestions(suggestions)) + msg_parts.append(context_line) + msg = ': '.join(msg_parts) + '.' + if self.config.spelling_warning: + logger.warning(msg) + elif self.config.spelling_verbose: + logger.info(msg) + yield "%s:%s: (%s) %s %s\n" % ( + source, lineno, word, + self.format_suggestions(suggestions), context_line, - line_offset - ) in misspellings: - - # Avoid TypeError on nodes lacking a line number - # This happens for some node originating from docstrings - lineno = node_lineno - if lineno is not None: - lineno += line_offset - - msg_parts = [ - f'{source}:{lineno}: ', - 'Spell check', - red(word), - ] - if self.format_suggestions(suggestions) != '': - msg_parts.append(self.format_suggestions(suggestions)) - msg_parts.append(context_line) - msg = ': '.join(msg_parts) + '.' - if self.config.spelling_warning: - logger.warning(msg) - elif self.config.spelling_verbose: - logger.info(msg) - yield "%s:%s: (%s) %s %s\n" % ( - source, lineno, word, - self.format_suggestions(suggestions), - context_line, - ) + ) self.checker.pop_filters() return diff --git a/tests/test_builder.py b/tests/test_builder.py index 11a90f7..d76c305 100644 --- a/tests/test_builder.py +++ b/tests/test_builder.py @@ -13,7 +13,7 @@ import sphinx from sphinx.application import Sphinx -from tests import helpers # isort:skip +from tests import helpers # isort:skip def _make_sphinx_project(tmpdir): @@ -446,6 +446,7 @@ def test_domain_role_multiple_words(sphinx_project): ) assert output_text is None + def test_domain_role_output(sphinx_project): srcdir, outdir = sphinx_project @@ -473,6 +474,7 @@ def test_domain_role_output(sphinx_project): assert output_text == "The Module\n**********\n\nteh is OK\n" + def test_domain_ignore(sphinx_project): srcdir, outdir = sphinx_project @@ -512,7 +514,7 @@ def test_domain_ignore_multiple_words(sphinx_project): 'contents', ) assert '(baddddd)' in output_text - assert output_text.count('\n') == 2 # Only expect 2 errors, not 3. + assert output_text.count('\n') == 2 # Only expect 2 errors, not 3. def test_domain_ignore_output(sphinx_project): @@ -541,3 +543,28 @@ def test_domain_ignore_output(sphinx_project): output_text = None assert output_text == "The Module\n**********\n\nteh is OK\n" + + +def test_only_directive(sphinx_project): + # How to skip checking nested blocks of content + # https://github.com/sphinx-contrib/spelling/issues/204 + srcdir, outdir = sphinx_project + + add_file(srcdir, 'contents.rst', ''' + The Module + ========== + + .. only:: html + + teh is ok + + whaat is not ok + ''') + + stdout, stderr, output_text = get_sphinx_output( + srcdir, + outdir, + 'contents', + ) + assert '(whaat)' in output_text + assert '(teh)' not in output_text