Repository: jackdewinter/pymarkdown

Issue:
MD044 - Add fix
need to implement a scan before fixing that joins any text blocks that were separated as part of the Extended Autolink parsing

Discussion:
sourcery-ai[bot]: <!-- Generated by sourcery-ai[bot]: start review_guide -->

🧙 Sourcery is reviewing your pull request!

<!-- Generated by sourcery-ai[bot]: end review_guide -->

---

<details>
<summary>Tips</summary>

- Trigger a new Sourcery review by commenting `@sourcery-ai review` on the pull request.
- You can change your review settings at any time by accessing your [dashboard](https://sourcery.ai/dashboard):
    - Enable or disable the Sourcery-generated pull request summary or reviewer's guide;
    - Change the review language;
- You can always [contact us](mailto:support@sourcery.ai) if you have any questions or feedback.

</details>
codecov[bot]: ## [Codecov](https://app.codecov.io/gh/jackdewinter/pymarkdown/pull/1105?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None) Report
All modified and coverable lines are covered by tests :white_check_mark:
> Project coverage is 100.00%. Comparing base [(`8a0c949`)](https://app.codecov.io/gh/jackdewinter/pymarkdown/commit/8a0c9498f3be2e56a28703f498642c2936944a66?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None) to head [(`1ac1311`)](https://app.codecov.io/gh/jackdewinter/pymarkdown/commit/1ac1311409e2bbc08bb8df8ee2934fefa489d6d5?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None).


<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##              main     #1105    +/-   ##
==========================================
  Coverage   100.00%   100.00%            
==========================================
  Files          189       189            
  Lines        19465     19568   +103     
  Branches      2426      2452    +26     
==========================================
+ Hits         19465     19568   +103     
```



</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/jackdewinter/pymarkdown/pull/1105?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None).


Patch:
diff --git a/docs/developer.md b/docs/developer.md
index 539c9b70..c64dcd5b 100644
--- a/docs/developer.md
+++ b/docs/developer.md
@@ -212,38 +212,46 @@ possible -> MD019/MD021, MD023
 possible -> md027 19/21/23/05/07 when blanks inside of list
          -> mod027 and most others
 
-Md001 Atx/SetExt hash_count
-MD004 UnorderedListStartMarkdownToken list_start_sequence
-Md005 NewListItemMarkdownToken indent_level, extracted_whitespace
-      UnorderedListStartMarkdownToken indent_level, extracted_whitespace, column_number, leading_spaces
-      OrderedListStartMarkdownToken indent_level, extracted_whitespace, column_number, leading_spaces
-MD006(d) NewListItemMarkdownToken indent_level, extracted_whitespace
-      UnorderedListStartMarkdownToken indent_level, extracted_whitespace
-MD007 NewListItemMarkdownToken indent_level, extracted_whitespace
-      UnorderedListStartMarkdownToken indent_level, extracted_whitespace
 MD009 line -> no trailing spaces
 MD010 line -> detabify
-MD019 AtxHeadingMarkdownToken extracted_whitespace
-MD021 AtxHeadingMarkdownToken extracted_whitespace, extra_end_data
-MD023 AtxHeadingMarkdownToken extracted_whitespace
-MD029 OrderedListStartMarkdownToken list_start_content
-md030 spaces after list markers, def = 1
-MD035 ThematicBreakMarkdownToken start_character,rest_of_line
-MD037 TextMarkdownToken (within emphasis) token_text
-MD038 InlineCodeSpanMarkdownToken span_text
-MD039 LinkStartMarkdownToken text_from_blocks
 MD047 line -> adds newline to end
-MD048 FencedCodeBlockMarkdownToken fence_character
 
-MD027   BlankLineMarkdownToken extracted_whitespace
-        ParagraphMarkdownToken extracted_whitespace
-        EndToken extracted_whitespace
+Md001 Atx/SetExt                                def   hash_count
+MD004 UnorderedListStartMarkdownToken           def   list_start_sequence
+Md005 NewListItemMarkdownToken                  2     indent_level, extracted_whitespace
+      UnorderedListStartMarkdownToken           def   indent_level, extracted_whitespace, column_number, leading_spaces
+      OrderedListStartMarkdownToken                   indent_level, extracted_whitespace, column_number, leading_spaces
+MD006(d) NewListItemMarkdownToken               def   indent_level, extracted_whitespace
+      UnorderedListStartMarkdownToken                 indent_level, extracted_whitespace
+MD007 NewListItemMarkdownToken                  3     indent_level, extracted_whitespace
+      UnorderedListStartMarkdownToken                 indent_level, extracted_whitespace
+MD019 AtxHeadingMarkdownToken                   def   extracted_whitespace
+MD021 AtxHeadingMarkdownToken                   def   extracted_whitespace, extra_end_data
+MD023 AtxHeadingMarkdownToken                   def   extracted_whitespace
+MD029 OrderedListStartMarkdownToken             def   list_start_content
+md030 ListStartMArkdownToken                    def   indent_level
+MD035 ThematicBreakMarkdownToken                def   start_character,rest_of_line
+MD037 TextMarkdownToken (within emphasis)       def   token_text
+MD038 InlineCodeSpanMarkdownToken               def   span_text
+MD039 LinkStartMarkdownToken                    def   text_from_blocks
+      ImageStartMarkdownToken
+MD044 TextMarkdownToken                         def   token_text
+      InlineCodeSpanMarkdownToken                     span_text
+      LinkReferenceDefinitionMarkdownToken            link_name, link_name_debug, link_title_raw, link_title
+      LinkStartMarkdownToken                          link_title, pre_link_title, text_from_blocks
+MD048 FencedCodeBlockMarkdownToken              def   fence_character
+
+MD027 BlankLineMarkdownToken                    5     extracted_whitespace
+      ParagraphMarkdownToken                          extracted_whitespace
+      EndToken                                        extracted_whitespace
         SetExt
         them
         fenc
         atx
         lrd
         Text end_whitespace
-       NewListItemMarkdownToken indent_level, extracted_whitespace
-      UnorderedListStartMarkdownToken indent_level, extracted_whitespace, column_number, leading_spaces
-      OrderedListStartMarkdownToken indent_level, extracted_whitespace, column_number, leading_spaces
+      NewListItemMarkdownToken            indent_level, extracted_whitespace
+      UnorderedListStartMarkdownToken     indent_level, extracted_whitespace, column_number, leading_spaces
+      OrderedListStartMarkdownToken       indent_level, extracted_whitespace, column_number, leading_spaces
+
+change docs for md044
diff --git a/newdocs/src/changelog.md b/newdocs/src/changelog.md
index 64993bcb..1ee67460 100644
--- a/newdocs/src/changelog.md
+++ b/newdocs/src/changelog.md
@@ -4,7 +4,8 @@
 
 ### Added
 
-- None
+- [Issue 826](https://github.com/jackdewinter/pymarkdown/issues/826)
+    - Added fix mode for Rule Md044
 
 ### Fixed
 
@@ -13,7 +14,9 @@
 
 ### Changed
 
-- None
+- [Issue 1103](https://github.com/jackdewinter/pymarkdown/issues/1103)
+    - added round of coalescing any text tokens separated during inline processing
+    - rewrote rule md037 to new text tokens
 
 ## Version 0.9.20 - Date: 2024-05-30
 
diff --git a/newdocs/src/plugins/rule_md044.md b/newdocs/src/plugins/rule_md044.md
index c498283b..0f73d0b3 100644
--- a/newdocs/src/plugins/rule_md044.md
+++ b/newdocs/src/plugins/rule_md044.md
@@ -3,7 +3,7 @@
 | Property | Value |
 | --- | -- |
 | Aliases | `md044`, `proper-names` |
-| Autofix Available | Pending |
+| Autofix Available | Yes |
 | Enabled By Default | Yes |
 
 ## Summary
@@ -83,8 +83,8 @@ this is a reparagraph
 
 ## Fix Description
 
-The auto-fix feature for this rule is scheduled to be added soon after the v1.0.0
-release.
+The specified word is replaced by the properly cased word presented in the
+configuration item.
 
 ## Configuration
 
diff --git a/newdocs/src/rules.md b/newdocs/src/rules.md
index 6bfc3945..ffe27352 100644
--- a/newdocs/src/rules.md
+++ b/newdocs/src/rules.md
@@ -611,7 +611,7 @@ Required heading structure.
 | Property | Value |
 | --- | -- |
 | Aliases | `md044`, `proper-names` |
-| Autofix Available | Pending |
+| Autofix Available | Yes |
 | Enabled By Default | Yes |
 
 <!--- pyml disable-next-line no-duplicate-heading-->
diff --git a/publish/coverage.json b/publish/coverage.json
index d058b5a0..dbc179ed 100644
--- a/publish/coverage.json
+++ b/publish/coverage.json
@@ -2,12 +2,12 @@
     "projectName": "pymarkdown",
     "reportSource": "pytest",
     "branchLevel": {
-        "totalMeasured": 4853,
-        "totalCovered": 4853
+        "totalMeasured": 4905,
+        "totalCovered": 4905
     },
     "lineLevel": {
-        "totalMeasured": 19465,
-        "totalCovered": 19465
+        "totalMeasured": 19568,
+        "totalCovered": 19568
     }
 }
 
diff --git a/publish/pylint_suppression.json b/publish/pylint_suppression.json
index c606ea0e..6d5513f4 100644
--- a/publish/pylint_suppression.json
+++ b/publish/pylint_suppression.json
@@ -397,7 +397,8 @@
         "pymarkdown/tokens/link_reference_definition_markdown_token.py": {
             "too-many-instance-attributes": 1,
             "too-many-arguments": 1,
-            "protected-access": 1
+            "protected-access": 1,
+            "too-many-return-statements": 1
         },
         "pymarkdown/tokens/link_start_markdown_token.py": {
             "protected-access": 1
@@ -503,6 +504,7 @@
         "too-many-boolean-expressions": 2,
         "protected-access": 25,
         "deprecated-decorator": 3,
-        "broad-exception-caught": 3
+        "broad-exception-caught": 3,
+        "too-many-return-statements": 1
     }
 }
\ No newline at end of file
diff --git a/pymarkdown/plugins/rule_md_044.py b/pymarkdown/plugins/rule_md_044.py
index 09267c58..2826eb35 100644
--- a/pymarkdown/plugins/rule_md_044.py
+++ b/pymarkdown/plugins/rule_md_044.py
@@ -3,7 +3,8 @@ Module to implement a plugin that ensures that specific proper names have
 the correct capitalization.
 """
 
-from typing import List, cast
+from dataclasses import dataclass
+from typing import List, Optional, cast
 
 from pymarkdown.general.constants import Constants
 from pymarkdown.general.parser_helper import ParserHelper
@@ -14,6 +15,7 @@ from pymarkdown.plugin_manager.plugin_details import (
 )
 from pymarkdown.plugin_manager.plugin_scan_context import PluginScanContext
 from pymarkdown.plugin_manager.rule_plugin import RulePlugin
+from pymarkdown.tokens.image_start_markdown_token import ImageStartMarkdownToken
 from pymarkdown.tokens.inline_code_span_markdown_token import (
     InlineCodeSpanMarkdownToken,
 )
@@ -25,6 +27,17 @@ from pymarkdown.tokens.markdown_token import EndMarkdownToken, MarkdownToken
 from pymarkdown.tokens.text_markdown_token import TextMarkdownToken
 
 
+@dataclass
+class FoundReplacement:
+    """
+    Class containing replacements found.
+    """
+
+    found_index: int
+    required_capitalization: str
+    part_context: str
+
+
 class RuleMd044(RulePlugin):
     """
     Class to implement a plugin that ensures that specific proper names have
@@ -37,6 +50,7 @@ class RuleMd044(RulePlugin):
         self.__check_in_code_blocks: bool = False
         self.__is_in_code_block: bool = False
         self.__names: str = ""
+        self.__replacement_items: List[FoundReplacement] = []
 
     def get_details(self) -> PluginDetailsV2:
         """
@@ -47,10 +61,11 @@ class RuleMd044(RulePlugin):
             plugin_id="MD044",
             plugin_enabled_by_default=True,
             plugin_description="Proper names should have the correct capitalization",
-            plugin_version="0.6.0",
+            plugin_version="0.7.0",
             plugin_url="https://pymarkdown.readthedocs.io/en/latest/plugins/rule_md044.md",
             plugin_configuration="names,code_blocks",
-            plugin_supports_fix=False,
+            plugin_supports_fix=True,
+            plugin_fix_level=2,
         )
 
     def starting_new_file(self) -> None:
@@ -106,6 +121,7 @@ class RuleMd044(RulePlugin):
         token: MarkdownToken,
         line_adjust: int,
         col_adjust: int,
+        part_context: str,
     ) -> None:
         original_found_text = original_source[
             found_index : found_index + len(required_capitalization)
@@ -120,9 +136,20 @@ class RuleMd044(RulePlugin):
             if after_found_index < len(original_source)
             else False
         )
-        if not is_character_after_match and not is_character_before_match:
+        if (
+            not is_character_after_match
+            and not is_character_before_match
+            and original_found_text != required_capitalization
+        ):
             assert len(original_found_text) == len(required_capitalization)
-            if original_found_text != required_capitalization:
+            if context.in_fix_mode:
+                # d1 = max(0,found_index-5)
+                # d2 = min(len(original_source), found_index+5)
+                # dd  = original_source[d1:d2]
+                self.__replacement_items.append(
+                    FoundReplacement(found_index, required_capitalization, part_context)
+                )
+            else:
                 extra_data = f"Expected: {required_capitalization}; Actual: {original_found_text}"
                 self.report_next_token_error(
                     context,
@@ -147,12 +174,15 @@ class RuleMd044(RulePlugin):
         next_name: str,
         context: PluginScanContext,
         token: MarkdownToken,
+        part_context: str,
     ) -> None:
         col_adjust, line_adjust = ParserHelper.adjust_for_newlines(
             string_to_check_lower, search_start, found_index
         )
         if line_adjust == 0 and start_y_offset == 0:
+            assert col_adjust >= 0
             col_adjust -= same_line_offset
+            assert same_line_offset <= 0
         line_adjust += start_y_offset
         if col_adjust == 0 and start_x_offset:
             col_adjust += (
@@ -170,6 +200,7 @@ class RuleMd044(RulePlugin):
             token,
             line_adjust,
             col_adjust,
+            part_context,
         )
 
     # pylint: enable=too-many-arguments
@@ -183,8 +214,11 @@ class RuleMd044(RulePlugin):
         same_line_offset: int = 0,
         start_x_offset: int = 0,
         start_y_offset: int = 0,
+        part_context: str = "",
+        keep_text_with_markers: bool = False,
     ) -> None:
-        string_to_check = ParserHelper.remove_all_from_text(string_to_check)
+        if not keep_text_with_markers:
+            string_to_check = ParserHelper.remove_all_from_text(string_to_check)
         string_to_check_lower = string_to_check.lower()
         for next_name in self.__proper_name_list:
             next_name_lower = next_name.lower()
@@ -202,6 +236,7 @@ class RuleMd044(RulePlugin):
                     next_name,
                     context,
                     token,
+                    part_context,
                 )
 
                 search_start = found_index + len(next_name)
@@ -218,6 +253,7 @@ class RuleMd044(RulePlugin):
         full_link_text: str,
         string_to_check: str,
         same_line_offset: int,
+        part_context: str,
     ) -> None:
         start_x_offset = 0
         start_y_offset = 0
@@ -232,6 +268,7 @@ class RuleMd044(RulePlugin):
             same_line_offset,
             start_x_offset,
             start_y_offset,
+            part_context,
         )
 
     # pylint: enable=too-many-arguments
@@ -261,7 +298,7 @@ class RuleMd044(RulePlugin):
                     link_body,
                 ]
             )
-            same_line_offset = len(full_link_text) + 1
+            same_line_offset = -(len(full_link_text))
             assert link_token.active_link_title is not None
             self.__adjust_for_newlines_and_search(
                 context,
@@ -270,6 +307,34 @@ class RuleMd044(RulePlugin):
                 full_link_text,
                 link_token.active_link_title,
                 same_line_offset,
+                "x",
+            )
+
+    def __handle_inline_link_fix(
+        self, context: PluginScanContext, token: MarkdownToken
+    ) -> None:
+        link_token = cast(LinkStartMarkdownToken, token)
+        assert link_token.link_title is not None
+        self.__search_for_matches(
+            link_token.link_title, context, token, 0, part_context="link_title"
+        )
+        self.__search_for_matches(
+            link_token.text_from_blocks,
+            context,
+            token,
+            0,
+            part_context="text_from_blocks",
+        )
+        if (
+            link_token.label_type == Constants.link_type__inline
+            and link_token.pre_link_title
+        ):
+            self.__search_for_matches(
+                link_token.pre_link_title,
+                context,
+                token,
+                0,
+                part_context="pre_link_title",
             )
 
     def __handle_inline_image(
@@ -281,7 +346,10 @@ class RuleMd044(RulePlugin):
             link_token.text_from_blocks, context, token, same_line_offset
         )
 
-        if link_token.label_type == Constants.link_type__inline:
+        if (
+            link_token.label_type == Constants.link_type__inline
+            and not context.in_fix_mode
+        ):
             assert link_token.before_link_whitespace is not None
             assert link_token.before_title_whitespace is not None
             assert link_token.inline_title_bounding_character is not None
@@ -294,7 +362,7 @@ class RuleMd044(RulePlugin):
                 ]
             )
             full_link_text = f"![{link_token.text_from_blocks}]({link_body}"
-            same_line_offset = len(full_link_text) + 1
+            same_line_offset = -(len(full_link_text))
             assert link_token.active_link_title is not None
             self.__adjust_for_newlines_and_search(
                 context,
@@ -303,6 +371,20 @@ class RuleMd044(RulePlugin):
                 full_link_text,
                 link_token.active_link_title,
                 same_line_offset,
+                "y",
+            )
+        elif context.in_fix_mode:
+            image_token = cast(ImageStartMarkdownToken, token)
+            assert image_token.link_title is not None
+            self.__search_for_matches(
+                image_token.link_title, context, token, 0, part_context="link_title"
+            )
+            self.__search_for_matches(
+                image_token.text_from_blocks,
+                context,
+                token,
+                0,
+                part_context="text_from_blocks",
             )
 
     def __handle_link_reference_definition(
@@ -311,7 +393,26 @@ class RuleMd044(RulePlugin):
         lrd_token = cast(LinkReferenceDefinitionMarkdownToken, token)
         link_name = lrd_token.link_name_debug or lrd_token.link_name
         same_line_offset = -1
-        self.__search_for_matches(link_name, context, token, same_line_offset)
+        if context.in_fix_mode:
+            if lrd_token.link_name_debug:
+                self.__search_for_matches(
+                    lrd_token.link_name_debug,
+                    context,
+                    token,
+                    same_line_offset,
+                    part_context="link_name_debug",
+                )
+            self.__search_for_matches(
+                lrd_token.link_name,
+                context,
+                token,
+                same_line_offset,
+                part_context="link_name",
+            )
+        else:
+            self.__search_for_matches(
+                link_name, context, token, same_line_offset, part_context="link_name"
+            )
 
         assert lrd_token.link_destination_whitespace is not None
         assert lrd_token.link_destination is not None
@@ -329,30 +430,62 @@ class RuleMd044(RulePlugin):
         )
         same_line_offset = -(len(full_link_text) - 1)
         assert lrd_token.link_title_raw is not None
-        self.__adjust_for_newlines_and_search(
-            context,
-            token,
-            full_link_text,
-            full_link_text,
-            lrd_token.link_title_raw,
-            same_line_offset,
-        )
+        if context.in_fix_mode:
+            self.__adjust_for_newlines_and_search(
+                context,
+                token,
+                full_link_text,
+                full_link_text,
+                lrd_token.link_title_raw,
+                same_line_offset,
+                "link_title_raw",
+            )
+            if lrd_token.link_title:
+                self.__adjust_for_newlines_and_search(
+                    context,
+                    token,
+                    full_link_text,
+                    full_link_text,
+                    lrd_token.link_title,
+                    same_line_offset,
+                    "link_title",
+                )
+        else:
+            self.__adjust_for_newlines_and_search(
+                context,
+                token,
+                full_link_text,
+                full_link_text,
+                lrd_token.link_title_raw,
+                same_line_offset,
+                "link_title_raw",
+            )
 
     def __handle_inline_code_span(
         self, context: PluginScanContext, token: MarkdownToken
     ) -> None:
         code_span_token = cast(InlineCodeSpanMarkdownToken, token)
-        same_line_offset = len(code_span_token.extracted_start_backticks) + len(
-            code_span_token.leading_whitespace
+        same_line_offset = -(
+            len(code_span_token.extracted_start_backticks)
+            + len(code_span_token.leading_whitespace)
         )
         self.__search_for_matches(
-            code_span_token.span_text, context, token, same_line_offset
+            code_span_token.span_text,
+            context,
+            token,
+            same_line_offset,
+            keep_text_with_markers=context.in_fix_mode,
         )
 
     def __handle_text(self, context: PluginScanContext, token: MarkdownToken) -> None:
         text_token = cast(TextMarkdownToken, token)
         if not self.__is_in_code_block or self.__check_in_code_blocks:
-            self.__search_for_matches(text_token.token_text, context, token)
+            self.__search_for_matches(
+                text_token.token_text,
+                context,
+                token,
+                keep_text_with_markers=context.in_fix_mode,
+            )
 
     def next_token(self, context: PluginScanContext, token: MarkdownToken) -> None:
         """
@@ -360,11 +493,12 @@ class RuleMd044(RulePlugin):
         """
         if not self.__proper_name_list:
             return
+        self.__replacement_items.clear()
         if token.is_text:
             self.__handle_text(context, token)
         elif token.is_inline_code_span:
             self.__handle_inline_code_span(context, token)
-        elif token.is_inline_link_end:
+        elif token.is_inline_link_end and not context.in_fix_mode:
             self.__handle_inline_link_end(context, token)
         elif token.is_inline_image:
             self.__handle_inline_image(context, token)
@@ -374,3 +508,108 @@ class RuleMd044(RulePlugin):
             self.__is_in_code_block = True
         elif token.is_code_block_end:
             self.__is_in_code_block = False
+        elif context.in_fix_mode:
+            if token.is_inline_link:
+                self.__handle_inline_link_fix(context, token)
+
+        if self.__replacement_items:
+            self.__apply_replacement_items(context, token)
+
+    def __apply_replacement_items(
+        self, context: PluginScanContext, token: MarkdownToken
+    ) -> None:
+        if token.is_text:
+            text_token = cast(TextMarkdownToken, token)
+            self.__apply_normal_replacement(
+                context, token, text_token.token_text, "token_text"
+            )
+        elif token.is_inline_code_span:
+            code_span_token = cast(InlineCodeSpanMarkdownToken, token)
+            self.__apply_normal_replacement(
+                context, token, code_span_token.span_text, "span_text"
+            )
+        elif token.is_link_reference_definition:
+            lrd_token = cast(LinkReferenceDefinitionMarkdownToken, token)
+            self.__apply_matching_replacement(
+                context, token, lrd_token.link_name, "link_name"
+            )
+            if lrd_token.link_name_debug:
+                self.__apply_matching_replacement(
+                    context, token, lrd_token.link_name_debug, "link_name_debug"
+                )
+            self.__apply_matching_replacement(
+                context, token, lrd_token.link_title_raw, "link_title_raw"
+            )
+            if lrd_token.link_title:
+                self.__apply_matching_replacement(
+                    context, token, lrd_token.link_title, "link_title"
+                )
+        elif token.is_inline_link:
+            link_token = cast(LinkStartMarkdownToken, token)
+            self.__apply_matching_replacement(
+                context, token, link_token.link_title, "link_title"
+            )
+            self.__apply_matching_replacement(
+                context, token, link_token.pre_link_title, "pre_link_title"
+            )
+            self.__apply_matching_replacement(
+                context, token, link_token.text_from_blocks, "text_from_blocks"
+            )
+        else:
+            assert (
+                token.is_inline_image
+            ), "If not anything else, must be an inline image."
+            image_token = cast(ImageStartMarkdownToken, token)
+            self.__apply_matching_replacement(
+                context, token, image_token.link_title, "link_title"
+            )
+            self.__apply_matching_replacement(
+                context, token, image_token.text_from_blocks, "text_from_blocks"
+            )
+
+    def __apply_normal_replacement(
+        self,
+        context: PluginScanContext,
+        token: MarkdownToken,
+        text_to_check: Optional[str],
+        name_to_check: str,
+    ) -> None:
+        assert text_to_check is not None
+        new_text = text_to_check
+        for replacement_item in self.__replacement_items:
+            new_text = (
+                new_text[: replacement_item.found_index]
+                + replacement_item.required_capitalization
+                + new_text[
+                    replacement_item.found_index
+                    + len(replacement_item.required_capitalization) :
+                ]
+            )
+        assert new_text != text_to_check, "The new text must always be different."
+        self.register_fix_token_request(
+            context, token, "next_token", name_to_check, new_text
+        )
+
+    def __apply_matching_replacement(
+        self,
+        context: PluginScanContext,
+        token: MarkdownToken,
+        text_to_check: Optional[str],
+        name_to_check: str,
+    ) -> None:
+        assert text_to_check is not None
+        new_text = text_to_check
+        for replacement_item in self.__replacement_items:
+            if replacement_item.part_context == name_to_check:
+                new_text = (
+                    new_text[: replacement_item.found_index]
+                    + replacement_item.required_capitalization
+                    + new_text[
+                        replacement_item.found_index
+                        + len(replacement_item.required_capitalization) :
+                    ]
+                )
+        if new_text != text_to_check:
+            self.register_fix_token_request(
+                context, token, "next_token", name_to_check, new_text
+            )
diff --git a/pymarkdown/tokens/link_reference_definition_markdown_token.py b/pymarkdown/tokens/link_reference_definition_markdown_token.py
index 4e3e2804..d95af4e6 100644
--- a/pymarkdown/tokens/link_reference_definition_markdown_token.py
+++ b/pymarkdown/tokens/link_reference_definition_markdown_token.py
@@ -199,6 +199,7 @@ class LinkReferenceDefinitionMarkdownToken(LeafMarkdownToken):
         """
         return self.__link_title_whitespace
 
+    # pylint: disable=too-many-return-statements
     @override
     def _modify_token(self, field_name: str, field_value: Union[str, int]) -> bool:
         if field_name == "link_destination_whitespace" and isinstance(field_value, str):
@@ -215,6 +216,13 @@ class LinkReferenceDefinitionMarkdownToken(LeafMarkdownToken):
             )
             super()._set_extra_data(extra_data)
             return True
+        if field_name == "link_name" and isinstance(field_value, str):
+            self.__link_name = field_value
+            extra_data = self.__validate_proper_fields_are_valid(
+                self.extracted_whitespace
+            )
+            super()._set_extra_data(extra_data)
+            return True
         if field_name == "link_name_debug" and isinstance(field_value, str):
             self.__link_name_debug = field_value
             extra_data = self.__validate_proper_fields_are_valid(
@@ -222,8 +230,24 @@ class LinkReferenceDefinitionMarkdownToken(LeafMarkdownToken):
             )
             super()._set_extra_data(extra_data)
             return True
+        if field_name == "link_title" and isinstance(field_value, str):
+            self.__link_title = field_value
+            extra_data = self.__validate_proper_fields_are_valid(
+                self.extracted_whitespace
+            )
+            super()._set_extra_data(extra_data)
+            return True
+        if field_name == "link_title_raw" and isinstance(field_value, str):
+            self.__link_title_raw = field_value
+            extra_data = self.__validate_proper_fields_are_valid(
+                self.extracted_whitespace
+            )
+            super()._set_extra_data(extra_data)
+            return True
         return super()._modify_token(field_name, field_value)
 
+    # pylint: enable=too-many-return-statements
+
     def register_for_markdown_transform(
         self, registration_function: RegisterMarkdownTransformHandlersProtocol
     ) -> None:
diff --git a/pymarkdown/tokens/reference_markdown_token.py b/pymarkdown/tokens/reference_markdown_token.py
index 585b1afc..505bbd51 100644
--- a/pymarkdown/tokens/reference_markdown_token.py
+++ b/pymarkdown/tokens/reference_markdown_token.py
@@ -176,6 +176,13 @@ class ReferenceMarkdownToken(InlineMarkdownToken):
         """
         return self.__link_title
 
+    @property
+    def pre_link_title(self) -> Optional[str]:
+        """
+        Returns the text associated with the link's title.
+        """
+        return self.__pre_link_title
+
     @property
     def active_link_title(self) -> Optional[str]:
         """
@@ -254,6 +261,16 @@ class ReferenceMarkdownToken(InlineMarkdownToken):
             self.__text_from_blocks = field_value
             self.__compose_extra_data_field(self.token_name)
 
+            return True
+        if field_name == "link_title" and isinstance(field_value, str):
+            self.__link_title = field_value
+            self.__compose_extra_data_field(self.token_name)
+
+            return True
+        if field_name == "pre_link_title" and isinstance(field_value, str):
+            self.__pre_link_title = field_value
+            self.__compose_extra_data_field(self.token_name)
+
             return True
         return False
 


Test patch:
diff --git a/publish/test-results.json b/publish/test-results.json
index 54943169..c6ce0776 100644
--- a/publish/test-results.json
+++ b/publish/test-results.json
@@ -1468,7 +1468,7 @@
         },
         {
             "name": "test.rules.test_md044",
-            "totalTests": 39,
+            "totalTests": 98,
             "failedTests": 0,
             "errorTests": 0,
             "skippedTests": 0,
diff --git a/test/api/test_api_scan.py b/test/api/test_api_scan.py
index 9406fc8b..6976716c 100644
--- a/test/api/test_api_scan.py
+++ b/test/api/test_api_scan.py
@@ -196,6 +196,7 @@ def test_api_scan_recursive_for_directory():
         f"{docs_prefix}advanced_scanning.md",
         f"{docs_prefix}api-usage.md",
         f"{docs_prefix}api.md",
+        f"{docs_prefix}developer.md",
         f"{extensions_prefix}front-matter.md",
         f"{docs_prefix}old_README.md",
         f"{docs_prefix}pre-commit.md",
@@ -236,7 +237,7 @@ def test_api_scan_recursive_for_directory():
     for i in scan_result.scan_failures:
         itemized_scan_failures = itemized_scan_failures + "\n" + str(i)
     print(itemized_scan_failures)
-    assert len(scan_result.scan_failures) == 68
+    assert len(scan_result.scan_failures) == 70
 
     scan_failures = []
     for i in scan_result.scan_failures:
diff --git a/test/resources/rules/md044/good_atx_heading_text.md b/test/resources/rules/md044/good_atx_heading_text.md
deleted file mode 100644
index 48f78c64..00000000
--- a/test/resources/rules/md044/good_atx_heading_text.md
+++ /dev/null
@@ -1,3 +0,0 @@
-# This section contains a paragraph
-
-yes, a paragraph is contained.
diff --git a/test/resources/rules/md044/good_block_quote_text.md b/test/resources/rules/md044/good_block_quote_text.md
deleted file mode 100644
index fe72fc98..00000000
--- a/test/resources/rules/md044/good_block_quote_text.md
+++ /dev/null
@@ -1,3 +0,0 @@
-# This section contains a paragraph
-
-> yes, a paragraph is contained.
diff --git a/test/resources/rules/md044/good_code_span_text.md b/test/resources/rules/md044/good_code_span_text.md
deleted file mode 100644
index 519b9f8c..00000000
--- a/test/resources/rules/md044/good_code_span_text.md
+++ /dev/null
@@ -1,3 +0,0 @@
-# This section contains a paragraph
-
-yes, `a paragraph is` contained.
diff --git a/test/resources/rules/md044/good_code_span_text_multiple_lines.md b/test/resources/rules/md044/good_code_span_text_multiple_lines.md
deleted file mode 100644
index 9e5221ef..00000000
--- a/test/resources/rules/md044/good_code_span_text_multiple_lines.md
+++ /dev/null
@@ -1,4 +0,0 @@
-# This section contains a paragraph
-
-yes, `a paragraph a
-is a paragraph` contained.
diff --git a/test/resources/rules/md044/good_collapsed_image.md b/test/resources/rules/md044/good_collapsed_image.md
deleted file mode 100644
index aaaabc81..00000000
--- a/test/resources/rules/md044/good_collapsed_image.md
+++ /dev/null
@@ -1,7 +0,0 @@
-this is a
-![collapsed
-paragraph][]
-link
-
-[collapsed
-paragraph]: /url "a paragraph title"
diff --git a/test/resources/rules/md044/good_collapsed_image_multiple.md b/test/resources/rules/md044/good_collapsed_image_multiple.md
deleted file mode 100644
index 2bd92b7c..00000000
--- a/test/resources/rules/md044/good_collapsed_image_multiple.md
+++ /dev/null
@@ -1,8 +0,0 @@
-this is a
-![collapsed
-paragraph][]
-link
-
-[collapsed
-paragraph]: /url "a
-big paragraph title"
diff --git a/test/resources/rules/md044/good_collapsed_link.md b/test/resources/rules/md044/good_collapsed_link.md
deleted file mode 100644
index a02458ee..00000000
--- a/test/resources/rules/md044/good_collapsed_link.md
+++ /dev/null
@@ -1,7 +0,0 @@
-this is a
-[collapsed
-paragraph][]
-link
-
-[collapsed
-paragraph]: /url "a paragraph title"
diff --git a/test/resources/rules/md044/good_collapsed_link_multiple.md b/test/resources/rules/md044/good_collapsed_link_multiple.md
deleted file mode 100644
index afbc7dcd..00000000
--- a/test/resources/rules/md044/good_collapsed_link_multiple.md
+++ /dev/null
@@ -1,8 +0,0 @@
-this is a
-[collapsed
-link paragraph][]
-link
-
-[collapsed
-link paragraph]: /url "a
-big paragraph title"
diff --git a/test/resources/rules/md044/good_fenced_code_block_text.md b/test/resources/rules/md044/good_fenced_code_block_text.md
deleted file mode 100644
index 6e71ef0f..00000000
--- a/test/resources/rules/md044/good_fenced_code_block_text.md
+++ /dev/null
@@ -1,5 +0,0 @@
-# This section contains a paragraph
-
-```text
-yes, a paragraph is contained.
-```
diff --git a/test/resources/rules/md044/good_full_image.md b/test/resources/rules/md044/good_full_image.md
deleted file mode 100644
index 7cffa052..00000000
--- a/test/resources/rules/md044/good_full_image.md
+++ /dev/null
@@ -1,5 +0,0 @@
-this is
-![a paragraph inspired link][bar]
-link
-
-[bar]: /url "a paragraph title"
diff --git a/test/resources/rules/md044/good_full_image_multiple.md b/test/resources/rules/md044/good_full_image_multiple.md
deleted file mode 100644
index df54bae8..00000000
--- a/test/resources/rules/md044/good_full_image_multiple.md
+++ /dev/null
@@ -1,9 +0,0 @@
-this is
-![a
-paragraph inspired link][ba
-r]
-link
-
-[ba
-r]: /url "a
-paragraph title"
diff --git a/test/resources/rules/md044/good_full_link.md b/test/resources/rules/md044/good_full_link.md
deleted file mode 100644
index d0a54cbb..00000000
--- a/test/resources/rules/md044/good_full_link.md
+++ /dev/null
@@ -1,5 +0,0 @@
-this is
-[a paragraph inspired link][bar]
-link
-
-[bar]: /url "a paragraph title"
diff --git a/test/resources/rules/md044/good_full_link_multiple.md b/test/resources/rules/md044/good_full_link_multiple.md
deleted file mode 100644
index 44a7892c..00000000
--- a/test/resources/rules/md044/good_full_link_multiple.md
+++ /dev/null
@@ -1,9 +0,0 @@
-this is
-[a
-paragraph inspired link][ba
-r]
-link
-
-[ba
-r]: /url "a
-paragraph title"
diff --git a/test/resources/rules/md044/good_html_block_text.md b/test/resources/rules/md044/good_html_block_text.md
deleted file mode 100644
index 96b5c9ba..00000000
--- a/test/resources/rules/md044/good_html_block_text.md
+++ /dev/null
@@ -1,5 +0,0 @@
-# This section contains a paragraph
-
-<!--
-yes, a paragraph is contained.
--->
diff --git a/test/resources/rules/md044/good_indented_code_block_text.md b/test/resources/rules/md044/good_indented_code_block_text.md
deleted file mode 100644
index 2e803a23..00000000
--- a/test/resources/rules/md044/good_indented_code_block_text.md
+++ /dev/null
@@ -1,3 +0,0 @@
-# This section contains a paragraph
-
-    yes, a paragraph is contained.
diff --git a/test/resources/rules/md044/good_inline_image.md b/test/resources/rules/md044/good_inline_image.md
deleted file mode 100644
index 5085a102..00000000
--- a/test/resources/rules/md044/good_inline_image.md
+++ /dev/null
@@ -1,1 +0,0 @@
-![a paragraph inspired link](/paragraph "paragraph")
diff --git a/test/resources/rules/md044/good_inline_image_multiple_lines.md b/test/resources/rules/md044/good_inline_image_multiple_lines.md
deleted file mode 100644
index 9e50656e..00000000
--- a/test/resources/rules/md044/good_inline_image_multiple_lines.md
+++ /dev/null
@@ -1,3 +0,0 @@
-![a paragraph inspired link](
-/paragraph
-"paragraph")
diff --git a/test/resources/rules/md044/good_inline_image_multiple_lines_two.md b/test/resources/rules/md044/good_inline_image_multiple_lines_two.md
deleted file mode 100644
index a22a558e..00000000
--- a/test/resources/rules/md044/good_inline_image_multiple_lines_two.md
+++ /dev/null
@@ -1,4 +0,0 @@
-![a paragraph inspired link](
-/paragraph
-"this is
-a very long paragraph")
diff --git a/test/resources/rules/md044/good_inline_link.md b/test/resources/rules/md044/good_inline_link.md
deleted file mode 100644
index 7da3ebec..00000000
--- a/test/resources/rules/md044/good_inline_link.md
+++ /dev/null
@@ -1,1 +0,0 @@
-[a paragraph inspired link](/paragraph "paragraph")
diff --git a/test/resources/rules/md044/good_inline_link_multiple_lines.md b/test/resources/rules/md044/good_inline_link_multiple_lines.md
deleted file mode 100644
index 34be6a7f..00000000
--- a/test/resources/rules/md044/good_inline_link_multiple_lines.md
+++ /dev/null
@@ -1,3 +0,0 @@
-[a paragraph inspired link](
-/paragraph
-"paragraph")
diff --git a/test/resources/rules/md044/good_inline_link_multiple_lines_three.md b/test/resources/rules/md044/good_inline_link_multiple_lines_three.md
deleted file mode 100644
index 29afe41f..00000000
--- a/test/resources/rules/md044/good_inline_link_multiple_lines_three.md
+++ /dev/null
@@ -1,4 +0,0 @@
-[a
-paragraph inspired link](
-/paragraph
-"paragraph")
diff --git a/test/resources/rules/md044/good_inline_link_multiple_lines_two.md b/test/resources/rules/md044/good_inline_link_multiple_lines_two.md
deleted file mode 100644
index 59e42d42..00000000
--- a/test/resources/rules/md044/good_inline_link_multiple_lines_two.md
+++ /dev/null
@@ -1,4 +0,0 @@
-[a paragraph inspired link](
-/paragraph
-"this is
-a very long paragraph")
diff --git a/test/resources/rules/md044/good_paragraph_text.md b/test/resources/rules/md044/good_paragraph_text.md
deleted file mode 100644
index 464d998e..00000000
--- a/test/resources/rules/md044/good_paragraph_text.md
+++ /dev/null
@@ -1,1 +0,0 @@
-this is a paragraph without any capitalization errors
diff --git a/test/resources/rules/md044/good_paragraph_text_end.md b/test/resources/rules/md044/good_paragraph_text_end.md
deleted file mode 100644
index ff2b2e13..00000000
--- a/test/resources/rules/md044/good_paragraph_text_end.md
+++ /dev/null
@@ -1,1 +0,0 @@
-ends with the word paragraph
diff --git a/test/resources/rules/md044/good_paragraph_text_followed_non_alpha.md b/test/resources/rules/md044/good_paragraph_text_followed_non_alpha.md
deleted file mode 100644
index f89ca592..00000000
--- a/test/resources/rules/md044/good_paragraph_text_followed_non_alpha.md
+++ /dev/null
@@ -1,1 +0,0 @@
-this is a paragraph.
diff --git a/test/resources/rules/md044/good_paragraph_text_multiples.md b/test/resources/rules/md044/good_paragraph_text_multiples.md
deleted file mode 100644
index a8a5d1a2..00000000
--- a/test/resources/rules/md044/good_paragraph_text_multiples.md
+++ /dev/null
@@ -1,1 +0,0 @@
-this is a paragraph with paragraph capitalization errors
diff --git a/test/resources/rules/md044/good_paragraph_text_multiples_on_multiple_lines.md b/test/resources/rules/md044/good_paragraph_text_multiples_on_multiple_lines.md
deleted file mode 100644
index 6128eea1..00000000
--- a/test/resources/rules/md044/good_paragraph_text_multiples_on_multiple_lines.md
+++ /dev/null
@@ -1,4 +0,0 @@
-this is a sample where the word paragraph should
-appear on multiple lines so we can make sure that
-advancing the line and column for the paragraph
-error reporting works.
diff --git a/test/resources/rules/md044/good_paragraph_text_prefix.md b/test/resources/rules/md044/good_paragraph_text_prefix.md
deleted file mode 100644
index 174fcd60..00000000
--- a/test/resources/rules/md044/good_paragraph_text_prefix.md
+++ /dev/null
@@ -1,1 +0,0 @@
-nothing like a good reparagraph to go
diff --git a/test/resources/rules/md044/good_paragraph_text_start.md b/test/resources/rules/md044/good_paragraph_text_start.md
deleted file mode 100644
index 534f77cb..00000000
--- a/test/resources/rules/md044/good_paragraph_text_start.md
+++ /dev/null
@@ -1,1 +0,0 @@
-paragraph is how this starts
diff --git a/test/resources/rules/md044/good_paragraph_text_suffix.md b/test/resources/rules/md044/good_paragraph_text_suffix.md
deleted file mode 100644
index db51c898..00000000
--- a/test/resources/rules/md044/good_paragraph_text_suffix.md
+++ /dev/null
@@ -1,1 +0,0 @@
-this is paragraphing at its best
diff --git a/test/resources/rules/md044/good_setext_heading_text.md b/test/resources/rules/md044/good_setext_heading_text.md
deleted file mode 100644
index 12af3303..00000000
--- a/test/resources/rules/md044/good_setext_heading_text.md
+++ /dev/null
@@ -1,4 +0,0 @@
-This section contains a paragraph
-===
-
-yes, a paragraph is contained.
diff --git a/test/rules/test_md044.py b/test/rules/test_md044.py
index 5a1e3148..fd8201c5 100644
--- a/test/rules/test_md044.py
+++ b/test/rules/test_md044.py
@@ -3,1536 +3,976 @@ Module to provide tests related to the MD044 rule.
 """
 
 import os
-from test.markdown_scanner import MarkdownScanner
-from test.rules.utils import execute_query_configuration_test, pluginQueryConfigTest
+from test.rules.utils import (
+    execute_configuration_test,
+    execute_fix_test,
+    execute_query_configuration_test,
+    execute_scan_test,
+    id_test_plug_rule_fn,
+    pluginConfigErrorTest,
+    pluginQueryConfigTest,
+    pluginRuleTest,
+)
 
 import pytest
 
-# pylint: disable=too-many-lines
-
-
-@pytest.mark.rules
-def test_md044_bad_configuration_names():
-    """
-    Test to verify that a configuration error is thrown when supplying the
-    names value with an integer that is not a string.
-    """
-
-    # Arrange
-    scanner = MarkdownScanner()
-    source_path = os.path.join(
-        "test", "resources", "rules", "md044", "good_paragraph_text.md"
-    )
-    supplied_arguments = [
-        "--set",
-        "plugins.md044.names=$#1",
-        "--strict-config",
-        "scan",
-        source_path,
-    ]
-
-    expected_return_code = 1
-    expected_output = ""
-    expected_error = (
-        "BadPluginError encountered while configuring plugins:\n"
-        + "The value for property 'plugins.md044.names' must be of type 'str'."
-    )
-
-    # Act
-    execute_results = scanner.invoke_main(arguments=supplied_arguments)
-
-    # Assert
-    execute_results.assert_results(
-        expected_output, expected_error, expected_return_code
-    )
-
-
-@pytest.mark.rules
-def test_md044_bad_configuration_names_empty_elements():
-    """
-    Test to verify that a configuration error is thrown when supplying the
-    names value with a string with empty elements.
-    """
-
-    # Arrange
-    scanner = MarkdownScanner()
-    source_path = os.path.join(
-        "test", "resources", "rules", "md044", "good_paragraph_text.md"
-    )
-    supplied_arguments = [
-        "--set",
-        "plugins.md044.names=,,",
-        "--strict-config",
-        "scan",
-        source_path,
-    ]
-
-    expected_return_code = 1
-    expected_output = ""
-    expected_error = (
-        "BadPluginError encountered while configuring plugins:\n"
-        + "Elements in the comma-separated list cannot be empty."
-    )
-
-    # Act
-    execute_results = scanner.invoke_main(arguments=supplied_arguments)
-
-    # Assert
-    execute_results.assert_results(
-        expected_output, expected_error, expected_return_code
-    )
-
-
-@pytest.mark.rules
-def test_md044_bad_configuration_names_repeated_elements():
-    """
-    Test to verify that a configuration error is thrown when supplying the
-    names value with a string with repeated elements.
-    """
-
-    # Arrange
-    scanner = MarkdownScanner()
-    source_path = os.path.join(
-        "test", "resources", "rules", "md044", "good_paragraph_text.md"
-    )
-    supplied_arguments = [
-        "--set",
-        "plugins.md044.names=one,two,One",
-        "--strict-config",
-        "scan",
-        source_path,
-    ]
-
-    expected_return_code = 1
-    expected_output = ""
-    expected_error = (
-        "BadPluginError encountered while configuring plugins:\n"
-        + "Element `One` is already present in the list as `one`."
-    )
-
-    # Act
-    execute_results = scanner.invoke_main(arguments=supplied_arguments)
-
-    # Assert
-    execute_results.assert_results(
-        expected_output, expected_error, expected_return_code
-    )
-
-
-@pytest.mark.rules
-def test_md044_bad_configuration_code_blocks():
-    """
-    Test to verify that a configuration error is thrown when supplying the
-    code_blocks value with a string instead of a boolean.
-    """
-
-    # Arrange
-    scanner = MarkdownScanner()
-    source_path = os.path.join(
-        "test", "resources", "rules", "md044", "good_paragraph_text.md"
-    )
-    supplied_arguments = [
-        "--set",
-        "plugins.md044.code_blocks=one",
-        "--strict-config",
-        "scan",
-        source_path,
-    ]
-
-    expected_return_code = 1
-    expected_output = ""
-    expected_error = (
-        "BadPluginError encountered while configuring plugins:\n"
-        + "The value for property 'plugins.md044.code_blocks' must be of type 'bool'."
-    )
-
-    # Act
-    execute_results = scanner.invoke_main(arguments=supplied_arguments)
-
-    # Assert
-    execute_results.assert_results(
-        expected_output, expected_error, expected_return_code
-    )
-
-
-@pytest.mark.rules
-def test_md044_good_paragraph_text():
-    """
-    Test to make sure this rule does not trigger with a document that
-    contains normal paragraphs containing the word with proper capitalization.
-    """
-
-    # Arrange
-    scanner = MarkdownScanner()
-    source_path = os.path.join(
-        "test", "resources", "rules", "md044", "good_paragraph_text.md"
-    )
-    supplied_arguments = [
-        "--set",
-        "plugins.md044.names=paragraph",
-        "scan",
-        source_path,
-    ]
-
-    expected_return_code = 0
-    expected_output = ""
-    expected_error = ""
-
-    # Act
-    execute_results = scanner.invoke_main(arguments=supplied_arguments)
-
-    # Assert
-    execute_results.assert_results(
-        expected_output, expected_error, expected_return_code
-    )
-
-
-@pytest.mark.rules
-def test_md044_bad_paragraph_text():
-    """
-    Test to make sure this rule does trigger with a document that
-    contains normal paragraphs containing the word with configuration
-    to specify proper capitalization.
-    """
-
-    # Arrange
-    scanner = MarkdownScanner()
-    source_path = os.path.join(
-        "test", "resources", "rules", "md044", "good_paragraph_text.md"
-    )
-    supplied_arguments = [
-        "--set",
-        "plugins.md044.names=ParaGraph",
-        "scan",
-        source_path,
-    ]
-
-    expected_return_code = 1
-    expected_output = (
-        f"{source_path}:1:11: "
-        + "MD044: Proper names should have the correct capitalization "
-        + "[Expected: ParaGraph; Actual: paragraph] (proper-names)"
-    )
-    expected_error = ""
-
-    # Act
-    execute_results = scanner.invoke_main(arguments=supplied_arguments)
-
-    # Assert
-    execute_results.assert_results(
-        expected_output, expected_error, expected_return_code
-    )
-
-
-@pytest.mark.rules
-def test_md044_good_paragraph_text_prefix():
-    """
-    Test to make sure this rule does not trigger with a document that
-    contains normal paragraphs containing the word with improper capitalization
-    and a prefix, and configuration to match the main word.
-    """
-
-    # Arrange
-    scanner = MarkdownScanner()
-    source_path = os.path.join(
-        "test", "resources", "rules", "md044", "good_paragraph_text_prefix.md"
-    )
-    supplied_arguments = [
-        "--set",
-        "plugins.md044.names=ParaGraph",
-        "scan",
-        source_path,
-    ]
-
-    expected_return_code = 0
-    expected_output = ""
-    expected_error = ""
-
-    # Act
-    execute_results = scanner.invoke_main(arguments=supplied_arguments)
-
-    # Assert
-    execute_results.assert_results(
-        expected_output, expected_error, expected_return_code
-    )
-
-
-@pytest.mark.rules
-def test_md044_good_paragraph_text_suffix():
-    """
-    Test to make sure this rule does not trigger with a document that
-    contains normal paragraphs containing the word with improper capitalization
-    and a suffix, and configuration to match the main word.
-    """
-
-    # Arrange
-    scanner = MarkdownScanner()
-    source_path = os.path.join(
-        "test", "resources", "rules", "md044", "good_paragraph_text_suffix.md"
-    )
-    supplied_arguments = [
-        "--set",
-        "plugins.md044.names=ParaGraph",
-        "scan",
-        source_path,
-    ]
-
-    expected_return_code = 0
-    expected_output = ""
-    expected_error = ""
-
-    # Act
-    execute_results = scanner.invoke_main(arguments=supplied_arguments)
-
-    # Assert
-    execute_results.assert_results(
-        expected_output, expected_error, expected_return_code
-    )
-
-
-@pytest.mark.rules
-def test_md044_bad_paragraph_text_start():
-    """
-    Test to make sure this rule does trigger with a document that
-    contains normal paragraphs containing the word with improper capitalization
-    and configuration to match the main word, where it occurs at the very
-    start of the line.
-    """
-
-    # Arrange
-    scanner = MarkdownScanner()
-    source_path = os.path.join(
-        "test", "resources", "rules", "md044", "good_paragraph_text_start.md"
-    )
-    supplied_arguments = [
-        "--set",
-        "plugins.md044.names=ParaGraph",
-        "scan",
-        source_path,
-    ]
-
-    expected_return_code = 1
-    expected_output = (
-        f"{source_path}:1:1: "
-        + "MD044: Proper names should have the correct capitalization "
-        + "[Expected: ParaGraph; Actual: paragraph] (proper-names)"
-    )
-    expected_error = ""
-
-    # Act
-    execute_results = scanner.invoke_main(arguments=supplied_arguments)
-
-    # Assert
-    execute_results.assert_results(
-        expected_output, expected_error, expected_return_code
-    )
-
-
-@pytest.mark.rules
-def test_md044_bad_paragraph_text_end():
-    """
-    Test to make sure this rule does trigger with a document that
-    contains normal paragraphs containing the word with improper capitalization
-    and configuration to match the main word, where it occurs at the very
-    end of the paragraph.
-    """
-
-    # Arrange
-    scanner = MarkdownScanner()
-    source_path = os.path.join(
-        "test", "resources", "rules", "md044", "good_paragraph_text_end.md"
-    )
-    supplied_arguments = [
-        "--set",
-        "plugins.md044.names=ParaGraph",
-        "scan",
-        source_path,
-    ]
-
-    expected_return_code = 1
-    expected_output = (
-        f"{source_path}:1:20: "
-        + "MD044: Proper names should have the correct capitalization "
-        + "[Expected: ParaGraph; Actual: paragraph] (proper-names)"
-    )
-    expected_error = ""
-
-    # Act
-    execute_results = scanner.invoke_main(arguments=supplied_arguments)
-
-    # Assert
-    execute_results.assert_results(
-        expected_output, expected_error, expected_return_code
-    )
-
-
-@pytest.mark.rules
-def test_md044_bad_paragraph_text_followed_non_alpha():
-    """
-    Test to make sure this rule does trigger with a document that
-    contains normal paragraphs containing the word with improper capitalization
-    and configuration to match the main word, where it is followed by non-alpha
-    characters.
-    """
-
-    # Arrange
-    scanner = MarkdownScanner()
-    source_path = os.path.join(
-        "test",
-        "resources",
-        "rules",
-        "md044",
-        "good_paragraph_text_followed_non_alpha.md",
-    )
-    supplied_arguments = [
-        "--set",
-        "plugins.md044.names=ParaGraph",
-        "scan",
-        source_path,
-    ]
-
-    expected_return_code = 1
-    expected_output = (
-        f"{source_path}:1:11: "
-        + "MD044: Proper names should have the correct capitalization "
-        + "[Expected: ParaGraph; Actual: paragraph] (proper-names)"
-    )
-    expected_error = ""
-
-    # Act
-    execute_results = scanner.invoke_main(arguments=supplied_arguments)
-
-    # Assert
-    execute_results.assert_results(
-        expected_output, expected_error, expected_return_code
-    )
-
-
-@pytest.mark.rules
-def test_md044_bar_paragraph_text_multiples():
-    """
-    Test to make sure this rule does trigger with a document that
-    contains normal paragraphs containing multiples of the word with
-    improper capitalization and configuration to match.
-    """
-
-    # Arrange
-    scanner = MarkdownScanner()
-    source_path = os.path.join(
-        "test", "resources", "rules", "md044", "good_paragraph_text_multiples.md"
-    )
-    supplied_arguments = [
-        "--set",
-        "plugins.md044.names=ParaGraph",
-        "scan",
-        source_path,
-    ]
-
-    expected_return_code = 1
-    expected_output = (
-        f"{source_path}:1:11: "
-        + "MD044: Proper names should have the correct capitalization "
-        + "[Expected: ParaGraph; Actual: paragraph] (proper-names)\n"
-        + f"{source_path}:1:26: "
-        + "MD044: Proper names should have the correct capitalization "
-        + "[Expected: ParaGraph; Actual: paragraph] (proper-names)"
-    )
-    expected_error = ""
-
-    # Act
-    execute_results = scanner.invoke_main(arguments=supplied_arguments)
-
-    # Assert
-    execute_results.assert_results(
-        expected_output, expected_error, expected_return_code
-    )
-
-
-@pytest.mark.rules
-def test_md044_bar_paragraph_text_multiples_on_multiple_lines():
-    """
-    Test to make sure this rule does trigger with a document that
-    contains normal paragraphs containing multiples of the word with
-    improper capitalization and configuration to match.
-    """
-
-    # Arrange
-    scanner = MarkdownScanner()
-    source_path = os.path.join(
-        "test",
-        "resources",
-        "rules",
-        "md044",
-        "good_paragraph_text_multiples_on_multiple_lines.md",
-    )
-    supplied_arguments = [
-        "--set",
-        "plugins.md044.names=ParaGraph",
-        "scan",
-        source_path,
-    ]
-
-    expected_return_code = 1
-    expected_output = (
-        f"{source_path}:1:33: "
-        + "MD044: Proper names should have the correct capitalization "
-        + "[Expected: ParaGraph; Actual: paragraph] (proper-names)\n"
-        + f"{source_path}:3:39: "
-        + "MD044: Proper names should have the correct capitalization "
-        + "[Expected: ParaGraph; Actual: paragraph] (proper-names)"
-    )
-    expected_error = ""
-
-    # Act
-    execute_results = scanner.invoke_main(arguments=supplied_arguments)
-
-    # Assert
-    execute_results.assert_results(
-        expected_output, expected_error, expected_return_code
-    )
-
-
-@pytest.mark.rules
-def test_md044_bar_atx_heading_text():
-    """
-    Test to make sure this rule does trigger with a document that
-    contains normal paragraphs containing multiples of the word with
-    improper capitalization and configuration to match, some within
-    an Atx Heading element.
-    """
-
-    # Arrange
-    scanner = MarkdownScanner()
-    source_path = os.path.join(
-        "test", "resources", "rules", "md044", "good_atx_heading_text.md"
-    )
-    supplied_arguments = [
-        "--set",
-        "plugins.md044.names=ParaGraph",
-        "scan",
-        source_path,
-    ]
-
-    expected_return_code = 1
-    expected_output = (
-        f"{source_path}:1:27: "
-        + "MD044: Proper names should have the correct capitalization "
-        + "[Expected: ParaGraph; Actual: paragraph] (proper-names)\n"
-        + f"{source_path}:3:8: "
-        + "MD044: Proper names should have the correct capitalization "
-        + "[Expected: ParaGraph; Actual: paragraph] (proper-names)"
-    )
-    expected_error = ""
-
-    # Act
-    execute_results = scanner.invoke_main(arguments=supplied_arguments)
-
-    # Assert
-    execute_results.assert_results(
-        expected_output, expected_error, expected_return_code
-    )
-
-
-@pytest.mark.rules
-def test_md044_bad_setext_heading_text():
-    """
-    Test to make sure this rule does trigger with a document that
-    contains normal paragraphs containing multiples of the word with
-    improper capitalization and configuration to match, some within
-    a SetExt Heading element.
-    """
-
-    # Arrange
-    scanner = MarkdownScanner()
-    source_path = os.path.join(
-        "test", "resources", "rules", "md044", "good_setext_heading_text.md"
-    )
-    supplied_arguments = [
-        "--set",
-        "plugins.md044.names=ParaGraph",
-        "scan",
-        source_path,
-    ]
-
-    expected_return_code = 1
-    expected_output = (
-        f"{source_path}:1:25: "
-        + "MD044: Proper names should have the correct capitalization "
-        + "[Expected: ParaGraph; Actual: paragraph] (proper-names)\n"
-        + f"{source_path}:4:8: "
-        + "MD044: Proper names should have the correct capitalization "
-        + "[Expected: ParaGraph; Actual: paragraph] (proper-names)"
-    )
-    expected_error = ""
-
-    # Act
-    execute_results = scanner.invoke_main(arguments=supplied_arguments)
-
-    # Assert
-    execute_results.assert_results(
-        expected_output, expected_error, expected_return_code
-    )
-
-
-@pytest.mark.rules
-def test_md044_bad_indented_code_block_text():
-    """
-    Test to make sure this rule does trigger with a document that
-    contains normal paragraphs containing multiples of the word with
-    improper capitalization and configuration to match, some within
-    an Indented Code Block element.
-    """
-
-    # Arrange
-    scanner = MarkdownScanner()
-    source_path = os.path.join(
-        "test", "resources", "rules", "md044", "good_indented_code_block_text.md"
-    )
-    supplied_arguments = [
-        "--set",
-        "plugins.md044.names=ParaGraph",
-        "scan",
-        source_path,
-    ]
-
-    expected_return_code = 1
-    expected_output = (
-        f"{source_path}:1:27: "
-        + "MD044: Proper names should have the correct capitalization "
-        + "[Expected: ParaGraph; Actual: paragraph] (proper-names)\n"
-        + f"{source_path}:3:12: "
-        + "MD044: Proper names should have the correct capitalization "
-        + "[Expected: ParaGraph; Actual: paragraph] (proper-names)"
-    )
-    expected_error = ""
-
-    # Act
-    execute_results = scanner.invoke_main(arguments=supplied_arguments)
-
-    # Assert
-    execute_results.assert_results(
-        expected_output, expected_error, expected_return_code
-    )
-
-
-@pytest.mark.rules
-def test_md044_bad_fenced_code_block_text():
-    """
-    Test to make sure this rule does trigger with a document that
-    contains normal paragraphs containing multiples of the word with
-    improper capitalization and configuration to match, some within
-    a Fenced Code Block element.
-    """
-
-    # Arrange
-    scanner = MarkdownScanner()
-    source_path = os.path.join(
-        "test", "resources", "rules", "md044", "good_fenced_code_block_text.md"
-    )
-    supplied_arguments = [
-        "--set",
-        "plugins.md044.names=ParaGraph",
-        "scan",
-        source_path,
-    ]
-
-    expected_return_code = 1
-    expected_output = (
-        f"{source_path}:1:27: "
-        + "MD044: Proper names should have the correct capitalization "
-        + "[Expected: ParaGraph; Actual: paragraph] (proper-names)\n"
-        + f"{source_path}:4:8: "
-        + "MD044: Proper names should have the correct capitalization "
-        + "[Expected: ParaGraph; Actual: paragraph] (proper-names)"
-    )
-    expected_error = ""
-
-    # Act
-    execute_results = scanner.invoke_main(arguments=supplied_arguments)
-
-    # Assert
-    execute_results.assert_results(
-        expected_output, expected_error, expected_return_code
-    )
-
-
-@pytest.mark.rules
-def test_md044_good_indented_code_block_text():
-    """
-    Test to make sure this rule does trigger with a document that
-    contains normal paragraphs containing multiples of the word with
-    improper capitalization and configuration to match, some within
-    an Indented Code Block element.
-    """
-
-    # Arrange
-    scanner = MarkdownScanner()
-    source_path = os.path.join(
-        "test", "resources", "rules", "md044", "good_indented_code_block_text.md"
-    )
-    supplied_arguments = [
-        "--set",
-        "plugins.md044.names=ParaGraph",
-        "--set",
-        "plugins.md044.code_blocks=$!False",
-        "--strict-config",
-        "scan",
-        source_path,
-    ]
-
-    expected_return_code = 1
-    expected_output = (
-        f"{source_path}:1:27: "
-        + "MD044: Proper names should have the correct capitalization "
-        + "[Expected: ParaGraph; Actual: paragraph] (proper-names)"
-    )
-    expected_error = ""
-
-    # Act
-    execute_results = scanner.invoke_main(arguments=supplied_arguments)
-
-    # Assert
-    execute_results.assert_results(
-        expected_output, expected_error, expected_return_code
-    )
-
-
-@pytest.mark.rules
-def test_md044_good_fenced_code_block_text():
-    """
-    Test to make sure this rule does trigger with a document that
-    contains normal paragraphs containing multiples of the word with
-    improper capitalization and configuration to match, some within
-    a Fenced Code Block element.
-    """
-
-    # Arrange
-    scanner = MarkdownScanner()
-    source_path = os.path.join(
-        "test", "resources", "rules", "md044", "good_fenced_code_block_text.md"
-    )
-    supplied_arguments = [
-        "--set",
-        "plugins.md044.names=ParaGraph",
-        "--set",
-        "plugins.md044.code_blocks=$!False",
-        "--strict-config",
-        "scan",
-        source_path,
-    ]
-
-    expected_return_code = 1
-    expected_output = (
-        f"{source_path}:1:27: "
-        + "MD044: Proper names should have the correct capitalization "
-        + "[Expected: ParaGraph; Actual: paragraph] (proper-names)"
-    )
-    expected_error = ""
-
-    # Act
-    execute_results = scanner.invoke_main(arguments=supplied_arguments)
-
-    # Assert
-    execute_results.assert_results(
-        expected_output, expected_error, expected_return_code
-    )
-
-
-@pytest.mark.rules
-def test_md044_good_html_block_text():
-    """
-    Test to make sure this rule does trigger with a document that
-    contains normal paragraphs containing multiples of the word with
-    improper capitalization and configuration to match, some within
-    a HTML Block element.
-    """
-
-    # Arrange
-    scanner = MarkdownScanner()
-    source_path = os.path.join(
-        "test", "resources", "rules", "md044", "good_html_block_text.md"
-    )
-    supplied_arguments = [
-        "--set",
-        "plugins.md044.names=ParaGraph",
-        "scan",
-        source_path,
-    ]
-
-    expected_return_code = 1
-    expected_output = (
-        f"{source_path}:1:27: "
-        + "MD044: Proper names should have the correct capitalization "
-        + "[Expected: ParaGraph; Actual: paragraph] (proper-names)\n"
-        + f"{source_path}:4:8: "
-        + "MD044: Proper names should have the correct capitalization "
-        + "[Expected: ParaGraph; Actual: paragraph] (proper-names)"
-    )
-    expected_error = ""
-
-    # Act
-    execute_results = scanner.invoke_main(arguments=supplied_arguments)
-
-    # Assert
-    execute_results.assert_results(
-        expected_output, expected_error, expected_return_code
-    )
-
-
-@pytest.mark.rules
-def test_md044_good_block_quote_text():
-    """
-    Test to make sure this rule does trigger with a document that
-    contains normal paragraphs containing multiples of the word with
-    improper capitalization and configuration to match, some within
-    a Block Quote element.
-    """
-
-    # Arrange
-    scanner = MarkdownScanner()
-    source_path = os.path.join(
-        "test", "resources", "rules", "md044", "good_block_quote_text.md"
-    )
-    supplied_arguments = [
-        "--set",
-        "plugins.md044.names=ParaGraph",
-        "scan",
-        source_path,
-    ]
-
-    expected_return_code = 1
-    expected_output = (
-        f"{source_path}:1:27: "
-        + "MD044: Proper names should have the correct capitalization "
-        + "[Expected: ParaGraph; Actual: paragraph] (proper-names)\n"
-        + f"{source_path}:3:10: "
-        + "MD044: Proper names should have the correct capitalization "
-        + "[Expected: ParaGraph; Actual: paragraph] (proper-names)"
-    )
-    expected_error = ""
-
-    # Act
-    execute_results = scanner.invoke_main(arguments=supplied_arguments)
-
-    # Assert
-    execute_results.assert_results(
-        expected_output, expected_error, expected_return_code
-    )
-
-
-@pytest.mark.rules
-def test_md044_good_code_span_text():
-    """
-    Test to make sure this rule does trigger with a document that
-    contains normal paragraphs containing multiples of the word with
-    improper capitalization and configuration to match, some within
-    a Code Span element.
-    """
-
-    # Arrange
-    scanner = MarkdownScanner()
-    source_path = os.path.join(
-        "test", "resources", "rules", "md044", "good_code_span_text.md"
-    )
-    supplied_arguments = [
-        "--set",
-        "plugins.md044.names=ParaGraph",
-        "scan",
-        source_path,
-    ]
-
-    expected_return_code = 1
-    expected_output = (
-        f"{source_path}:1:27: "
-        + "MD044: Proper names should have the correct capitalization "
-        + "[Expected: ParaGraph; Actual: paragraph] (proper-names)\n"
-        + f"{source_path}:3:7: "
-        + "MD044: Proper names should have the correct capitalization "
-        + "[Expected: ParaGraph; Actual: paragraph] (proper-names)"
-    )
-    expected_error = ""
-
-    # Act
-    execute_results = scanner.invoke_main(arguments=supplied_arguments)
-
-    # Assert
-    execute_results.assert_results(
-        expected_output, expected_error, expected_return_code
-    )
-
-
-@pytest.mark.rules
-def test_md044_good_code_span_text_multiple_lines():
-    """
-    Test to make sure this rule does trigger with a document that
-    contains normal paragraphs containing multiples of the word with
-    improper capitalization and configuration to match, some within
-    a Code span element that is over multiple lines.
-    """
-
-    # Arrange
-    scanner = MarkdownScanner()
-    source_path = os.path.join(
-        "test", "resources", "rules", "md044", "good_code_span_text_multiple_lines.md"
-    )
-    supplied_arguments = [
-        "--set",
-        "plugins.md044.names=ParaGraph",
-        "scan",
-        source_path,
-    ]
-
-    expected_return_code = 1
-    expected_output = (
-        f"{source_path}:1:27: "
-        + "MD044: Proper names should have the correct capitalization "
-        + "[Expected: ParaGraph; Actual: paragraph] (proper-names)\n"
-        + f"{source_path}:3:7: "
-        + "MD044: Proper names should have the correct capitalization "
-        + "[Expected: ParaGraph; Actual: paragraph] (proper-names)\n"
-        + f"{source_path}:4:6: "
-        + "MD044: Proper names should have the correct capitalization "
-        + "[Expected: ParaGraph; Actual: paragraph] (proper-names)"
-    )
-    expected_error = ""
-
-    # Act
-    execute_results = scanner.invoke_main(arguments=supplied_arguments)
-
-    # Assert
-    execute_results.assert_results(
-        expected_output, expected_error, expected_return_code
-    )
-
-
-@pytest.mark.rules
-def test_md044_good_inline_link():
-    """
-    Test to make sure this rule does trigger with a document that
-    contains normal paragraphs containing multiples of the word with
-    improper capitalization and configuration to match, some within
-    an Inline Link element.
-    """
-
-    # Arrange
-    scanner = MarkdownScanner()
-    source_path = os.path.join(
-        "test", "resources", "rules", "md044", "good_inline_link.md"
-    )
-    supplied_arguments = [
-        "--set",
-        "plugins.md044.names=ParaGraph",
-        "scan",
-        source_path,
-    ]
-
-    expected_return_code = 1
-    expected_output = (
-        f"{source_path}:1:4: "
-        + "MD044: Proper names should have the correct capitalization "
-        + "[Expected: ParaGraph; Actual: paragraph] (proper-names)\n"
-        + f"{source_path}:1:41: "
-        + "MD044: Proper names should have the correct capitalization "
-        + "[Expected: ParaGraph; Actual: paragraph] (proper-names)"
-    )
-    expected_error = ""
-
-    # Act
-    execute_results = scanner.invoke_main(arguments=supplied_arguments)
-
-    # Assert
-    execute_results.assert_results(
-        expected_output, expected_error, expected_return_code
-    )
-
-
-@pytest.mark.rules
-def test_md044_good_inline_link_multiple_lines_x():
-    """
-    Test to make sure this rule does trigger with a document that
-    contains normal paragraphs containing multiples of the word with
-    improper capitalization and configuration to match, some within
-    an Inline Link element over multiple lines.
-    """
-
-    # Arrange
-    scanner = MarkdownScanner()
-    source_path = os.path.join(
-        "test", "resources", "rules", "md044", "good_inline_link_multiple_lines.md"
-    )
-    supplied_arguments = [
-        "--set",
-        "plugins.md044.names=ParaGraph",
-        "scan",
-        source_path,
-    ]
-
-    expected_return_code = 1
-    expected_output = (
-        f"{source_path}:1:4: "
-        + "MD044: Proper names should have the correct capitalization "
-        + "[Expected: ParaGraph; Actual: paragraph] (proper-names)\n"
-        + f"{source_path}:3:2: "
-        + "MD044: Proper names should have the correct capitalization "
-        + "[Expected: ParaGraph; Actual: paragraph] (proper-names)"
-    )
-    expected_error = ""
-
-    # Act
-    execute_results = scanner.invoke_main(arguments=supplied_arguments)
-
-    # Assert
-    execute_results.assert_results(
-        expected_output, expected_error, expected_return_code
-    )
-
-
-@pytest.mark.rules
-def test_md044_good_inline_link_multiple_lines_two():
-    """
-    Test to make sure this rule does trigger with a document that
-    contains normal paragraphs containing multiples of the word with
-    improper capitalization and configuration to match, some within
-    an Inline Link element over multiple lines.
-    """
-
-    # Arrange
-    scanner = MarkdownScanner()
-    source_path = os.path.join(
-        "test", "resources", "rules", "md044", "good_inline_link_multiple_lines_two.md"
-    )
-    supplied_arguments = [
-        "--set",
-        "plugins.md044.names=ParaGraph",
-        "scan",
-        source_path,
-    ]
-
-    expected_return_code = 1
-    expected_output = (
-        f"{source_path}:1:4: "
-        + "MD044: Proper names should have the correct capitalization "
-        + "[Expected: ParaGraph; Actual: paragraph] (proper-names)\n"
-        + f"{source_path}:4:13: "
-        + "MD044: Proper names should have the correct capitalization "
-        + "[Expected: ParaGraph; Actual: paragraph] (proper-names)"
-    )
-    expected_error = ""
-
-    # Act
-    execute_results = scanner.invoke_main(arguments=supplied_arguments)
-
-    # Assert
-    execute_results.assert_results(
-        expected_output, expected_error, expected_return_code
-    )
-
-
-@pytest.mark.rules
-def test_md044_good_inline_link_multiple_lines_three():
-    """
-    Test to make sure this rule does trigger with a document that
-    contains normal paragraphs containing multiples of the word with
-    improper capitalization and configuration to match, some within
-    an Inline Line element over multiple lines.
-    """
-
-    # Arrange
-    scanner = MarkdownScanner()
-    source_path = os.path.join(
-        "test",
-        "resources",
-        "rules",
-        "md044",
-        "good_inline_link_multiple_lines_three.md",
-    )
-    supplied_arguments = [
-        "--set",
-        "plugins.md044.names=ParaGraph",
-        "scan",
-        source_path,
-    ]
-
-    expected_return_code = 1
-    expected_output = (
-        f"{source_path}:2:1: "
-        + "MD044: Proper names should have the correct capitalization "
-        + "[Expected: ParaGraph; Actual: paragraph] (proper-names)\n"
-        + f"{source_path}:4:2: "
-        + "MD044: Proper names should have the correct capitalization "
-        + "[Expected: ParaGraph; Actual: paragraph] (proper-names)"
-    )
-    expected_error = ""
-
-    # Act
-    execute_results = scanner.invoke_main(arguments=supplied_arguments)
-
-    # Assert
-    execute_results.assert_results(
-        expected_output, expected_error, expected_return_code
-    )
-
-
-@pytest.mark.rules
-def test_md044_good_inline_image():
-    """
-    Test to make sure this rule does trigger with a document that
-    contains normal paragraphs containing multiples of the word with
-    improper capitalization and configuration to match, some within
-    an Inline Image element.
-    """
-
-    # Arrange
-    scanner = MarkdownScanner()
-    source_path = os.path.join(
-        "test", "resources", "rules", "md044", "good_inline_image.md"
-    )
-    supplied_arguments = [
-        "--set",
-        "plugins.md044.names=ParaGraph",
-        "scan",
-        source_path,
-    ]
-
-    expected_return_code = 1
-    expected_output = (
-        f"{source_path}:1:5: "
-        + "MD044: Proper names should have the correct capitalization "
-        + "[Expected: ParaGraph; Actual: paragraph] (proper-names)\n"
-        + f"{source_path}:1:42: "
-        + "MD044: Proper names should have the correct capitalization "
-        + "[Expected: ParaGraph; Actual: paragraph] (proper-names)"
-    )
-    expected_error = ""
-
-    # Act
-    execute_results = scanner.invoke_main(arguments=supplied_arguments)
-
-    # Assert
-    execute_results.assert_results(
-        expected_output, expected_error, expected_return_code
-    )
-
-
-@pytest.mark.rules
-def test_md044_good_inline_image_multiple_lines():
-    """
-    Test to make sure this rule does trigger with a document that
-    contains normal paragraphs containing multiples of the word with
-    improper capitalization and configuration to match, some within
-    an Inline Image element over multiple lines.
-    """
-
-    # Arrange
-    scanner = MarkdownScanner()
-    source_path = os.path.join(
-        "test", "resources", "rules", "md044", "good_inline_image_multiple_lines.md"
-    )
-    supplied_arguments = [
-        "--set",
-        "plugins.md044.names=ParaGraph",
-        "scan",
-        source_path,
-    ]
-
-    expected_return_code = 1
-    expected_output = (
-        f"{source_path}:1:5: "
-        + "MD044: Proper names should have the correct capitalization "
-        + "[Expected: ParaGraph; Actual: paragraph] (proper-names)\n"
-        + f"{source_path}:3:2: "
-        + "MD044: Proper names should have the correct capitalization "
-        + "[Expected: ParaGraph; Actual: paragraph] (proper-names)"
-    )
-    expected_error = ""
-
-    # Act
-    execute_results = scanner.invoke_main(arguments=supplied_arguments)
-
-    # Assert
-    execute_results.assert_results(
-        expected_output, expected_error, expected_return_code
-    )
-
-
-@pytest.mark.rules
-def test_md044_good_inline_image_multiple_lines_two():
-    """
-    Test to make sure this rule does trigger with a document that
-    contains normal paragraphs containing multiples of the word with
-    improper capitalization and configuration to match, some within
-    an Inline Image element over multiple lines.
-    """
-
-    # Arrange
-    scanner = MarkdownScanner()
-    source_path = os.path.join(
-        "test", "resources", "rules", "md044", "good_inline_image_multiple_lines_two.md"
-    )
-    supplied_arguments = [
-        "--set",
-        "plugins.md044.names=ParaGraph",
-        "scan",
-        source_path,
-    ]
-
-    expected_return_code = 1
-    expected_output = (
-        f"{source_path}:1:5: "
-        + "MD044: Proper names should have the correct capitalization "
-        + "[Expected: ParaGraph; Actual: paragraph] (proper-names)\n"
-        + f"{source_path}:4:13: "
-        + "MD044: Proper names should have the correct capitalization "
-        + "[Expected: ParaGraph; Actual: paragraph] (proper-names)"
-    )
-    expected_error = ""
-
-    # Act
-    execute_results = scanner.invoke_main(arguments=supplied_arguments)
+source_path = os.path.join("test", "resources", "rules", "md044") + os.sep
+
+
+configTests = [
+    pluginConfigErrorTest(
+        "names_bad_type",
+        use_strict_config=True,
+        set_args=["plugins.md044.names=$#1"],
+        expected_error="""BadPluginError encountered while configuring plugins:
+The value for property 'plugins.md044.names' must be of type 'str'.""",
+    ),
+    pluginConfigErrorTest(
+        "names_empty_elements",
+        use_strict_config=True,
+        set_args=["plugins.md044.names=,,"],
+        expected_error="""BadPluginError encountered while configuring plugins:
+Elements in the comma-separated list cannot be empty.""",
+    ),
+    pluginConfigErrorTest(
+        "names_repeated_elements",
+        use_strict_config=True,
+        set_args=["plugins.md044.names=one,two,One"],
+        expected_error="""BadPluginError encountered while configuring plugins:
+Element `One` is already present in the list as `one`.""",
+    ),
+    pluginConfigErrorTest(
+        "code_blocks",
+        use_strict_config=True,
+        set_args=["plugins.md044.code_blocks=one"],
+        expected_error="""BadPluginError encountered while configuring plugins:
+The value for property 'plugins.md044.code_blocks' must be of type 'bool'.""",
+    ),
+]
+
+scanTests = [
+    pluginRuleTest(
+        "good_paragraph_text",
+        source_file_contents="""this is a paragraph without any capitalization errors
+""",
+        set_args=["plugins.md044.names=paragraph"],
+    ),
+    pluginRuleTest(
+        "bad_paragraph_text",
+        source_file_contents="""this is a paragraph without any capitalization errors
+""",
+        set_args=["plugins.md044.names=ParaGraph"],
+        scan_expected_return_code=1,
+        scan_expected_output="""{temp_source_path}:1:11: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+""",
+        fix_expected_file_contents="""this is a ParaGraph without any capitalization errors
+""",
+    ),
+    pluginRuleTest(
+        "good_paragraph_text_prefix",
+        source_file_contents="""nothing like a good reparagraph to go
+""",
+        set_args=["plugins.md044.names=ParaGraph"],
+    ),
+    pluginRuleTest(
+        "good_paragraph_text_suffix",
+        source_file_contents="""this is paragraphing at its best
+""",
+        set_args=["plugins.md044.names=ParaGraph"],
+    ),
+    pluginRuleTest(
+        "bad_paragraph_text_start",
+        source_file_contents="""paragraph is how this starts
+""",
+        set_args=["plugins.md044.names=ParaGraph"],
+        scan_expected_return_code=1,
+        scan_expected_output="""{temp_source_path}:1:1: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+""",
+        fix_expected_file_contents="""ParaGraph is how this starts
+""",
+    ),
+    pluginRuleTest(
+        "bad_paragraph_text_end",
+        source_file_contents="""ends with the word paragraph
+""",
+        set_args=["plugins.md044.names=ParaGraph"],
+        scan_expected_return_code=1,
+        scan_expected_output="""{temp_source_path}:1:20: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+""",
+        fix_expected_file_contents="""ends with the word ParaGraph
+""",
+    ),
+    pluginRuleTest(
+        "bad_paragraph_text_followed_non_alpha",
+        source_file_contents="""this is a paragraph.
+""",
+        set_args=["plugins.md044.names=ParaGraph"],
+        scan_expected_return_code=1,
+        scan_expected_output="""{temp_source_path}:1:11: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+""",
+        fix_expected_file_contents="""this is a ParaGraph.
+""",
+    ),
+    pluginRuleTest(
+        "bad_paragraph_text_multiples",
+        source_file_contents="""this is a paragraph with paragraph capitalization errors
+""",
+        set_args=["plugins.md044.names=ParaGraph"],
+        scan_expected_return_code=1,
+        scan_expected_output="""{temp_source_path}:1:11: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+{temp_source_path}:1:26: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+""",
+        fix_expected_file_contents="""this is a ParaGraph with ParaGraph capitalization errors
+""",
+    ),
+    pluginRuleTest(
+        "bad_paragraph_text_multiples_on_multiple_lines",
+        source_file_contents="""this is a sample where the word paragraph should
+appear on multiple lines so we can make sure that
+advancing the line and column for the paragraph
+error reporting works.
+""",
+        set_args=["plugins.md044.names=ParaGraph"],
+        scan_expected_return_code=1,
+        scan_expected_output="""{temp_source_path}:1:33: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+{temp_source_path}:3:39: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+""",
+        fix_expected_file_contents="""this is a sample where the word ParaGraph should
+appear on multiple lines so we can make sure that
+advancing the line and column for the ParaGraph
+error reporting works.
+""",
+    ),
+    pluginRuleTest(
+        "bad_paragraph_text_backslash",
+        source_file_contents="""paragraph \\! paragraph
+""",
+        set_args=["plugins.md044.names=ParaGraph"],
+        scan_expected_return_code=1,
+        scan_expected_output="""{temp_source_path}:1:1: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+{temp_source_path}:1:14: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+""",
+        fix_expected_file_contents="""ParaGraph \\! ParaGraph
+""",
+    ),
+    pluginRuleTest(
+        "bad_paragraph_text_reference",
+        source_file_contents="""paragraph &amp; paragraph
+""",
+        set_args=["plugins.md044.names=ParaGraph"],
+        scan_expected_return_code=1,
+        scan_expected_output="""{temp_source_path}:1:1: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+{temp_source_path}:1:17: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+""",
+        fix_expected_file_contents="""ParaGraph &amp; ParaGraph
+""",
+    ),
+    pluginRuleTest(
+        "bad_atx_heading_text",
+        source_file_contents="""# This section contains a paragraph
 
-    # Assert
-    execute_results.assert_results(
-        expected_output, expected_error, expected_return_code
-    )
+yes, a paragraph is contained.
+""",
+        set_args=["plugins.md044.names=ParaGraph"],
+        scan_expected_return_code=1,
+        scan_expected_output="""{temp_source_path}:1:27: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+{temp_source_path}:3:8: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+""",
+        fix_expected_file_contents="""# This section contains a ParaGraph
 
+yes, a ParaGraph is contained.
+""",
+    ),
+    pluginRuleTest(
+        "bad_setext_heading_text",
+        source_file_contents="""This section contains a paragraph
+===
 
-@pytest.mark.rules
-def test_md044_good_full_link():
-    """
-    Test to make sure this rule does trigger with a document that
-    contains normal paragraphs containing multiples of the word with
-    improper capitalization and configuration to match, some within
-    a Full Link element.
-    """
+yes, a paragraph is contained.
+""",
+        set_args=["plugins.md044.names=ParaGraph"],
+        scan_expected_return_code=1,
+        scan_expected_output="""{temp_source_path}:1:25: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+{temp_source_path}:4:8: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+""",
+        fix_expected_file_contents="""This section contains a ParaGraph
+===
 
-    # Arrange
-    scanner = MarkdownScanner()
-    source_path = os.path.join(
-        "test", "resources", "rules", "md044", "good_full_link.md"
-    )
-    supplied_arguments = [
-        "--set",
-        "plugins.md044.names=ParaGraph",
-        "scan",
-        source_path,
-    ]
-
-    expected_return_code = 1
-    expected_output = (
-        f"{source_path}:2:4: "
-        + "MD044: Proper names should have the correct capitalization "
-        + "[Expected: ParaGraph; Actual: paragraph] (proper-names)\n"
-        + f"{source_path}:5:16: "
-        + "MD044: Proper names should have the correct capitalization "
-        + "[Expected: ParaGraph; Actual: paragraph] (proper-names)"
-    )
-    expected_error = ""
+yes, a ParaGraph is contained.
+""",
+    ),
+    pluginRuleTest(
+        "bad_indented_code_block_text",
+        source_file_contents="""# This section contains a paragraph
 
-    # Act
-    execute_results = scanner.invoke_main(arguments=supplied_arguments)
+    yes, a paragraph is contained.
+""",
+        set_args=["plugins.md044.names=ParaGraph"],
+        scan_expected_return_code=1,
+        scan_expected_output="""{temp_source_path}:1:27: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+{temp_source_path}:3:12: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+""",
+        fix_expected_file_contents="""# This section contains a ParaGraph
 
-    # Assert
-    execute_results.assert_results(
-        expected_output, expected_error, expected_return_code
-    )
+    yes, a ParaGraph is contained.
+""",
+    ),
+    pluginRuleTest(
+        "bad_indented_code_block_text_no_code_blocks",
+        source_file_contents="""# This section contains a paragraph
 
+    yes, a paragraph is contained.
+""",
+        set_args=["plugins.md044.names=ParaGraph", "plugins.md044.code_blocks=$!False"],
+        use_strict_config=True,
+        scan_expected_return_code=1,
+        scan_expected_output="""{temp_source_path}:1:27: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+""",
+        fix_expected_file_contents="""# This section contains a ParaGraph
 
-@pytest.mark.rules
-def test_md044_good_full_link_multiple():
-    """
-    Test to make sure this rule does trigger with a document that
-    contains normal paragraphs containing multiples of the word with
-    improper capitalization and configuration to match, some within
-    a Full Link element over multiple lines.
-    """
+    yes, a paragraph is contained.
+""",
+    ),
+    pluginRuleTest(
+        "bad_fenced_code_block_text",
+        source_file_contents="""# This section contains a paragraph
+
+```text
+yes, a paragraph is contained.
+```
+""",
+        set_args=["plugins.md044.names=ParaGraph"],
+        scan_expected_return_code=1,
+        scan_expected_output="""{temp_source_path}:1:27: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+{temp_source_path}:4:8: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+""",
+        fix_expected_file_contents="""# This section contains a ParaGraph
 
-    # Arrange
-    scanner = MarkdownScanner()
-    source_path = os.path.join(
-        "test", "resources", "rules", "md044", "good_full_link_multiple.md"
-    )
-    supplied_arguments = [
-        "--set",
-        "plugins.md044.names=ParaGraph",
-        "scan",
-        source_path,
-    ]
-
-    expected_return_code = 1
-    expected_output = (
-        f"{source_path}:3:1: "
-        + "MD044: Proper names should have the correct capitalization "
-        + "[Expected: ParaGraph; Actual: paragraph] (proper-names)\n"
-        + f"{source_path}:9:1: "
-        + "MD044: Proper names should have the correct capitalization "
-        + "[Expected: ParaGraph; Actual: paragraph] (proper-names)"
-    )
-    expected_error = ""
+```text
+yes, a ParaGraph is contained.
+```
+""",
+    ),
+    pluginRuleTest(
+        "bad_fenced_code_block_text_no_code_blocks",
+        source_file_contents="""# This section contains a paragraph
+
+```text
+yes, a paragraph is contained.
+```
+""",
+        set_args=["plugins.md044.names=ParaGraph", "plugins.md044.code_blocks=$!False"],
+        use_strict_config=True,
+        scan_expected_return_code=1,
+        scan_expected_output="""{temp_source_path}:1:27: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+""",
+        fix_expected_file_contents="""# This section contains a ParaGraph
 
-    # Act
-    execute_results = scanner.invoke_main(arguments=supplied_arguments)
+```text
+yes, a paragraph is contained.
+```
+""",
+    ),
+    pluginRuleTest(
+        "bad_html_block_text",
+        source_file_contents="""# This section contains a paragraph
+
+<!--
+yes, a paragraph is contained.
+-->
+""",
+        set_args=["plugins.md044.names=ParaGraph"],
+        use_strict_config=True,
+        scan_expected_return_code=1,
+        scan_expected_output="""{temp_source_path}:1:27: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+{temp_source_path}:4:8: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+""",
+        fix_expected_file_contents="""# This section contains a ParaGraph
 
-    # Assert
-    execute_results.assert_results(
-        expected_output, expected_error, expected_return_code
-    )
+<!--
+yes, a ParaGraph is contained.
+-->
+""",
+    ),
+    pluginRuleTest(
+        "bad_block_quote_text",
+        source_file_contents="""# This section contains a paragraph
 
+> yes, a paragraph is contained.
+""",
+        set_args=["plugins.md044.names=ParaGraph"],
+        use_strict_config=True,
+        scan_expected_return_code=1,
+        scan_expected_output="""{temp_source_path}:1:27: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+{temp_source_path}:3:10: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+""",
+        fix_expected_file_contents="""# This section contains a ParaGraph
 
-@pytest.mark.rules
-def test_md044_good_full_image():
-    """
-    Test to make sure this rule does trigger with a document that
-    contains normal paragraphs containing multiples of the word with
-    improper capitalization and configuration to match, some within
-    a Full Image element.
-    """
+> yes, a ParaGraph is contained.
+""",
+    ),
+    pluginRuleTest(
+        "bad_code_span_text",
+        source_file_contents="""# This section contains a paragraph
 
-    # Arrange
-    scanner = MarkdownScanner()
-    source_path = os.path.join(
-        "test", "resources", "rules", "md044", "good_full_image.md"
-    )
-    supplied_arguments = [
-        "--set",
-        "plugins.md044.names=ParaGraph",
-        "scan",
-        source_path,
-    ]
-
-    expected_return_code = 1
-    expected_output = (
-        f"{source_path}:2:5: "
-        + "MD044: Proper names should have the correct capitalization "
-        + "[Expected: ParaGraph; Actual: paragraph] (proper-names)\n"
-        + f"{source_path}:5:16: "
-        + "MD044: Proper names should have the correct capitalization "
-        + "[Expected: ParaGraph; Actual: paragraph] (proper-names)"
-    )
-    expected_error = ""
+yes, `a paragraph is` contained.
+""",
+        set_args=["plugins.md044.names=ParaGraph"],
+        use_strict_config=True,
+        scan_expected_return_code=1,
+        scan_expected_output="""{temp_source_path}:1:27: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+{temp_source_path}:3:9: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+""",
+        fix_expected_file_contents="""# This section contains a ParaGraph
 
-    # Act
-    execute_results = scanner.invoke_main(arguments=supplied_arguments)
+yes, `a ParaGraph is` contained.
+""",
+    ),
+    pluginRuleTest(
+        "bad_code_span_text_multiple_lines",
+        source_file_contents="""# This section contains a paragraph
 
-    # Assert
-    execute_results.assert_results(
-        expected_output, expected_error, expected_return_code
-    )
+yes, `a paragraph a
+is a paragraph` contained.
+""",
+        set_args=["plugins.md044.names=ParaGraph"],
+        use_strict_config=True,
+        scan_expected_return_code=1,
+        scan_expected_output="""{temp_source_path}:1:27: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+{temp_source_path}:3:9: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+{temp_source_path}:4:6: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+""",
+        fix_expected_file_contents="""# This section contains a ParaGraph
 
+yes, `a ParaGraph a
+is a ParaGraph` contained.
+""",
+    ),
+    pluginRuleTest(
+        "bad_inline_link",
+        source_file_contents="""[a paragraph inspired link](/paragraph "paragraph")
+""",
+        set_args=["plugins.md044.names=ParaGraph"],
+        use_strict_config=True,
+        use_debug=True,
+        scan_expected_return_code=1,
+        scan_expected_output="""{temp_source_path}:1:4: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+{temp_source_path}:1:41: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+""",
+        fix_expected_file_contents="""[a ParaGraph inspired link](/paragraph "ParaGraph")
+""",
+    ),
+    pluginRuleTest(
+        "bad_inline_link_backslash",
+        source_file_contents="""[a paragraph inspired \\! paragraph link](/paragraph "paragraph \\! paragraph")
+""",
+        set_args=["plugins.md044.names=ParaGraph"],
+        use_strict_config=True,
+        use_debug=True,
+        scan_expected_return_code=1,
+        scan_expected_output="""{temp_source_path}:1:4: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+{temp_source_path}:1:26: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+{temp_source_path}:1:54: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+{temp_source_path}:1:67: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+""",
+        fix_expected_file_contents="""[a ParaGraph inspired \\! ParaGraph link](/paragraph "ParaGraph \\! ParaGraph")
+""",
+    ),
+    pluginRuleTest(
+        "bad_inline_link_reference",
+        source_file_contents="""[a paragraph inspired &amp; paragraph link](/paragraph "paragraph &amp; paragraph")
+""",
+        set_args=["plugins.md044.names=ParaGraph"],
+        use_strict_config=True,
+        use_debug=True,
+        scan_expected_return_code=1,
+        scan_expected_output="""{temp_source_path}:1:4: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+{temp_source_path}:1:29: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+{temp_source_path}:1:57: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+{temp_source_path}:1:73: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+""",
+        fix_expected_file_contents="""[a ParaGraph inspired &amp; ParaGraph link](/paragraph "ParaGraph &amp; ParaGraph")
+""",
+    ),
+    pluginRuleTest(
+        "bad_inline_link_multiple_lines_one",
+        source_file_contents="""[a paragraph inspired link](
+/paragraph
+"paragraph")
+""",
+        set_args=["plugins.md044.names=ParaGraph"],
+        use_strict_config=True,
+        scan_expected_return_code=1,
+        scan_expected_output="""{temp_source_path}:1:4: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+{temp_source_path}:3:2: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+""",
+        fix_expected_file_contents="""[a ParaGraph inspired link](
+/paragraph
+"ParaGraph")
+""",
+    ),
+    pluginRuleTest(
+        "bad_inline_link_multiple_lines_two",
+        source_file_contents="""[a paragraph inspired link](
+/paragraph
+"this is
+a very long paragraph")
+""",
+        set_args=["plugins.md044.names=ParaGraph"],
+        use_strict_config=True,
+        scan_expected_return_code=1,
+        scan_expected_output="""{temp_source_path}:1:4: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+{temp_source_path}:4:13: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+""",
+        fix_expected_file_contents="""[a ParaGraph inspired link](
+/paragraph
+"this is
+a very long ParaGraph")
+""",
+    ),
+    pluginRuleTest(
+        "bad_inline_link_multiple_lines_three",
+        source_file_contents="""[a
+paragraph inspired link](
+/paragraph
+"paragraph")
+""",
+        set_args=["plugins.md044.names=ParaGraph"],
+        use_strict_config=True,
+        scan_expected_return_code=1,
+        scan_expected_output="""{temp_source_path}:2:1: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+{temp_source_path}:4:2: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+""",
+        fix_expected_file_contents="""[a
+ParaGraph inspired link](
+/paragraph
+"ParaGraph")
+""",
+    ),
+    pluginRuleTest(
+        "bad_inline_image",
+        source_file_contents="""![a paragraph inspired link](/paragraph "paragraph")
+""",
+        set_args=["plugins.md044.names=ParaGraph"],
+        use_strict_config=True,
+        scan_expected_return_code=1,
+        scan_expected_output="""{temp_source_path}:1:5: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+{temp_source_path}:1:42: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+""",
+        fix_expected_file_contents="""![a ParaGraph inspired link](/paragraph "ParaGraph")
+""",
+    ),
+    pluginRuleTest(
+        "bad_inline_image_multiple_lines_one",
+        source_file_contents="""![a paragraph inspired link](
+/paragraph
+"paragraph")
+""",
+        set_args=["plugins.md044.names=ParaGraph"],
+        use_strict_config=True,
+        scan_expected_return_code=1,
+        scan_expected_output="""{temp_source_path}:1:5: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+{temp_source_path}:3:2: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+""",
+        fix_expected_file_contents="""![a ParaGraph inspired link](
+/paragraph
+"ParaGraph")
+""",
+    ),
+    pluginRuleTest(
+        "bad_inline_image_multiple_lines_two",
+        source_file_contents="""![a paragraph inspired link](
+/paragraph
+"this is
+a very long paragraph")
+""",
+        set_args=["plugins.md044.names=ParaGraph"],
+        use_strict_config=True,
+        scan_expected_return_code=1,
+        scan_expected_output="""{temp_source_path}:1:5: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+{temp_source_path}:4:13: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+""",
+        fix_expected_file_contents="""![a ParaGraph inspired link](
+/paragraph
+"this is
+a very long ParaGraph")
+""",
+    ),
+    pluginRuleTest(
+        "bad_full_link",
+        source_file_contents="""this is
+[a paragraph inspired link][bar]
+link
+
+[bar]: /url "a paragraph title"
+""",
+        set_args=["plugins.md044.names=ParaGraph"],
+        use_strict_config=True,
+        scan_expected_return_code=1,
+        scan_expected_output="""{temp_source_path}:2:4: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+{temp_source_path}:5:16: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+""",
+        fix_expected_file_contents="""this is
+[a ParaGraph inspired link][bar]
+link
 
-@pytest.mark.rules
-def test_md044_good_full_image_multiple():
-    """
-    Test to make sure this rule does trigger with a document that
-    contains normal paragraphs containing multiples of the word with
-    improper capitalization and configuration to match, some within
-    a Full Image element over multiple lines.
-    """
+[bar]: /url "a ParaGraph title"
+""",
+    ),
+    pluginRuleTest(
+        "bad_full_link_multiple",
+        source_file_contents="""this is
+[a
+paragraph inspired link][ba
+r]
+link
+
+[ba
+r]: /url "a
+paragraph title"
+""",
+        set_args=["plugins.md044.names=ParaGraph"],
+        use_strict_config=True,
+        scan_expected_return_code=1,
+        scan_expected_output="""{temp_source_path}:3:1: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+{temp_source_path}:9:1: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+""",
+        fix_expected_file_contents="""this is
+[a
+ParaGraph inspired link][ba
+r]
+link
+
+[ba
+r]: /url "a
+ParaGraph title"
+""",
+    ),
+    pluginRuleTest(
+        "bad_full_image",
+        source_file_contents="""this is
+![a paragraph inspired link][bar]
+link
+
+[bar]: /url "a paragraph title"
+""",
+        set_args=["plugins.md044.names=ParaGraph"],
+        use_strict_config=True,
+        scan_expected_return_code=1,
+        scan_expected_output="""{temp_source_path}:2:5: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+{temp_source_path}:5:16: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+""",
+        fix_expected_file_contents="""this is
+![a ParaGraph inspired link][bar]
+link
 
-    # Arrange
-    scanner = MarkdownScanner()
-    source_path = os.path.join(
-        "test", "resources", "rules", "md044", "good_full_image_multiple.md"
-    )
-    supplied_arguments = [
-        "--set",
-        "plugins.md044.names=ParaGraph",
-        "scan",
-        source_path,
-    ]
-
-    expected_return_code = 1
-    expected_output = (
-        f"{source_path}:3:1: "
-        + "MD044: Proper names should have the correct capitalization "
-        + "[Expected: ParaGraph; Actual: paragraph] (proper-names)\n"
-        + f"{source_path}:9:1: "
-        + "MD044: Proper names should have the correct capitalization "
-        + "[Expected: ParaGraph; Actual: paragraph] (proper-names)"
-    )
-    expected_error = ""
+[bar]: /url "a ParaGraph title"
+""",
+    ),
+    pluginRuleTest(
+        "bad_full_image_multiple",
+        source_file_contents="""this is
+![a
+paragraph inspired link][ba
+r]
+link
+
+[ba
+r]: /url "a
+paragraph title"
+""",
+        set_args=["plugins.md044.names=ParaGraph"],
+        use_strict_config=True,
+        scan_expected_return_code=1,
+        scan_expected_output="""{temp_source_path}:3:1: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+{temp_source_path}:9:1: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+""",
+        fix_expected_file_contents="""this is
+![a
+ParaGraph inspired link][ba
+r]
+link
+
+[ba
+r]: /url "a
+ParaGraph title"
+""",
+    ),
+    pluginRuleTest(
+        "bad_collapsed_link",
+        use_debug=True,
+        source_file_contents="""this is a
+[collapsed
+paragraph][]
+link
+
+[collapsed
+paragraph]: /url "a paragraph title"
+""",
+        set_args=["plugins.md044.names=ParaGraph"],
+        use_strict_config=True,
+        scan_expected_return_code=1,
+        scan_expected_output="""{temp_source_path}:3:1: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+{temp_source_path}:7:1: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+{temp_source_path}:7:21: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+""",
+        fix_expected_file_contents="""this is a
+[collapsed
+ParaGraph][]
+link
 
-    # Act
-    execute_results = scanner.invoke_main(arguments=supplied_arguments)
+[collapsed
+ParaGraph]: /url "a ParaGraph title"
+""",
+    ),
+    pluginRuleTest(
+        "bad_collapsed_link_multiple",
+        source_file_contents="""this is a
+[collapsed
+link paragraph][]
+link
+
+[collapsed
+link paragraph]: /url "a
+big paragraph title"
+""",
+        set_args=["plugins.md044.names=ParaGraph"],
+        use_strict_config=True,
+        scan_expected_return_code=1,
+        scan_expected_output="""{temp_source_path}:3:6: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+{temp_source_path}:7:6: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+{temp_source_path}:8:5: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+""",
+        fix_expected_file_contents="""this is a
+[collapsed
+link ParaGraph][]
+link
+
+[collapsed
+link ParaGraph]: /url "a
+big ParaGraph title"
+""",
+    ),
+    pluginRuleTest(
+        "bad_collapsed_image",
+        source_file_contents="""this is a
+![collapsed
+paragraph][]
+link
+
+[collapsed
+paragraph]: /url "a paragraph title"
+""",
+        set_args=["plugins.md044.names=ParaGraph"],
+        use_strict_config=True,
+        scan_expected_return_code=1,
+        scan_expected_output="""{temp_source_path}:3:1: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+{temp_source_path}:7:1: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+{temp_source_path}:7:21: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+""",
+        fix_expected_file_contents="""this is a
+![collapsed
+ParaGraph][]
+link
 
-    # Assert
-    execute_results.assert_results(
-        expected_output, expected_error, expected_return_code
-    )
+[collapsed
+ParaGraph]: /url "a ParaGraph title"
+""",
+    ),
+    pluginRuleTest(
+        "bad_collapsed_image_multiple",
+        source_file_contents="""this is a
+![collapsed
+paragraph][]
+link
+
+[collapsed
+paragraph]: /url "a
+big paragraph title"
+""",
+        set_args=["plugins.md044.names=ParaGraph"],
+        use_strict_config=True,
+        scan_expected_return_code=1,
+        scan_expected_output="""{temp_source_path}:3:1: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+{temp_source_path}:7:1: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+{temp_source_path}:8:5: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+""",
+        fix_expected_file_contents="""this is a
+![collapsed
+ParaGraph][]
+link
+
+[collapsed
+ParaGraph]: /url "a
+big ParaGraph title"
+""",
+    ),
+    pluginRuleTest(
+        "bad_shortcut_link",
+        use_debug=True,
+        source_file_contents="""this is a
+[another
+paragraph]
+link
+
+[another
+paragraph]: /url "a paragraph title"
+""",
+        set_args=["plugins.md044.names=ParaGraph"],
+        use_strict_config=True,
+        scan_expected_return_code=1,
+        scan_expected_output="""{temp_source_path}:3:1: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+{temp_source_path}:7:1: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+{temp_source_path}:7:21: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+""",
+        fix_expected_file_contents="""this is a
+[another
+ParaGraph]
+link
 
+[another
+ParaGraph]: /url "a ParaGraph title"
+""",
+    ),
+    pluginRuleTest(
+        "bad_shortcut_link_no_title",
+        use_debug=True,
+        source_file_contents="""this is a
+[another
+paragraph]
+link
+
+[another
+paragraph]: /url
+""",
+        set_args=["plugins.md044.names=ParaGraph"],
+        use_strict_config=True,
+        scan_expected_return_code=1,
+        scan_expected_output="""{temp_source_path}:3:1: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+{temp_source_path}:7:1: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+""",
+        fix_expected_file_contents="""this is a
+[another
+ParaGraph]
+link
 
-@pytest.mark.rules
-def test_md044_good_collapsed_link():
-    """
-    Test to make sure this rule does trigger with a document that
-    contains normal paragraphs containing multiples of the word with
-    improper capitalization and configuration to match, some within
-    a Collapsed Link element.
-    """
+[another
+ParaGraph]: /url
+""",
+    ),
+    pluginRuleTest(
+        "bad_shortcut_link_backslash",
+        use_debug=True,
+        source_file_contents="""this is a
+[paragraph \\! paragraph]
+link
+
+[paragraph \\! paragraph]: /paragraph "a paragraph \\! paragraph title"
+""",
+        set_args=["plugins.md044.names=ParaGraph"],
+        use_strict_config=True,
+        scan_expected_return_code=1,
+        scan_expected_output="""{temp_source_path}:2:2: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+{temp_source_path}:2:15: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+{temp_source_path}:5:2: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+{temp_source_path}:5:15: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+{temp_source_path}:5:41: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+{temp_source_path}:5:54: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+""",
+        fix_expected_file_contents="""this is a
+[ParaGraph \\! ParaGraph]
+link
 
-    # Arrange
-    scanner = MarkdownScanner()
-    source_path = os.path.join(
-        "test", "resources", "rules", "md044", "good_collapsed_link.md"
-    )
-    supplied_arguments = [
-        "--set",
-        "plugins.md044.names=ParaGraph",
-        "scan",
-        source_path,
-    ]
-
-    expected_return_code = 1
-    expected_output = (
-        f"{source_path}:3:1: "
-        + "MD044: Proper names should have the correct capitalization "
-        + "[Expected: ParaGraph; Actual: paragraph] (proper-names)\n"
-        + f"{source_path}:7:1: "
-        + "MD044: Proper names should have the correct capitalization "
-        + "[Expected: ParaGraph; Actual: paragraph] (proper-names)\n"
-        + f"{source_path}:7:21: "
-        + "MD044: Proper names should have the correct capitalization "
-        + "[Expected: ParaGraph; Actual: paragraph] (proper-names)"
-    )
-    expected_error = ""
+[ParaGraph \\! ParaGraph]: /paragraph "a ParaGraph \\! ParaGraph title"
+""",
+    ),
+    pluginRuleTest(
+        "bad_shortcut_link_reference",
+        use_debug=True,
+        source_file_contents="""this is a
+[paragraph &amp; paragraph]
+link
+
+[paragraph &amp; paragraph]: /paragraph "a paragraph &amp; paragraph title"
+""",
+        set_args=["plugins.md044.names=ParaGraph"],
+        use_strict_config=True,
+        scan_expected_return_code=1,
+        scan_expected_output="""{temp_source_path}:2:2: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+{temp_source_path}:2:18: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+{temp_source_path}:5:2: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+{temp_source_path}:5:18: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+{temp_source_path}:5:44: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+{temp_source_path}:5:60: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+""",
+        fix_expected_file_contents="""this is a
+[ParaGraph &amp; ParaGraph]
+link
 
-    # Act
-    execute_results = scanner.invoke_main(arguments=supplied_arguments)
+[ParaGraph &amp; ParaGraph]: /paragraph "a ParaGraph &amp; ParaGraph title"
+""",
+    ),
+    pluginRuleTest(
+        "bad_shortcut_link_multiple",
+        source_file_contents="""this is a
+[collapsed
+link paragraph]
+link
+
+[collapsed
+link paragraph]: /url "a
+big paragraph title"
+""",
+        set_args=["plugins.md044.names=ParaGraph"],
+        use_strict_config=True,
+        scan_expected_return_code=1,
+        scan_expected_output="""{temp_source_path}:3:6: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+{temp_source_path}:7:6: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+{temp_source_path}:8:5: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+""",
+        fix_expected_file_contents="""this is a
+[collapsed
+link ParaGraph]
+link
+
+[collapsed
+link ParaGraph]: /url "a
+big ParaGraph title"
+""",
+    ),
+    pluginRuleTest(
+        "bad_shortcut_image",
+        source_file_contents="""this is a
+![collapsed
+paragraph]
+link
+
+[collapsed
+paragraph]: /url "a paragraph title"
+""",
+        set_args=["plugins.md044.names=ParaGraph"],
+        use_strict_config=True,
+        scan_expected_return_code=1,
+        scan_expected_output="""{temp_source_path}:3:1: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+{temp_source_path}:7:1: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+{temp_source_path}:7:21: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+""",
+        fix_expected_file_contents="""this is a
+![collapsed
+ParaGraph]
+link
 
-    # Assert
-    execute_results.assert_results(
-        expected_output, expected_error, expected_return_code
-    )
+[collapsed
+ParaGraph]: /url "a ParaGraph title"
+""",
+    ),
+    pluginRuleTest(
+        "bad_shortcut_image_multiple",
+        source_file_contents="""this is a
+![collapsed
+paragraph]
+link
+
+[collapsed
+paragraph]: /url "a
+big paragraph title"
+""",
+        set_args=["plugins.md044.names=ParaGraph"],
+        use_strict_config=True,
+        scan_expected_return_code=1,
+        scan_expected_output="""{temp_source_path}:3:1: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+{temp_source_path}:7:1: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+{temp_source_path}:8:5: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+""",
+        fix_expected_file_contents="""this is a
+![collapsed
+ParaGraph]
+link
+
+[collapsed
+ParaGraph]: /url "a
+big ParaGraph title"
+""",
+    ),
+    pluginRuleTest(
+        "mix_md044_md037",
+        source_file_contents="""this * paragraph * is the best!
+""",
+        set_args=["plugins.md044.names=ParaGraph"],
+        use_strict_config=True,
+        # disable_rules=__plugin_disable_md007,
+        scan_expected_return_code=1,
+        scan_expected_output="""{temp_source_path}:1:7: MD037: Spaces inside emphasis markers (no-space-in-emphasis)
+{temp_source_path}:1:8: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+{temp_source_path}:1:17: MD037: Spaces inside emphasis markers (no-space-in-emphasis)
+""",
+        fix_expected_file_contents="""this *ParaGraph* is the best!
+""",
+    ),
+    pluginRuleTest(
+        "mix_md044_md038",
+        source_file_contents="""this this is ` paragraph` is the best!
+""",
+        set_args=["plugins.md044.names=ParaGraph"],
+        use_strict_config=True,
+        # disable_rules=__plugin_disable_md007,
+        scan_expected_return_code=1,
+        scan_expected_output="""{temp_source_path}:1:14: MD038: Spaces inside code span elements (no-space-in-code)
+{temp_source_path}:1:16: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+""",
+        fix_expected_file_contents="""this this is `ParaGraph` is the best!
+""",
+    ),
+    pluginRuleTest(
+        "mix_md044_md039",
+        source_file_contents="""this link
+[ paragraph ](https://www.example.com)
+is bad
+""",
+        set_args=["plugins.md044.names=ParaGraph"],
+        use_strict_config=True,
+        # disable_rules=__plugin_disable_md007,
+        scan_expected_return_code=1,
+        scan_expected_output="""{temp_source_path}:2:1: MD039: Spaces inside link text (no-space-in-links)
+{temp_source_path}:2:3: MD044: Proper names should have the correct capitalization [Expected: ParaGraph; Actual: paragraph] (proper-names)
+""",
+        fix_expected_file_contents="""this link
+[ParaGraph](https://www.example.com)
+is bad
+""",
+    ),
+]
+fixTests = []
+for i in scanTests:
+    if i.fix_expected_file_contents:
+        fixTests.append(i)
 
 
-@pytest.mark.rules
-def test_md044_good_collapsed_link_multiple():
+@pytest.mark.parametrize("test", scanTests, ids=id_test_plug_rule_fn)
+def test_md044_scan(test: pluginRuleTest) -> None:
     """
-    Test to make sure this rule does trigger with a document that
-    contains normal paragraphs containing multiples of the word with
-    improper capitalization and configuration to match, some within
-    a Collapsed Link element over multiple lines.
+    Execute a parameterized scan test for plugin md001.
     """
+    execute_scan_test(test, "md044")
 
-    # Arrange
-    scanner = MarkdownScanner()
-    source_path = os.path.join(
-        "test", "resources", "rules", "md044", "good_collapsed_link_multiple.md"
-    )
-    supplied_arguments = [
-        "--set",
-        "plugins.md044.names=ParaGraph",
-        "scan",
-        source_path,
-    ]
-
-    expected_return_code = 1
-    expected_output = (
-        f"{source_path}:3:6: "
-        + "MD044: Proper names should have the correct capitalization "
-        + "[Expected: ParaGraph; Actual: paragraph] (proper-names)\n"
-        + f"{source_path}:7:6: "
-        + "MD044: Proper names should have the correct capitalization "
-        + "[Expected: ParaGraph; Actual: paragraph] (proper-names)\n"
-        + f"{source_path}:8:5: "
-        + "MD044: Proper names should have the correct capitalization "
-        + "[Expected: ParaGraph; Actual: paragraph] (proper-names)"
-    )
-    expected_error = ""
-
-    # Act
-    execute_results = scanner.invoke_main(arguments=supplied_arguments)
 
-    # Assert
-    execute_results.assert_results(
-        expected_output, expected_error, expected_return_code
-    )
-
-
-@pytest.mark.rules
-def test_md044_good_collapsed_image():
+@pytest.mark.parametrize("test", fixTests, ids=id_test_plug_rule_fn)
+def test_md044_fix(test: pluginRuleTest) -> None:
     """
-    Test to make sure this rule does trigger with a document that
-    contains normal paragraphs containing multiples of the word with
-    improper capitalization and configuration to match, some within
-    a Collapsed Image element.
+    Execute a parameterized fix test for plugin md001.
     """
-
-    # Arrange
-    scanner = MarkdownScanner()
-    source_path = os.path.join(
-        "test", "resources", "rules", "md044", "good_collapsed_image.md"
-    )
-    supplied_arguments = [
-        "--set",
-        "plugins.md044.names=ParaGraph",
-        "scan",
-        source_path,
-    ]
-
-    expected_return_code = 1
-    expected_output = (
-        f"{source_path}:3:1: "
-        + "MD044: Proper names should have the correct capitalization "
-        + "[Expected: ParaGraph; Actual: paragraph] (proper-names)\n"
-        + f"{source_path}:7:1: "
-        + "MD044: Proper names should have the correct capitalization "
-        + "[Expected: ParaGraph; Actual: paragraph] (proper-names)\n"
-        + f"{source_path}:7:21: "
-        + "MD044: Proper names should have the correct capitalization "
-        + "[Expected: ParaGraph; Actual: paragraph] (proper-names)"
-    )
-    expected_error = ""
-
-    # Act
-    execute_results = scanner.invoke_main(arguments=supplied_arguments)
-
-    # Assert
-    execute_results.assert_results(
-        expected_output, expected_error, expected_return_code
-    )
+    execute_fix_test(test)
 
 
-@pytest.mark.rules
-def test_md044_good_collapsed_image_multiple():
+@pytest.mark.parametrize("test", configTests, ids=id_test_plug_rule_fn)
+def test_md044_config(test: pluginRuleTest) -> None:
     """
-    Test to make sure this rule does trigger with a document that
-    contains normal paragraphs containing multiples of the word with
-    improper capitalization and configuration to match, some within
-    a Collapsed Image element over multiple lines.
+    Execute a parameterized fix test for plugin md001.
     """
-
-    # Arrange
-    scanner = MarkdownScanner()
-    source_path = os.path.join(
-        "test", "resources", "rules", "md044", "good_collapsed_image_multiple.md"
-    )
-    supplied_arguments = [
-        "--set",
-        "plugins.md044.names=ParaGraph",
-        "scan",
-        source_path,
-    ]
-
-    expected_return_code = 1
-    expected_output = (
-        f"{source_path}:3:1: "
-        + "MD044: Proper names should have the correct capitalization "
-        + "[Expected: ParaGraph; Actual: paragraph] (proper-names)\n"
-        + f"{source_path}:7:1: "
-        + "MD044: Proper names should have the correct capitalization "
-        + "[Expected: ParaGraph; Actual: paragraph] (proper-names)\n"
-        + f"{source_path}:8:5: "
-        + "MD044: Proper names should have the correct capitalization "
-        + "[Expected: ParaGraph; Actual: paragraph] (proper-names)"
-    )
-    expected_error = ""
-
-    # Act
-    execute_results = scanner.invoke_main(arguments=supplied_arguments)
-
-    # Assert
-    execute_results.assert_results(
-        expected_output, expected_error, expected_return_code
+    execute_configuration_test(
+        test,
+        file_contents="""this is a paragraph without any capitalization errors
+""",
     )
 
 
diff --git a/test/rules/test_plugin_manager.py b/test/rules/test_plugin_manager.py
index d9b06705..c938c16a 100644
--- a/test/rules/test_plugin_manager.py
+++ b/test/rules/test_plugin_manager.py
@@ -1329,7 +1329,7 @@ def test_markdown_with_plugins_list_only():
   md042   no-empty-links                  True       True       0.5.0    No
   md043   required-headings, required-he  True       True       0.6.0    No
           aders
-  md044   proper-names                    True       True       0.6.0    No
+  md044   proper-names                    True       True       0.7.0    Yes
   md045   no-alt-text                     True       True       0.5.0    No
   md046   code-block-style                True       True       0.6.0    No
   md047   single-trailing-newline         True       True       0.5.1    Yes
@@ -1413,7 +1413,7 @@ def test_markdown_with_plugins_list_only_all():
   md042   no-empty-links                  True       True       0.5.0    No
   md043   required-headings, required-he  True       True       0.6.0    No
           aders
-  md044   proper-names                    True       True       0.6.0    No
+  md044   proper-names                    True       True       0.7.0    Yes
   md045   no-alt-text                     True       True       0.5.0    No
   md046   code-block-style                True       True       0.6.0    No
   md047   single-trailing-newline         True       True       0.5.1    Yes
diff --git a/test/rules/utils.py b/test/rules/utils.py
index 09f4861c..94e3b267 100644
--- a/test/rules/utils.py
+++ b/test/rules/utils.py
@@ -184,30 +184,48 @@ def execute_fix_test(test: pluginRuleTest):
         assert_file_is_as_expected(temp_source_path, expected_file_contents)
 
 
-def execute_configuration_test(test: pluginConfigErrorTest, file_to_use: str):
+def execute_configuration_test(
+    test: pluginConfigErrorTest,
+    file_to_use: Optional[str] = None,
+    file_contents: Optional[str] = None,
+):
     scanner = MarkdownScanner()
 
-    temp_source_path = copy_to_temporary_file(file_to_use)
-    supplied_arguments = []
-    if test.use_strict_config:
-        supplied_arguments.append("--strict-config")
-    if test.set_args:
-        for next_set_arg in test.set_args:
-            supplied_arguments.extend(("--set", next_set_arg))
+    temp_source_path = None
+    try:
+        if file_to_use is not None:
+            temp_source_path = copy_to_temporary_file(file_to_use)
+        elif file_contents is not None:
+            temp_source_path = write_temporary_configuration(
+                file_to_use, file_name_suffix=".md"
+            )
+        else:
+            raise AssertionError(
+                "One of `file_to_use` and `file_contents` must be specified."
+            )
+        supplied_arguments = []
+        if test.use_strict_config:
+            supplied_arguments.append("--strict-config")
+        if test.set_args:
+            for next_set_arg in test.set_args:
+                supplied_arguments.extend(("--set", next_set_arg))
 
-    supplied_arguments.extend(("scan", temp_source_path))
+        supplied_arguments.extend(("scan", temp_source_path))
 
-    expected_return_code = 1
-    expected_output = ""
-    expected_error = test.expected_error
+        expected_return_code = 1
+        expected_output = ""
+        expected_error = test.expected_error
 
-    # Act
-    execute_results = scanner.invoke_main(arguments=supplied_arguments)
+        # Act
+        execute_results = scanner.invoke_main(arguments=supplied_arguments)
 
-    # Assert
-    execute_results.assert_results(
-        expected_output, expected_error, expected_return_code
-    )
+        # Assert
+        execute_results.assert_results(
+            expected_output, expected_error, expected_return_code
+        )
+    finally:
+        if temp_source_path is not None and os.path.isfile(temp_source_path):
+            os.remove(temp_source_path)
 
 
 @dataclass
diff --git a/test/utils.py b/test/utils.py
index 33830600..f7398561 100644
--- a/test/utils.py
+++ b/test/utils.py
@@ -274,7 +274,7 @@ def write_temporary_configuration(
     directory=None,
     file_name_prefix=None,
     file_name_suffix=None,
-):
+) -> str:
     """
     Write the configuration as a temporary file that is kept around.
     """