Repository: mkdocs/mkdocs (language: python)

Issue:
draft_docs does not support comments, which are shown in the docs
The [documentation for `draft_docs`](https://www.mkdocs.org/user-guide/configuration/#draft_docs) shows inline comments, like this:

```yaml
draft_docs: |
  drafts/               # A "drafts" directory anywhere.
  _unpublished.md       # A md file ending in _unpublished.md
  !/foo_unpublished.md  # But keep this particular file.
```

However, it seems that adding comments like that causes the pattern matching to break (presumably the comments get included in the pattern).

I copied this section verbatim as a starting point, but it didn't cause the matching pages to be excluded from the build, and it took a surprising amount of trial and error to work out what the problem was. As soon as I removed the inline comments, everything started working as expected. Sorry if it's just me being a bit dim, but I doubt I'll be the only one.

I'm not sure if it this is a problem with the docs (i.e. not expected to work, and the explanations would be better as prose outside the example) or with the code (it's a bug and the comments should get automatically stripped).

The same issue probably applies to `exclude_docs`.


Discussion / hints:
Hi @pxc, thanks for the report. I'd consider this a docs issue that must be fixed urgently :smile: 

From https://git-scm.com/docs/gitignore#_pattern_format:

> A line starting with # serves as a comment. Put a backslash ("\") in front of the first hash for patterns that begin with a hash.

So it seems comments are supported, but on their own lines only, not after a pattern on the same line.

And indeed [pathspec](https://pypi.org/project/pathspec/) (the library used by MkDocs to parse the paths) shows the same thing: comments allowed on their own line only.

So in the end I suggest we update the docs like:

```yaml
draft_docs: |
  # A "drafts" directory anywhere.
  drafts/

  # A md file ending in _unpublished.md
  _unpublished.md

  # But keep this particular file.
  !/foo_unpublished.md
```
Thanks @pawamoy .

Also, for the second example, I had to go for `*_unpublished.md` to pick up those files (which seems to work at any depth without needing a `**/` prefix). I think the `_unpublished.md` given will not match `some_file_unpublished.md` even in the `docs/` directory root.
Would you like to send a PR @pxc?

Fix patch:
diff --git a/docs/user-guide/configuration.md b/docs/user-guide/configuration.md
index 69992c1a0f..0d76b428dd 100644
--- a/docs/user-guide/configuration.md
+++ b/docs/user-guide/configuration.md
@@ -305,10 +305,17 @@ Example:
 
 ```yaml
 exclude_docs: |
-  api-config.json    # A file with this name anywhere.
-  /requirements.txt  # Top-level "docs/requirements.txt".
-  *.py               # Any file with this extension anywhere.
-  !/foo/example.py   # But keep this particular file.
+  # A file with this name anywhere.
+  api-config.json
+
+  # Top-level "docs/requirements.txt".
+  /requirements.txt
+
+  # Any file with this extension anywhere.
+  *.py
+
+  # But keep this particular file.
+  !/foo/example.py
 ```
 
 This follows the [.gitignore pattern format](https://git-scm.com/docs/gitignore#_pattern_format).
@@ -327,7 +334,8 @@ Otherwise you could for example opt only certain dot-files back into the site:
 
 ```yaml
 exclude_docs: |
-  !.assets  # Don't exclude '.assets' although all other '.*' are excluded
+  # Don't exclude '.assets' although all other '.*' are excluded
+  !.assets
 ```
 
 ### draft_docs
@@ -340,9 +348,14 @@ Example:
 
 ```yaml
 draft_docs: |
-  drafts/               # A "drafts" directory anywhere.
-  _unpublished.md       # A md file ending in _unpublished.md
-  !/foo_unpublished.md  # But keep this particular file.
+  # A "drafts" directory anywhere.
+  drafts/
+
+  # A Markdown file ending in _unpublished.md anywhere.
+  *_unpublished.md
+
+  # But keep this particular file.
+  !/foo_unpublished.md
 ```
 
 This follows the [.gitignore pattern format](https://git-scm.com/docs/gitignore#_pattern_format).


Test patch:
diff --git a/mkdocs/tests/__init__.py b/mkdocs/tests/__init__.py
index e0248786db..7f41675eec 100644
--- a/mkdocs/tests/__init__.py
+++ b/mkdocs/tests/__init__.py
@@ -1,7 +1,7 @@
 import logging
 import unittest.util
 
-unittest.util._MAX_LENGTH = 100000
+unittest.util._MAX_LENGTH = 100000  # type: ignore[misc]
 
 
 class DisallowLogsHandler(logging.Handler):
diff --git a/mkdocs/tests/build_tests.py b/mkdocs/tests/build_tests.py
index d2dd3ca04e..4fc1cf4c23 100644
--- a/mkdocs/tests/build_tests.py
+++ b/mkdocs/tests/build_tests.py
@@ -571,6 +571,66 @@ def _assert_build_logs(self, expected):
             del msgs[-1]
         self.assertEqual('\n'.join(msgs), textwrap.dedent(expected).strip('\n'))
 
+    @tempdir(
+        files={
+            'foo_unpublished.md': 'unpublished content to include anyway',
+            'other_unpublished.md': 'unpublished content',
+            'normal_file.md': 'should not be affected',
+            'test/other_unpublished.md': 'more unpublished content',
+            'test/normal_file.md': 'should not be affected',
+        }
+    )
+    @tempdir()
+    def test_draft_docs_with_comments_from_user_guide(self, site_dir, docs_dir):
+        cfg = load_config(
+            docs_dir=docs_dir,
+            site_dir=site_dir,
+            use_directory_urls=False,
+            draft_docs='''
+                # A "drafts" directory anywhere.
+                drafts/
+
+                # A Markdown file ending in _unpublished.md anywhere.
+                *_unpublished.md
+
+                # But keep this particular file.
+                !/foo_unpublished.md
+            ''',
+        )
+
+        with self.subTest(serve_url=None):
+            build.build(cfg)
+            self.assertPathIsFile(site_dir, 'foo_unpublished.html')
+            self.assertPathIsFile(site_dir, 'normal_file.html')
+            self.assertPathIsFile(site_dir, 'test', 'normal_file.html')
+            self.assertPathNotExists(site_dir, 'other_unpublished.html')
+            self.assertPathNotExists(site_dir, 'test', 'other_unpublished.html')
+
+        serve_url = 'http://localhost:123/documentation/'
+        with self.subTest(serve_url=serve_url):
+            expected_logs = '''
+                INFO:The following pages are being built only for the preview but will be excluded from `mkdocs build` per `draft_docs` config:
+                  - http://localhost:123/documentation/other_unpublished.html
+                  - http://localhost:123/documentation/test/other_unpublished.html
+            '''
+            with self._assert_build_logs(expected_logs):
+                build.build(cfg, serve_url=serve_url)
+
+            top_other_path = Path(site_dir, 'other_unpublished.html')
+            self.assertTrue(top_other_path.is_file())
+            self.assertIn('DRAFT', top_other_path.read_text())
+
+            sub_other_path = Path(site_dir, 'test', 'other_unpublished.html')
+            self.assertPathIsFile(sub_other_path)
+            self.assertIn('DRAFT', sub_other_path.read_text())
+
+            self.assertPathIsFile(site_dir, 'foo_unpublished.html')
+            self.assertPathIsFile(site_dir, 'normal_file.html')
+
+            good_path = Path(site_dir, 'test', 'normal_file.html')
+            self.assertPathIsFile(good_path)
+            self.assertNotIn('DRAFT', good_path.read_text())
+
     @tempdir(
         files={
             'test/foo.md': 'page1 content, [bar](bar.md)',