Skip to content

Commit

Permalink
Release 1.6.0 (#3631)
Browse files Browse the repository at this point in the history
  • Loading branch information
oprypin committed Apr 20, 2024
1 parent bce85bf commit 0998fec
Show file tree
Hide file tree
Showing 6 changed files with 257 additions and 9 deletions.
235 changes: 235 additions & 0 deletions docs/about/release-notes.md
Expand Up @@ -27,6 +27,241 @@ The current and past members of the MkDocs team.
* [@oprypin](https://github.com/oprypin/)
* [@ultrabug](https://github.com/ultrabug/)

## Version 1.6.0 (2024-04-20)

### Local preview

* `mkdocs serve` no longer locks up the browser when more than 5 tabs are open. This is achieved by closing the polling connection whenever a tab becomes inactive. Background tabs will no longer auto-reload either - that will instead happen as soon the tab is opened again. Context: #3391

* New flag `serve --open` to open the site in a browser.
After the first build is finished, this flag will cause the default OS Web browser to be opened at the home page of the local site.
Context: #3500

#### Drafts

> DANGER: **Changed from version 1.5.**
**The `exclude_docs` config was split up into two separate concepts.**

The `exclude_docs` config no longer has any special behavior for `mkdocs serve` - it now always completely excludes the listed documents from the site.

If you wish to use the "drafts" functionality like the `exclude_docs` key used to do in MkDocs 1.5, please switch to the **new config key `draft_docs`**.

See [documentation](../user-guide/configuration.md#exclude_docs).

Other changes:

* Reduce warning levels when a "draft" page has a link to a non-existent file. Context: #3449

### Update to deduction of page titles

MkDocs 1.5 had a change in behavior in deducing the page titles from the first heading. Unfortunately this could cause unescaped HTML tags or entities to appear in edge cases.

Now tags are always fully sanitized from the title. Though it still remains the case that [`Page.title`][mkdocs.structure.pages.Page.title] is expected to contain HTML entities and is passed directly to the themes.

Images (notably, emojis in some extensions) get preserved in the title only through their `alt` attribute's value.

Context: #3564, #3578

### Themes

* Built-in themes now also support Polish language (#3613)

#### "readthedocs" theme

* Fix: "readthedocs" theme can now correctly handle deeply nested nav configurations (over 2 levels deep), without confusedly expanding all sections and jumping around vertically. (#3464)

* Fix: "readthedocs" theme now shows a link to the repository (with a generic logo) even when isn't one of the 3 known hosters. (#3435)

* "readthedocs" theme now also has translation for the word "theme" in the footer that mistakenly always remained in English. (#3613, #3625)

#### "mkdocs" theme

The "mkdocs" theme got a big update to a newer version of Bootstrap, meaning a slight overhaul of styles. Colors (most notably of admonitions) have much better contrast.

The "mkdocs" theme now has support for dark mode - both automatic (based on the OS/browser setting) and with a manual toggle. Both of these options are **not** enabled by default and need to be configured explicitly.
See `color_mode`, `user_color_mode_toggle` in [**documentation**](../user-guide/choosing-your-theme.md#mkdocs).

> WARNING: **Possible breaking change.**
>
> jQuery is no longer included into the "mkdocs" theme. If you were relying on it in your scripts, you will need to separately add it first (into mkdocs.yml) as an extra script:
>
> ```yaml
> extra_javascript:
> - https://code.jquery.com/jquery-3.7.1.min.js
> ```
>
> Or even better if the script file is copied and included from your docs dir.
Context: #3493, #3649
### Configuration
#### New "`enabled`" setting for all plugins
You may have seen some plugins take up the convention of having a setting `enabled: false` (or usually controlled through an environment variable) to make the plugin do nothing.
Now *every* plugin has this setting. Plugins can still *choose* to implement this config themselves and decide how it behaves (and unless they drop older versions of MkDocs, they still should for now), but now there's always a fallback for every plugin.
See [**documentation**](../user-guide/configuration.md/#enabled-option). Context: #3395
### Validation
#### Validation of hyperlinks between pages
##### Absolute links
> Historically, within Markdown, MkDocs only recognized **relative** links that lead to another physical `*.md` document (or media file). This is a good convention to follow because then the source pages are also freely browsable without MkDocs, for example on GitHub. Whereas absolute links were left unmodified (making them often not work as expected or, more recently, warned against).
If you dislike having to always use relative links, now you can opt into absolute links and have them work correctly.
If you set the setting `validation.links.absolute_links` to the new value `relative_to_docs`, all Markdown links starting with `/` will be understood as being relative to the `docs_dir` root. The links will then be validated for correctness according to all the other rules that were already working for relative links in prior versions of MkDocs. For the HTML output, these links will still be turned relative so that the site still works reliably.
So, now any document (e.g. "dir1/foo.md") can link to the document "dir2/bar.md" as `[link](/dir2/bar.md)`, in addition to the previously only correct way `[link](../dir2/bar.md)`.
You have to enable the setting, though. The default is still to just skip any processing of such links.
See [**documentation**](../user-guide/configuration.md#validation-of-absolute-links). Context: #3485
###### Absolute links within nav
Absolute links within the `nav:` config were also always skipped. It is now possible to also validate them in the same way with `validation.nav.absolute_links`. Though it makes a bit less sense because then the syntax is simply redundant with the syntax that comes without the leading slash.
##### Anchors
There is a new config setting that is recommended to enable warnings for:
```yaml
validation:
anchors: warn
```
Example of a warning that this can produce:
```text
WARNING - Doc file 'foo/example.md' contains a link '../bar.md#some-heading', but the doc 'foo/bar.md' does not contain an anchor '#some-heading'.
```
Any of the below methods of declaring an anchor will be detected by MkDocs:
```markdown
## Heading producing an anchor
## Another heading {#custom-anchor-for-heading-using-attr-list}
<a id="raw-anchor"></a>
[](){#markdown-anchor-using-attr-list}
```
Plugins and extensions that insert anchors, in order to be compatible with this, need to be developed as treeprocessors that insert `etree` elements as their mode of operation, rather than raw HTML which is undetectable for this purpose.
If you as a user are dealing with falsely reported missing anchors and there's no way to resolve this, you can choose to disable these messages by setting this option to `ignore` (and they are at INFO level by default anyway).
See [**documentation**](../user-guide/configuration.md#validation). Context: #3463
Other changes:
* When the `nav` config is not specified at all, the `not_in_nav` setting (originally added in 1.5.0) gains an additional behavior: documents covered by `not_in_nav` will not be part of the automatically deduced navigation. Context: #3443
* Fix: the `!relative` YAML tag for `markdown_extensions` (originally added in 1.5.0) - it was broken in many typical use cases.
See [**documentation**](../user-guide/configuration.md#paths-relative-to-the-current-file-or-site). Context: #3466
* Config validation now exits on first error, to avoid showing bizarre secondary errors. Context: #3437
* MkDocs used to shorten error messages for unexpected errors such as "file not found", but that is no longer the case, the full error message and stack trace will be possible to see (unless the error has a proper handler, of course). Context: #3445
### Upgrades for plugin developers
#### Plugins can add multiple handlers for the same event type, at multiple priorities
See [`mkdocs.plugins.CombinedEvent`][] in [**documentation**](../dev-guide/plugins.md#event-priorities). Context: #3448
#### Enabling true generated files and expanding the [`File`][mkdocs.structure.files.File] API
See [**documentation**][mkdocs.structure.files.File].
* There is a new pair of attributes [`File.content_string`][mkdocs.structure.files.File.content_string]/[`content_bytes`][mkdocs.structure.files.File.content_bytes] that becomes the official API for obtaining the content of a file and is used by MkDocs itself.
This replaces the old approach where one had to manually read the file located at [`File.abs_src_path`][mkdocs.structure.files.File.abs_src_path], although that is still the primary action that these new attributes do under the hood.
* The content of a `File` can be backed by a string and no longer has to be a real existing file at `abs_src_path`.
It is possible to **set** the attribute `File.content_string` or `File.content_bytes` and it will take precedence over `abs_src_path`.
Further, `abs_src_path` is no longer guaranteed to be present and can be `None` instead. MkDocs itself still uses physical files in all cases, but eventually plugins will appear that don't populate this attribute.
* There is a new constructor [`File.generated()`][mkdocs.structure.files.File.generated] that should be used by plugins instead of the `File()` constructor. It is much more convenient because one doesn't need to manually look up the values such as `docs_dir` and `use_directory_urls`. Its signature is one of:
```python
f = File.generated(config: MkDocsConfig, src_uri: str, content: str | bytes)
f = File.generated(config: MkDocsConfig, src_uri: str, abs_src_path: str)
```
This way, it is now extremely easy to add a virtual file even from a hook:
```python
def on_files(files: Files, config: MkDocsConfig):
files.append(File.generated(config, 'fake/path.md', content="Hello, world!"))
```
For large content it is still best to use physical files, but one no longer needs to manipulate the path by providing a fake unused `docs_dir`.
* There is a new attribute [`File.generated_by`][mkdocs.structure.files.File.generated_by] that arose by convention - for generated files it should be set to the name of the plugin (the key in the `plugins:` collection) that produced this file. This attribute is populated automatically when using the `File.generated()` constructor.
* It is possible to set the [`edit_uri`][mkdocs.structure.files.File.edit_uri] attribute of a `File`, for example from a plugin or hook, to make it different from the default (equal to `src_uri`), and this will be reflected in the edit link of the document. This can be useful because some pages aren't backed by a real file and are instead created dynamically from some other source file or script. So a hook could set the `edit_uri` to that source file or script accordingly.
* The `File` object now stores its original `src_dir`, `dest_dir`, `use_directory_urls` values as attributes.
* Fields of `File` are computed on demand but cached. Only the three above attributes are primary ones, and partly also [`dest_uri`][mkdocs.structure.files.File.dest_uri]. This way, it is possible to, for example, overwrite `dest_uri` of a `File`, and `abs_dest_path` will be calculated based on it. However you need to clear the attribute first using `del f.abs_dest_path`, because the values are cached.
* `File` instances are now hashable (can be used as keys of a `dict`). Two files can no longer be considered "equal" unless it's the exact same instance of `File`.
Other changes:
* The internal storage of `File` objects inside a `Files` object has been reworked, so any plugins that choose to access `Files._files` will get a deprecation warning.
* The order of `File` objects inside a `Files` collection is no longer significant when automatically inferring the `nav`. They get forcibly sorted according to the default alphabetic order.
Context: #3451, #3463
### Hooks and debugging
* Hook files can now import adjacent *.py files using the `import` statement. Previously this was possible to achieve only through a `sys.path` workaround. See the new mention in [documentation](../user-guide/configuration.md#hooks). Context: #3568
* Verbose `-v` log shows the sequence of plugin events in more detail - shows each invoked plugin one by one, not only the event type. Context: #3444
### Deprecations
* Python 3.7 is no longer supported, Python 3.12 is officially supported. Context: #3429
* The theme config file `mkdocs_theme.yml` no longer executes YAML tags. Context: #3465
* The plugin event `on_page_read_source` is soft-deprecated because there is always a better alternative to it (see the new `File` API or just `on_page_markdown`, depending on the desired interaction).
When multiple plugins/hooks apply this event handler, they trample over each other, so now there is a warning in that case.
See [**documentation**](../dev-guide/plugins.md#on_page_read_source). Context: #3503
#### API deprecations
* It is no longer allowed to set `File.page` to a type other than `Page` or a subclass thereof. Context: #3443 - following the deprecation in version 1.5.3 and #3381.
* `Theme._vars` is deprecated - use `theme['foo']` instead of `theme._vars['foo']`
* `utils`: `modified_time()`, `get_html_path()`, `get_url_path()`, `is_html_file()`, `is_template_file()` are removed. `path_to_url()` is deprecated.
* `LiveReloadServer.watch()` no longer accepts a custom callback.
Context: #3429
### Misc
* The `sitemap.xml.gz` file is slightly more reproducible and no longer changes on every build, but instead only once per day (upon a date change). Context: #3460
Other small improvements; see [commit log](https://github.com/mkdocs/mkdocs/compare/1.5.3...1.6.0).
## Version 1.5.3 (2023-09-18)
* Fix `mkdocs serve` sometimes locking up all browser tabs when navigating quickly (#3390)
Expand Down
14 changes: 8 additions & 6 deletions docs/dev-guide/plugins.md
Expand Up @@ -431,11 +431,13 @@ Since MkDocs 1.4, plugins can choose to set a priority value for their events. E
#### ::: mkdocs.plugins.event_priority
There may also arise a need to register a handler for the same event at multiple different priorities.
`CombinedEvent` makes this possible since MkDocs 1.6.
#### ::: mkdocs.plugins.CombinedEvent
> NEW: **New in version 1.6**
>
> There may also arise a need to register a handler for the same event at multiple different priorities.
>
> `CombinedEvent` makes this possible.
>
> #### ::: mkdocs.plugins.CombinedEvent
### Handling Errors
Expand Down Expand Up @@ -504,7 +506,7 @@ To ensure that your plugins' log messages adhere with MkDocs' formatting and `--
`log.error()` is another logging level that is differentiated by its look, but in all other ways it functions the same as `warning`, so it's strange to use it. If your plugin encounters an actual error, it is best to just interrupt the build by raising [`mkdocs.exceptions.PluginError`][] (which will also log an ERROR message).
<!-- -->
> NEW: New in MkDocs 1.5
> NEW: **New in version 1.5**
>
> MkDocs now provides a `get_plugin_logger()` convenience function that returns a logger like the above that is also prefixed with the plugin's name.
>
Expand Down
2 changes: 1 addition & 1 deletion mkdocs/__init__.py
Expand Up @@ -2,4 +2,4 @@


# For acceptable version formats, see https://www.python.org/dev/peps/pep-0440/
__version__ = '1.5.3'
__version__ = '1.6.0'
6 changes: 5 additions & 1 deletion mkdocs/plugins.py
@@ -1,4 +1,5 @@
"""Implements the plugin API for MkDocs."""

from __future__ import annotations

import logging
Expand Down Expand Up @@ -323,7 +324,10 @@ def on_pre_page(self, page: Page, /, *, config: MkDocsConfig, files: Files) -> P

def on_page_read_source(self, /, *, page: Page, config: MkDocsConfig) -> str | None:
"""
Deprecated: Since MkDocs 1.6, instead set `content_bytes`/`content_string` of a `File`.
> DEPRECATED: Instead of this event, prefer one of these alternatives:
>
> * Since MkDocs 1.6, instead set `content_bytes`/`content_string` of a `File` inside [`on_files`][].
> * Usually (although it's not an exact alternative), `on_page_markdown` can serve the same purpose.
The `on_page_read_source` event can replace the default mechanism to read
the contents of a page's source from the filesystem.
Expand Down
6 changes: 6 additions & 0 deletions mkdocs/structure/files.py
Expand Up @@ -354,6 +354,12 @@ def __repr__(self):

@utils.weak_property
def edit_uri(self) -> str | None:
"""
A path relative to the source repository to use for the "edit" button.
Defaults to `src_uri` and can be overwritten.
For generated files this should be set to `None`.
"""
return self.src_uri if self.generated_by is None else None

def _get_stem(self) -> str:
Expand Down
3 changes: 2 additions & 1 deletion mkdocs/structure/pages.py
Expand Up @@ -231,7 +231,8 @@ def title(self) -> str | None: # type: ignore[override]
Before calling `read_source()`, this value is empty. It can also be updated by `render()`.
Check these in order and use the first that returns a valid title:
Checks these in order and uses the first that returns a valid title:
- value provided on init (passed in from config)
- value of metadata 'title'
- content of the first H1 in Markdown content
Expand Down

0 comments on commit 0998fec

Please sign in to comment.