Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add additional 'drafts' level to inclusion #3476

Merged
merged 6 commits into from
Dec 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 4 additions & 1 deletion docs/about/release-notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,6 @@ The `exclude_docs` config follows the [.gitignore pattern format](https://git-sc
```yaml
exclude_docs: |
*.py # Excludes e.g. docs/hooks/foo.py
/drafts # Excludes e.g. docs/drafts/hello.md
/requirements.txt # Excludes docs/requirements.txt
```

Expand All @@ -169,6 +168,10 @@ See [**documentation**](../user-guide/configuration.md#exclude_docs). Context: #

#### Drafts

> DANGER: **Dropped from version 1.6:**
>
> The `exclude_docs` config no longer applies the "drafts" functionality for `mkdocs serve`. This was renamed to [`draft_docs`](../user-guide/configuration.md#draft_docs).

The `exclude_docs` config has another behavior: all excluded Markdown pages will still be previewable in `mkdocs serve` only, just with a "DRAFT" marker on top. Then they will of course be excluded from `mkdocs build` or `gh-deploy`.

If you don't want `mkdocs serve` to have any special behaviors and instead want it to perform completely normal builds, use the new flag `mkdocs serve --clean`.
Expand Down
24 changes: 21 additions & 3 deletions docs/user-guide/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -295,23 +295,24 @@ sub-directories. Index files will always be listed first within a sub-section.

NEW: **New in version 1.5.**

> DANGER: **Changed in version 1.6:**
>
> This config no longer applies the "drafts" functionality for `mkdocs serve`. If you have draft documents that you want available in "serve" and not "build", replace `exclude_docs` with the new [`draft_docs`](#draft_docs) config option.

This config defines patterns of files (under [`docs_dir`](#docs_dir)) to not be picked up into the built site.

Example:

```yaml
exclude_docs: |
api-config.json # A file with this name anywhere.
drafts/ # A "drafts" directory anywhere.
/requirements.txt # Top-level "docs/requirements.txt".
*.py # Any file with this extension anywhere.
!/foo/example.py # But keep this particular file.
```

This follows the [.gitignore pattern format](https://git-scm.com/docs/gitignore#_pattern_format).

Note that `mkdocs serve` does *not* follow this setting and instead displays excluded documents but with a "DRAFT" mark. To prevent this effect, you can run `mkdocs serve --clean`.

The following defaults are always implicitly prepended - to exclude dot-files (and directories) as well as the top-level `templates` directory:

```yaml
Expand All @@ -329,6 +330,23 @@ exclude_docs: |
!.assets # Don't exclude '.assets' although all other '.*' are excluded
```

athackst marked this conversation as resolved.
Show resolved Hide resolved
### draft_docs

NEW: **New in version 1.6.**

This config defines patterns of files (under [`docs_dir`](#docs_dir)) to be treated as a draft. Draft files are available during `mkdocs serve` and include a "DRAFT" mark but will not be included in the build. To prevent this effect and make "serve" behave the same as "build", you can run `mkdocs serve --clean`.

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.
```

This follows the [.gitignore pattern format](https://git-scm.com/docs/gitignore#_pattern_format).

### not_in_nav

NEW: **New in version 1.5.**
Expand Down
4 changes: 2 additions & 2 deletions mkdocs/commands/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ def build(config: MkDocsConfig, *, serve_url: str | None = None, dirty: bool = F
if config.strict:
logging.getLogger('mkdocs').addHandler(warning_counter)

inclusion = InclusionLevel.all if serve_url else InclusionLevel.is_included
inclusion = InclusionLevel.is_in_serve if serve_url else InclusionLevel.is_included

try:
start = time.monotonic()
Expand Down Expand Up @@ -312,7 +312,7 @@ def build(config: MkDocsConfig, *, serve_url: str | None = None, dirty: bool = F
if excluded:
log.info(
"The following pages are being built only for the preview "
"but will be excluded from `mkdocs build` per `exclude_docs`:\n - "
"but will be excluded from `mkdocs build` per `draft_docs` config:\n - "
+ "\n - ".join(excluded)
)

Expand Down
3 changes: 3 additions & 0 deletions mkdocs/config/defaults.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ class MkDocsConfig(base.Config):
exclude_docs = c.Optional(c.PathSpec())
"""Gitignore-like patterns of files (relative to docs dir) to exclude from the site."""

draft_docs = c.Optional(c.PathSpec())
"""Gitignore-like patterns of files (relative to docs dir) to mark as draft."""

not_in_nav = c.Optional(c.PathSpec())
"""Gitignore-like patterns of files (relative to docs dir) that are not intended to be in the nav.

Expand Down
14 changes: 11 additions & 3 deletions mkdocs/structure/files.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@


class InclusionLevel(enum.Enum):
EXCLUDED = -2
EXCLUDED = -3
"""The file is excluded and will not be processed."""
DRAFT = -2
"""The file is excluded from the final site, but will still be populated during `mkdocs serve`."""
NOT_IN_NAV = -1
"""The file is part of the site, but doesn't produce nav warnings."""
Expand All @@ -41,10 +43,13 @@ def all(self):
return True

def is_included(self):
return self.value > self.EXCLUDED.value
return self.value > self.DRAFT.value

def is_excluded(self):
return self.value <= self.EXCLUDED.value
return self.value <= self.DRAFT.value

def is_in_serve(self):
return self.value >= self.DRAFT.value

def is_in_nav(self):
return self.value > self.NOT_IN_NAV.value
Expand Down Expand Up @@ -326,12 +331,15 @@ def set_exclusions(files: Iterable[File], config: MkDocsConfig) -> None:
"""Re-calculate which files are excluded, based on the patterns in the config."""
exclude: pathspec.gitignore.GitIgnoreSpec | None = config.get('exclude_docs')
exclude = _default_exclude + exclude if exclude else _default_exclude
drafts: pathspec.gitignore.GitIgnoreSpec | None = config.get('draft_docs')
nav_exclude: pathspec.gitignore.GitIgnoreSpec | None = config.get('not_in_nav')

for file in files:
if file.inclusion == InclusionLevel.UNDEFINED:
if exclude.match_file(file.src_uri):
file.inclusion = InclusionLevel.EXCLUDED
elif drafts and drafts.match_file(file.src_uri):
file.inclusion = InclusionLevel.DRAFT
elif nav_exclude and nav_exclude.match_file(file.src_uri):
file.inclusion = InclusionLevel.NOT_IN_NAV
else:
Expand Down
20 changes: 11 additions & 9 deletions mkdocs/tests/build_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -580,12 +580,12 @@ def _assert_build_logs(self, expected):
}
)
@tempdir()
def test_exclude_pages_with_invalid_links(self, site_dir, docs_dir):
def test_draft_pages_with_invalid_links(self, site_dir, docs_dir):
cfg = load_config(
docs_dir=docs_dir,
site_dir=site_dir,
use_directory_urls=False,
exclude_docs='ba*.md',
draft_docs='ba*.md',
)

with self.subTest(serve_url=None):
Expand All @@ -603,8 +603,7 @@ def test_exclude_pages_with_invalid_links(self, site_dir, docs_dir):
expected_logs = '''
INFO:Doc file 'test/bar.md' contains a relative link 'nonexistent.md', but the target 'test/nonexistent.md' is not found among documentation files.
INFO:Doc file 'test/foo.md' contains a link to 'test/bar.md' which is excluded from the built site.
INFO:The following pages are being built only for the preview but will be excluded from `mkdocs build` per `exclude_docs`:
- http://localhost:123/documentation/.zoo.html
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/test/bar.html
- http://localhost:123/documentation/test/baz.html
'''
Expand All @@ -619,7 +618,7 @@ def test_exclude_pages_with_invalid_links(self, site_dir, docs_dir):
self.assertPathIsFile(baz_path)
self.assertIn('DRAFT', baz_path.read_text())

self.assertPathIsFile(site_dir, '.zoo.html')
self.assertPathNotExists(site_dir, '.zoo.html')

@tempdir(
files={
Expand Down Expand Up @@ -686,13 +685,14 @@ def on_files_2(files: Files, config: MkDocsConfig) -> None:
config.nav = Path(f.abs_src_path).read_text().splitlines()

for serve_url in None, 'http://localhost:123/':
for exclude in 'full', 'nav', None:
for exclude in 'full', 'drafts', 'nav', None:
with self.subTest(serve_url=serve_url, exclude=exclude):
cfg = load_config(
docs_dir=docs_dir,
site_dir=site_dir,
use_directory_urls=False,
exclude_docs='SUMMARY.md' if exclude == 'full' else '',
draft_docs='SUMMARY.md' if exclude == 'drafts' else '',
not_in_nav='SUMMARY.md' if exclude == 'nav' else '',
)
cfg.plugins.events['files'] += [on_files_1, on_files_2]
Expand All @@ -703,9 +703,9 @@ def on_files_2(files: Files, config: MkDocsConfig) -> None:
INFO:The following pages exist in the docs directory, but are not included in the "nav" configuration:
- SUMMARY.md
'''
if exclude == 'full' and serve_url:
if exclude == 'drafts' and serve_url:
expected_logs = '''
INFO:The following pages are being built only for the preview but will be excluded from `mkdocs build` per `exclude_docs`:
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/SUMMARY.html
'''
with self._assert_build_logs(expected_logs):
Expand All @@ -719,7 +719,9 @@ def on_files_2(files: Files, config: MkDocsConfig) -> None:
)

summary_path = Path(site_dir, 'SUMMARY.html')
if exclude == 'full' and not serve_url:
if exclude == 'full':
self.assertPathNotExists(summary_path)
elif exclude == 'drafts' and not serve_url:
self.assertPathNotExists(summary_path)
else:
self.assertPathExists(summary_path)
Expand Down