diff --git a/.gitignore b/.gitignore
index 8e8a83d68..f97bd86a6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -119,3 +119,9 @@ tests/snapshot_tests/output
# Sandbox folder - convenient place for us to develop small test apps without leaving the repo
sandbox/
+
+# Cache of screenshots used in the docs
+.screenshot_cache
+
+# Used by mkdocs-material social plugin
+.cache
diff --git a/Makefile b/Makefile
index 429996c68..9d71e69d7 100644
--- a/Makefile
+++ b/Makefile
@@ -11,8 +11,10 @@ format:
format-check:
black --check src
docs-serve:
+ rm -rf .screenshot_cache
mkdocs serve
docs-build:
mkdocs build
docs-deploy:
+ rm -rf .screenshot_cache
mkdocs gh-deploy
diff --git a/docs/reference/app.md b/docs/api/app.md
similarity index 100%
rename from docs/reference/app.md
rename to docs/api/app.md
diff --git a/docs/reference/binding.md b/docs/api/binding.md
similarity index 100%
rename from docs/reference/binding.md
rename to docs/api/binding.md
diff --git a/docs/reference/button.md b/docs/api/button.md
similarity index 100%
rename from docs/reference/button.md
rename to docs/api/button.md
diff --git a/docs/reference/checkbox.md b/docs/api/checkbox.md
similarity index 100%
rename from docs/reference/checkbox.md
rename to docs/api/checkbox.md
diff --git a/docs/reference/color.md b/docs/api/color.md
similarity index 100%
rename from docs/reference/color.md
rename to docs/api/color.md
diff --git a/docs/reference/containers.md b/docs/api/containers.md
similarity index 100%
rename from docs/reference/containers.md
rename to docs/api/containers.md
diff --git a/docs/reference/data_table.md b/docs/api/data_table.md
similarity index 100%
rename from docs/reference/data_table.md
rename to docs/api/data_table.md
diff --git a/docs/reference/dom_node.md b/docs/api/dom_node.md
similarity index 100%
rename from docs/reference/dom_node.md
rename to docs/api/dom_node.md
diff --git a/docs/reference/events.md b/docs/api/events.md
similarity index 100%
rename from docs/reference/events.md
rename to docs/api/events.md
diff --git a/docs/reference/footer.md b/docs/api/footer.md
similarity index 100%
rename from docs/reference/footer.md
rename to docs/api/footer.md
diff --git a/docs/reference/geometry.md b/docs/api/geometry.md
similarity index 100%
rename from docs/reference/geometry.md
rename to docs/api/geometry.md
diff --git a/docs/reference/header.md b/docs/api/header.md
similarity index 100%
rename from docs/reference/header.md
rename to docs/api/header.md
diff --git a/docs/api/index.md b/docs/api/index.md
new file mode 100644
index 000000000..989244f2c
--- /dev/null
+++ b/docs/api/index.md
@@ -0,0 +1,5 @@
+# API
+
+This is a API-level reference to the Textual API. Click the links to your left (or in the burger menu) to open a reference for each module.
+
+If you are new to Textual, you may want to read the [tutorial](./../tutorial.md) or [guide](../guide/index.md) first.
diff --git a/docs/reference/input.md b/docs/api/input.md
similarity index 100%
rename from docs/reference/input.md
rename to docs/api/input.md
diff --git a/docs/reference/message.md b/docs/api/message.md
similarity index 100%
rename from docs/reference/message.md
rename to docs/api/message.md
diff --git a/docs/reference/message_pump.md b/docs/api/message_pump.md
similarity index 100%
rename from docs/reference/message_pump.md
rename to docs/api/message_pump.md
diff --git a/docs/reference/pilot.md b/docs/api/pilot.md
similarity index 100%
rename from docs/reference/pilot.md
rename to docs/api/pilot.md
diff --git a/docs/reference/query.md b/docs/api/query.md
similarity index 100%
rename from docs/reference/query.md
rename to docs/api/query.md
diff --git a/docs/reference/reactive.md b/docs/api/reactive.md
similarity index 100%
rename from docs/reference/reactive.md
rename to docs/api/reactive.md
diff --git a/docs/reference/screen.md b/docs/api/screen.md
similarity index 100%
rename from docs/reference/screen.md
rename to docs/api/screen.md
diff --git a/docs/reference/static.md b/docs/api/static.md
similarity index 100%
rename from docs/reference/static.md
rename to docs/api/static.md
diff --git a/docs/reference/timer.md b/docs/api/timer.md
similarity index 100%
rename from docs/reference/timer.md
rename to docs/api/timer.md
diff --git a/docs/reference/widget.md b/docs/api/widget.md
similarity index 100%
rename from docs/reference/widget.md
rename to docs/api/widget.md
diff --git a/docs/blog/.authors.yml b/docs/blog/.authors.yml
new file mode 100644
index 000000000..e233de92d
--- /dev/null
+++ b/docs/blog/.authors.yml
@@ -0,0 +1,4 @@
+willmcgugan:
+ name: Will McGugan
+ description: CEO / code-monkey
+ avatar: https://github.com/willmcgugan.png
diff --git a/docs/blog/index.md b/docs/blog/index.md
new file mode 100644
index 000000000..5ae47bcdb
--- /dev/null
+++ b/docs/blog/index.md
@@ -0,0 +1,3 @@
+# Textual Blog
+
+Welcome to the Textual blog, where we post about the latest releases and developments in the Textual world.
diff --git a/docs/blog/posts/helo-world.md b/docs/blog/posts/helo-world.md
new file mode 100644
index 000000000..90dab804b
--- /dev/null
+++ b/docs/blog/posts/helo-world.md
@@ -0,0 +1,19 @@
+---
+draft: false
+date: 2022-11-06
+categories:
+ - News
+authors:
+ - willmcgugan
+---
+
+# New Blog
+
+Welcome to the first post on the Textual blog.
+
+
+
+I plan on using this as a place to make announcements regarding new releases of Textual, and any other relevant news.
+
+The first piece of news is that we've reorganized this site a little. The Events, Styles, and Widgets references are now under "Reference", and what used to be under "Reference" is now "API" which contains API-level documentation. I hope that's a little clearer than it used to be!
+
diff --git a/docs/custom_theme/main.html b/docs/custom_theme/main.html
index 8e2960ddd..eaf708583 100644
--- a/docs/custom_theme/main.html
+++ b/docs/custom_theme/main.html
@@ -5,4 +5,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
{% endblock %}
diff --git a/docs/events/index.md b/docs/events/index.md
index 5b3430c34..6fe8635ee 100644
--- a/docs/events/index.md
+++ b/docs/events/index.md
@@ -1,3 +1,5 @@
# Events
A reference to Textual [events](../guide/events.md).
+
+See the links to the left of the page, or in the hamburger menu (three horizontal bars, top left).
diff --git a/docs/guide/index.md b/docs/guide/index.md
index 412a09b13..f9cb74d74 100644
--- a/docs/guide/index.md
+++ b/docs/guide/index.md
@@ -1,4 +1,4 @@
-# Textual Guide
+# Guide
Welcome to the Textual Guide! An in-depth reference on how to build apps with Textual.
diff --git a/docs/help.md b/docs/help.md
index 6f2d86939..488d0919b 100644
--- a/docs/help.md
+++ b/docs/help.md
@@ -1,20 +1,16 @@
----
-hide:
- - navigation
----
-
# Help
-Here's where to go if you need help with Textual.
+If you need help with any aspect of Textual, let us know! We would be happy to hear from you.
## Bugs and feature requests
Report bugs via GitHub on the Textual [issues](https://github.com/Textualize/textual/issues) page. You can also post feature requests via GitHub issues, but see the [roadmap](./roadmap.md) first.
+## Discord Server
+
+For more realtime feedback or chat, join our discord server to connect with the [Textual community](https://discord.gg/Enf6Z3qhVr).
+
## Forum
Visit the [Textual forum](https://community.textualize.io/) for Textual (and Rich) discussions.
-## Discord Server
-
-For more realtime feedback or chat, join our discord server to connect with the [Textual community](https://discord.gg/Enf6Z3qhVr).
diff --git a/docs/reference/index.md b/docs/reference/index.md
index 8e129acd1..1ddd462b1 100644
--- a/docs/reference/index.md
+++ b/docs/reference/index.md
@@ -1,3 +1,35 @@
# Reference
-A reference to the Textual public APIs.
+Welcome to the Textual Reference.
+
+
+
+- :octicons-book-16:{ .lg .middle } __Events__
+
+ ---
+
+ Events are how Textual communicates with your application.
+
+ :octicons-arrow-right-24: [Events Reference](../events/index.md)
+
+
+- :octicons-book-16:{ .lg .middle } __Styles__
+
+ ---
+
+ All the styles you can use to take your Textual app to the next level.
+
+ [:octicons-arrow-right-24: Styles Reference](../styles/index.md)
+
+
+- :octicons-book-16:{ .lg .middle } __Widgets__
+
+ ---
+
+ How to use the many widgets builtin to Textual.
+
+ :octicons-arrow-right-24: [Widgets Reference](../widgets/index.md)
+
+
+
+
diff --git a/docs/roadmap.md b/docs/roadmap.md
index 3828365fa..a1b0c9347 100644
--- a/docs/roadmap.md
+++ b/docs/roadmap.md
@@ -1,3 +1,9 @@
+---
+hide:
+ - navigation
+---
+
+
# Roadmap
We ([textualize.io](https://www.textualize.io/)) are actively building and maintaining Textual.
diff --git a/docs/styles/index.md b/docs/styles/index.md
index 67b6f6c85..309f8f744 100644
--- a/docs/styles/index.md
+++ b/docs/styles/index.md
@@ -1,3 +1,5 @@
# Styles
A reference to Widget [styles](../guide/styles.md).
+
+See the links to the left of the page, or in the hamburger menu (three horizontal bars, top left).
diff --git a/docs/stylesheets/custom.css b/docs/stylesheets/custom.css
index ea1639ef1..d33303601 100644
--- a/docs/stylesheets/custom.css
+++ b/docs/stylesheets/custom.css
@@ -13,11 +13,11 @@ h3 .doc-heading code {
monospace;
}
-body[data-md-color-primary="black"] .excalidraw svg {
+body[data-md-color-primary="indigo"] .excalidraw svg {
filter: invert(100%) hue-rotate(180deg);
}
-body[data-md-color-primary="black"] .excalidraw svg rect {
+body[data-md-color-primary="indigo"] .excalidraw svg rect {
fill: transparent;
}
diff --git a/docs/widgets/button.md b/docs/widgets/button.md
index f8aad75de..6683ee73a 100644
--- a/docs/widgets/button.md
+++ b/docs/widgets/button.md
@@ -55,4 +55,4 @@ _No other attributes_
## See Also
-* [Button](../reference/button.md) code reference
+* [Button](../api/button.md) code reference
diff --git a/docs/widgets/checkbox.md b/docs/widgets/checkbox.md
index 1404a43c5..c1ef5265a 100644
--- a/docs/widgets/checkbox.md
+++ b/docs/widgets/checkbox.md
@@ -29,7 +29,7 @@ The example below shows checkboxes in various states.
## Reactive Attributes
| Name | Type | Default | Description |
-|---------|--------|---------|------------------------------------|
+| ------- | ------ | ------- | ---------------------------------- |
| `value` | `bool` | `False` | The default value of the checkbox. |
## Messages
@@ -43,7 +43,7 @@ The `Checkbox.Changed` message is sent when the checkbox is toggled.
#### Attributes
| attribute | type | purpose |
-|-----------|--------|--------------------------------|
+| --------- | ------ | ------------------------------ |
| `value` | `bool` | The new value of the checkbox. |
## Additional Notes
@@ -54,4 +54,4 @@ The `Checkbox.Changed` message is sent when the checkbox is toggled.
## See Also
-- [Checkbox](../reference/checkbox.md) code reference
+- [Checkbox](../api/checkbox.md) code reference
diff --git a/docs/widgets/footer.md b/docs/widgets/footer.md
index ee1d4eeb7..e45b147db 100644
--- a/docs/widgets/footer.md
+++ b/docs/widgets/footer.md
@@ -39,4 +39,4 @@ This widget sends no messages.
## See Also
-* [Footer](../reference/footer.md) code reference
+* [Footer](../api/footer.md) code reference
diff --git a/docs/widgets/header.md b/docs/widgets/header.md
index 685ce04ee..f5dd191e7 100644
--- a/docs/widgets/header.md
+++ b/docs/widgets/header.md
@@ -32,4 +32,4 @@ This widget sends no messages.
## See Also
-* [Header](../reference/header.md) code reference
+* [Header](../api/header.md) code reference
diff --git a/docs/widgets/index.md b/docs/widgets/index.md
index 90c80104e..1d9262dca 100644
--- a/docs/widgets/index.md
+++ b/docs/widgets/index.md
@@ -1,3 +1,5 @@
# Widgets
A reference to the builtin [widgets](../guide/widgets.md).
+
+See the links to the left of the page, or in the hamburger menu (three horizontal bars, top left).
diff --git a/docs/widgets/input.md b/docs/widgets/input.md
index 43d728d54..586fd1ca5 100644
--- a/docs/widgets/input.md
+++ b/docs/widgets/input.md
@@ -54,7 +54,7 @@ The `Input.Submitted` message is sent when you press ++enter++ with the text fie
#### Attributes
| attribute | type | purpose |
-|-----------|-------|----------------------------------|
+| --------- | ----- | -------------------------------- |
| `value` | `str` | The new value in the text input. |
@@ -64,4 +64,4 @@ The `Input.Submitted` message is sent when you press ++enter++ with the text fie
## See Also
-* [Input](../reference/input.md) code reference
+* [Input](../api/input.md) code reference
diff --git a/docs/widgets/static.md b/docs/widgets/static.md
index 3ed68ac95..342e2daf7 100644
--- a/docs/widgets/static.md
+++ b/docs/widgets/static.md
@@ -31,4 +31,4 @@ This widget sends no messages.
## See Also
-* [Static](../reference/static.md) code reference
+* [Static](../api/static.md) code reference
diff --git a/mkdocs.yml b/mkdocs.yml
index 3700d97af..46f51a2d1 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -7,6 +7,7 @@ nav:
- Introduction:
- "index.md"
- "getting_started.md"
+ - "help.md"
- "tutorial.md"
- Guide:
- "guide/index.md"
@@ -25,97 +26,100 @@ nav:
- "guide/animation.md"
- "guide/screens.md"
- "roadmap.md"
- - Events:
- - "events/index.md"
- - "events/blur.md"
- - "events/descendant_blur.md"
- - "events/descendant_focus.md"
- - "events/enter.md"
- - "events/focus.md"
- - "events/hide.md"
- - "events/key.md"
- - "events/leave.md"
- - "events/load.md"
- - "events/mount.md"
- - "events/mouse_capture.md"
- - "events/click.md"
- - "events/mouse_down.md"
- - "events/mouse_move.md"
- - "events/mouse_release.md"
- - "events/mouse_scroll_down.md"
- - "events/mouse_scroll_up.md"
- - "events/mouse_up.md"
- - "events/paste.md"
- - "events/resize.md"
- - "events/screen_resume.md"
- - "events/screen_suspend.md"
- - "events/show.md"
- - Styles:
- - "styles/index.md"
- - "styles/align.md"
- - "styles/background.md"
- - "styles/border.md"
- - "styles/box_sizing.md"
- - "styles/color.md"
- - "styles/content_align.md"
- - "styles/display.md"
- - "styles/dock.md"
- - "styles/grid.md"
- - "styles/height.md"
- - "styles/layer.md"
- - "styles/layers.md"
- - "styles/layout.md"
- - "styles/links.md"
- - "styles/margin.md"
- - "styles/max_height.md"
- - "styles/max_width.md"
- - "styles/min_height.md"
- - "styles/min_width.md"
- - "styles/offset.md"
- - "styles/opacity.md"
- - "styles/outline.md"
- - "styles/overflow.md"
- - "styles/padding.md"
- - "styles/scrollbar.md"
- - "styles/scrollbar_gutter.md"
- - "styles/scrollbar_size.md"
- - "styles/text_align.md"
- - "styles/text_style.md"
- - "styles/text_opacity.md"
- - "styles/tint.md"
- - "styles/visibility.md"
- - "styles/width.md"
- - Widgets:
- - "widgets/index.md"
- - "widgets/button.md"
- - "widgets/checkbox.md"
- - "widgets/data_table.md"
- - "widgets/footer.md"
- - "widgets/header.md"
- - "widgets/input.md"
- - "widgets/static.md"
- - "widgets/tree_control.md"
- Reference:
- - "reference/app.md"
- - "reference/button.md"
- - "reference/color.md"
- - "reference/containers.md"
- - "reference/dom_node.md"
- - "reference/events.md"
- - "reference/footer.md"
- - "reference/geometry.md"
- - "reference/header.md"
- "reference/index.md"
- - "reference/message_pump.md"
- - "reference/message.md"
- - "reference/pilot.md"
- - "reference/query.md"
- - "reference/reactive.md"
- - "reference/screen.md"
- - "reference/static.md"
- - "reference/timer.md"
- - "reference/widget.md"
- - "help.md"
+ - Events:
+ - "events/index.md"
+ - "events/blur.md"
+ - "events/descendant_blur.md"
+ - "events/descendant_focus.md"
+ - "events/enter.md"
+ - "events/focus.md"
+ - "events/hide.md"
+ - "events/key.md"
+ - "events/leave.md"
+ - "events/load.md"
+ - "events/mount.md"
+ - "events/mouse_capture.md"
+ - "events/click.md"
+ - "events/mouse_down.md"
+ - "events/mouse_move.md"
+ - "events/mouse_release.md"
+ - "events/mouse_scroll_down.md"
+ - "events/mouse_scroll_up.md"
+ - "events/mouse_up.md"
+ - "events/paste.md"
+ - "events/resize.md"
+ - "events/screen_resume.md"
+ - "events/screen_suspend.md"
+ - "events/show.md"
+ - Styles:
+ - "styles/index.md"
+ - "styles/align.md"
+ - "styles/background.md"
+ - "styles/border.md"
+ - "styles/box_sizing.md"
+ - "styles/color.md"
+ - "styles/content_align.md"
+ - "styles/display.md"
+ - "styles/dock.md"
+ - "styles/grid.md"
+ - "styles/height.md"
+ - "styles/layer.md"
+ - "styles/layers.md"
+ - "styles/layout.md"
+ - "styles/links.md"
+ - "styles/margin.md"
+ - "styles/max_height.md"
+ - "styles/max_width.md"
+ - "styles/min_height.md"
+ - "styles/min_width.md"
+ - "styles/offset.md"
+ - "styles/opacity.md"
+ - "styles/outline.md"
+ - "styles/overflow.md"
+ - "styles/padding.md"
+ - "styles/scrollbar.md"
+ - "styles/scrollbar_gutter.md"
+ - "styles/scrollbar_size.md"
+ - "styles/text_align.md"
+ - "styles/text_style.md"
+ - "styles/text_opacity.md"
+ - "styles/tint.md"
+ - "styles/visibility.md"
+ - "styles/width.md"
+ - Widgets:
+ - "widgets/index.md"
+ - "widgets/button.md"
+ - "widgets/checkbox.md"
+ - "widgets/data_table.md"
+ - "widgets/footer.md"
+ - "widgets/header.md"
+ - "widgets/input.md"
+ - "widgets/static.md"
+ - "widgets/tree_control.md"
+ - API:
+ - "api/index.md"
+ - "api/app.md"
+ - "api/button.md"
+ - "api/color.md"
+ - "api/containers.md"
+ - "api/dom_node.md"
+ - "api/events.md"
+ - "api/footer.md"
+ - "api/geometry.md"
+ - "api/header.md"
+ - "api/message_pump.md"
+ - "api/message.md"
+ - "api/pilot.md"
+ - "api/query.md"
+ - "api/reactive.md"
+ - "api/screen.md"
+ - "api/static.md"
+ - "api/timer.md"
+ - "api/widget.md"
+ - "Blog":
+ - blog/index.md
@@ -171,13 +175,21 @@ theme:
name: Switch to dark mode
- media: "(prefers-color-scheme: dark)"
scheme: slate
- primary: black
+ primary: indigo
toggle:
icon: material/weather-night
name: Switch to light mode
plugins:
+- blog:
+- rss:
+ match_path: blog/posts/.*
+ date_from_meta:
+ as_creation: date
+ categories:
+ - categories
+ - tags
- search:
- autorefs:
- mkdocstrings:
diff --git a/poetry.lock b/poetry.lock
index 5aaf7bfbb..8f20ae475 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -182,7 +182,7 @@ python-versions = "*"
[[package]]
name = "exceptiongroup"
-version = "1.0.0"
+version = "1.0.1"
description = "Backport of PEP 654 (exception groups)"
category = "dev"
optional = false
@@ -225,6 +225,29 @@ python-dateutil = ">=2.8.1"
[package.extras]
dev = ["flake8", "markdown", "twine", "wheel"]
+[[package]]
+name = "gitdb"
+version = "4.0.9"
+description = "Git Object Database"
+category = "dev"
+optional = false
+python-versions = ">=3.6"
+
+[package.dependencies]
+smmap = ">=3.0.1,<6"
+
+[[package]]
+name = "gitpython"
+version = "3.1.29"
+description = "GitPython is a python library used to interact with Git repositories"
+category = "dev"
+optional = false
+python-versions = ">=3.7"
+
+[package.dependencies]
+gitdb = ">=4.0.1,<5"
+typing-extensions = {version = ">=3.7.4.3", markers = "python_version < \"3.8\""}
+
[[package]]
name = "griffe"
version = "0.23.0"
@@ -329,7 +352,7 @@ python-versions = ">=3.6"
[[package]]
name = "mkdocs"
-version = "1.4.1"
+version = "1.4.2"
description = "Project documentation with Markdown."
category = "dev"
optional = false
@@ -367,7 +390,7 @@ mkdocs = ">=1.1"
[[package]]
name = "mkdocs-material"
-version = "8.5.7"
+version = "8.5.8"
description = "Documentation that simply works"
category = "dev"
optional = false
@@ -377,7 +400,7 @@ python-versions = ">=3.7"
jinja2 = ">=3.0.2"
markdown = ">=3.2"
mkdocs = ">=1.4.0"
-mkdocs-material-extensions = ">=1.0.3"
+mkdocs-material-extensions = ">=1.1"
pygments = ">=2.12"
pymdown-extensions = ">=9.4"
requests = ">=2.26"
@@ -390,6 +413,24 @@ category = "dev"
optional = false
python-versions = ">=3.7"
+[[package]]
+name = "mkdocs-rss-plugin"
+version = "1.5.0"
+description = "MkDocs plugin which generates a static RSS feed using git log and page.meta."
+category = "dev"
+optional = false
+python-versions = ">=3.7, <4"
+
+[package.dependencies]
+GitPython = ">=3.1,<3.2"
+mkdocs = ">=1.1,<2"
+pytz = {version = ">=2022.0.0,<2023.0.0", markers = "python_version < \"3.9\""}
+tzdata = {version = ">=2022.0.0,<2023.0.0", markers = "python_version >= \"3.9\" and sys_platform == \"win32\""}
+
+[package.extras]
+dev = ["black", "feedparser (>=6.0,<6.1)", "flake8 (>=4,<5.1)", "pre-commit (>=2.10,<2.21)", "pytest-cov (>=4.0.0,<4.1.0)", "validator-collection (>=1.5,<1.6)"]
+doc = ["mkdocs-bootswatch (>=1,<2)", "mkdocs-minify-plugin (>=0.5.0,<0.6.0)", "pygments (>=2.5,<3)", "pymdown-extensions (>=7,<10)"]
+
[[package]]
name = "mkdocstrings"
version = "0.19.0"
@@ -507,15 +548,15 @@ python-versions = ">=3.7"
[[package]]
name = "platformdirs"
-version = "2.5.2"
-description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
+version = "2.5.3"
+description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
category = "dev"
optional = false
python-versions = ">=3.7"
[package.extras]
-docs = ["furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx (>=4)", "sphinx-autodoc-typehints (>=1.12)"]
-test = ["appdirs (==1.4.4)", "pytest (>=6)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)"]
+docs = ["furo (>=2022.9.29)", "proselint (>=0.13)", "sphinx (>=5.3)", "sphinx-autodoc-typehints (>=1.19.4)"]
+test = ["appdirs (==1.4.4)", "pytest (>=7.2)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"]
[[package]]
name = "pluggy"
@@ -661,6 +702,14 @@ python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7"
[package.dependencies]
six = ">=1.5"
+[[package]]
+name = "pytz"
+version = "2022.6"
+description = "World timezone definitions, modern and historical"
+category = "dev"
+optional = false
+python-versions = "*"
+
[[package]]
name = "pyyaml"
version = "6.0"
@@ -716,7 +765,7 @@ jupyter = ["ipywidgets (>=7.5.1,<8.0.0)"]
[[package]]
name = "setuptools"
-version = "65.5.0"
+version = "65.5.1"
description = "Easily download, build, install, upgrade, and uninstall Python packages"
category = "dev"
optional = false
@@ -724,7 +773,7 @@ python-versions = ">=3.7"
[package.extras]
docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-notfound-page (==0.8.3)", "sphinx-reredirects", "sphinxcontrib-towncrier"]
-testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8 (<5)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "mock", "pip (>=19.1)", "pip-run (>=8.8)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"]
+testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8 (<5)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pip-run (>=8.8)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"]
testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"]
[[package]]
@@ -735,9 +784,17 @@ category = "dev"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
+[[package]]
+name = "smmap"
+version = "5.0.0"
+description = "A pure Python implementation of a sliding window memory map manager"
+category = "dev"
+optional = false
+python-versions = ">=3.6"
+
[[package]]
name = "syrupy"
-version = "3.0.2"
+version = "3.0.4"
description = "Pytest Snapshot Test Utility"
category = "dev"
optional = false
@@ -790,6 +847,14 @@ category = "main"
optional = false
python-versions = ">=3.7"
+[[package]]
+name = "tzdata"
+version = "2022.6"
+description = "Provider of IANA time zone data"
+category = "dev"
+optional = false
+python-versions = ">=2"
+
[[package]]
name = "urllib3"
version = "1.26.12"
@@ -863,7 +928,7 @@ dev = ["aiohttp", "click", "msgpack"]
[metadata]
lock-version = "1.1"
python-versions = "^3.7"
-content-hash = "cfa35529900ee7fc7bca1e2a189f0240081bdbc75b501b25b394dfce66261c8b"
+content-hash = "9d355751c84f02b15b267922c96b2ca172dfe2e18e0afaf0d2e6794458ef5667"
[metadata.files]
aiohttp = [
@@ -1082,8 +1147,8 @@ distlib = [
{file = "distlib-0.3.6.tar.gz", hash = "sha256:14bad2d9b04d3a36127ac97f30b12a19268f211063d8f8ee4f47108896e11b46"},
]
exceptiongroup = [
- {file = "exceptiongroup-1.0.0-py3-none-any.whl", hash = "sha256:2ac84b496be68464a2da60da518af3785fff8b7ec0d090a581604bc870bdee41"},
- {file = "exceptiongroup-1.0.0.tar.gz", hash = "sha256:affbabf13fb6e98988c38d9c5650e701569fe3c1de3233cfb61c5f33774690ad"},
+ {file = "exceptiongroup-1.0.1-py3-none-any.whl", hash = "sha256:4d6c0aa6dd825810941c792f53d7b8d71da26f5e5f84f20f9508e8f2d33b140a"},
+ {file = "exceptiongroup-1.0.1.tar.gz", hash = "sha256:73866f7f842ede6cb1daa42c4af078e2035e5f7607f0e2c762cc51bb31bbe7b2"},
]
filelock = [
{file = "filelock-3.8.0-py3-none-any.whl", hash = "sha256:617eb4e5eedc82fc5f47b6d61e4d11cb837c56cb4544e39081099fa17ad109d4"},
@@ -1154,6 +1219,14 @@ ghp-import = [
{file = "ghp-import-2.1.0.tar.gz", hash = "sha256:9c535c4c61193c2df8871222567d7fd7e5014d835f97dc7b7439069e2413d343"},
{file = "ghp_import-2.1.0-py3-none-any.whl", hash = "sha256:8337dd7b50877f163d4c0289bc1f1c7f127550241988d568c1db512c4324a619"},
]
+gitdb = [
+ {file = "gitdb-4.0.9-py3-none-any.whl", hash = "sha256:8033ad4e853066ba6ca92050b9df2f89301b8fc8bf7e9324d412a63f8bf1a8fd"},
+ {file = "gitdb-4.0.9.tar.gz", hash = "sha256:bac2fd45c0a1c9cf619e63a90d62bdc63892ef92387424b855792a6cabe789aa"},
+]
+gitpython = [
+ {file = "GitPython-3.1.29-py3-none-any.whl", hash = "sha256:41eea0deec2deea139b459ac03656f0dd28fc4a3387240ec1d3c259a2c47850f"},
+ {file = "GitPython-3.1.29.tar.gz", hash = "sha256:cc36bfc4a3f913e66805a28e84703e419d9c264c1077e537b54f0e1af85dbefd"},
+]
griffe = [
{file = "griffe-0.23.0-py3-none-any.whl", hash = "sha256:cfca5f523808109da3f8cfaa46e325fa2e5bef51120d1146e908c121b56475f0"},
{file = "griffe-0.23.0.tar.gz", hash = "sha256:a639e2968c8e27f56ebcc57f869a03cea7ac7e7f5684bd2429c665f761c4e7bd"},
@@ -1229,21 +1302,25 @@ mergedeep = [
{file = "mergedeep-1.3.4.tar.gz", hash = "sha256:0096d52e9dad9939c3d975a774666af186eda617e6ca84df4c94dec30004f2a8"},
]
mkdocs = [
- {file = "mkdocs-1.4.1-py3-none-any.whl", hash = "sha256:2b7845c2775396214cd408753e4cfb01af3cfed36acc141a84bce2ceec9d705d"},
- {file = "mkdocs-1.4.1.tar.gz", hash = "sha256:07ed90be4062e4ef732bbac2623097b9dca35c67b562c38cfd0bfbc7151758c1"},
+ {file = "mkdocs-1.4.2-py3-none-any.whl", hash = "sha256:c8856a832c1e56702577023cd64cc5f84948280c1c0fcc6af4cd39006ea6aa8c"},
+ {file = "mkdocs-1.4.2.tar.gz", hash = "sha256:8947af423a6d0facf41ea1195b8e1e8c85ad94ac95ae307fe11232e0424b11c5"},
]
mkdocs-autorefs = [
{file = "mkdocs-autorefs-0.4.1.tar.gz", hash = "sha256:70748a7bd025f9ecd6d6feeba8ba63f8e891a1af55f48e366d6d6e78493aba84"},
{file = "mkdocs_autorefs-0.4.1-py3-none-any.whl", hash = "sha256:a2248a9501b29dc0cc8ba4c09f4f47ff121945f6ce33d760f145d6f89d313f5b"},
]
mkdocs-material = [
- {file = "mkdocs_material-8.5.7-py3-none-any.whl", hash = "sha256:07fc70dfa325a8019b99a124751c43e4c1c2a739ed1b0b82c00f823f31c9a1e2"},
- {file = "mkdocs_material-8.5.7.tar.gz", hash = "sha256:ff4c7851b2e5f9a6cfa0a8b247e973ebae753b9836a53bd68742827541ab73e5"},
+ {file = "mkdocs_material-8.5.8-py3-none-any.whl", hash = "sha256:7ff092299e3a63cef99cd87e4a6cc7e7d9ec31fd190d766fd147c35572e6d593"},
+ {file = "mkdocs_material-8.5.8.tar.gz", hash = "sha256:61396251819cf7f547f70a09ce6a7edb2ff5d32e47b9199769020b2d20a83d44"},
]
mkdocs-material-extensions = [
{file = "mkdocs_material_extensions-1.1-py3-none-any.whl", hash = "sha256:bcc2e5fc70c0ec50e59703ee6e639d87c7e664c0c441c014ea84461a90f1e902"},
{file = "mkdocs_material_extensions-1.1.tar.gz", hash = "sha256:96ca979dae66d65c2099eefe189b49d5ac62f76afb59c38e069ffc7cf3c131ec"},
]
+mkdocs-rss-plugin = [
+ {file = "mkdocs-rss-plugin-1.5.0.tar.gz", hash = "sha256:4178b3830dcbad9b53b12459e315b1aad6b37d1e7e5c56c686866a10f99878a4"},
+ {file = "mkdocs_rss_plugin-1.5.0-py2.py3-none-any.whl", hash = "sha256:2ab14c20bf6b7983acbe50181e7e4a0778731d9c2d5c38107ca7047a7abd2165"},
+]
mkdocstrings = [
{file = "mkdocstrings-0.19.0-py3-none-any.whl", hash = "sha256:3217d510d385c961f69385a670b2677e68e07b5fea4a504d86bf54c006c87c7d"},
{file = "mkdocstrings-0.19.0.tar.gz", hash = "sha256:efa34a67bad11229d532d89f6836a8a215937548623b64f3698a1df62e01cc3e"},
@@ -1414,8 +1491,8 @@ pathspec = [
{file = "pathspec-0.10.1.tar.gz", hash = "sha256:7ace6161b621d31e7902eb6b5ae148d12cfd23f4a249b9ffb6b9fee12084323d"},
]
platformdirs = [
- {file = "platformdirs-2.5.2-py3-none-any.whl", hash = "sha256:027d8e83a2d7de06bbac4e5ef7e023c02b863d7ea5d079477e722bb41ab25788"},
- {file = "platformdirs-2.5.2.tar.gz", hash = "sha256:58c8abb07dcb441e6ee4b11d8df0ac856038f944ab98b7be6b27b2a3c7feef19"},
+ {file = "platformdirs-2.5.3-py3-none-any.whl", hash = "sha256:0cb405749187a194f444c25c82ef7225232f11564721eabffc6ec70df83b11cb"},
+ {file = "platformdirs-2.5.3.tar.gz", hash = "sha256:6e52c21afff35cb659c6e52d8b4d61b9bd544557180440538f255d9382c8cbe0"},
]
pluggy = [
{file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"},
@@ -1457,6 +1534,10 @@ python-dateutil = [
{file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"},
{file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"},
]
+pytz = [
+ {file = "pytz-2022.6-py2.py3-none-any.whl", hash = "sha256:222439474e9c98fced559f1709d89e6c9cbf8d79c794ff3eb9f8800064291427"},
+ {file = "pytz-2022.6.tar.gz", hash = "sha256:e89512406b793ca39f5971bc999cc538ce125c0e51c27941bef4568b460095e2"},
+]
pyyaml = [
{file = "PyYAML-6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53"},
{file = "PyYAML-6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c"},
@@ -1512,16 +1593,20 @@ rich = [
{file = "rich-12.6.0.tar.gz", hash = "sha256:ba3a3775974105c221d31141f2c116f4fd65c5ceb0698657a11e9f295ec93fd0"},
]
setuptools = [
- {file = "setuptools-65.5.0-py3-none-any.whl", hash = "sha256:f62ea9da9ed6289bfe868cd6845968a2c854d1427f8548d52cae02a42b4f0356"},
- {file = "setuptools-65.5.0.tar.gz", hash = "sha256:512e5536220e38146176efb833d4a62aa726b7bbff82cfbc8ba9eaa3996e0b17"},
+ {file = "setuptools-65.5.1-py3-none-any.whl", hash = "sha256:d0b9a8433464d5800cbe05094acf5c6d52a91bfac9b52bcfc4d41382be5d5d31"},
+ {file = "setuptools-65.5.1.tar.gz", hash = "sha256:e197a19aa8ec9722928f2206f8de752def0e4c9fc6953527360d1c36d94ddb2f"},
]
six = [
{file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"},
{file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"},
]
+smmap = [
+ {file = "smmap-5.0.0-py3-none-any.whl", hash = "sha256:2aba19d6a040e78d8b09de5c57e96207b09ed71d8e55ce0959eeee6c8e190d94"},
+ {file = "smmap-5.0.0.tar.gz", hash = "sha256:c840e62059cd3be204b0c9c9f74be2c09d5648eddd4580d9314c3ecde0b30936"},
+]
syrupy = [
- {file = "syrupy-3.0.2-py3-none-any.whl", hash = "sha256:b7afb1424ddbdbfba6c7340fd7b939dd129879f891172dd2e59ec971fb40c60d"},
- {file = "syrupy-3.0.2.tar.gz", hash = "sha256:5425a23f816743227542c91c83d2bf0847f029284236f8c30e10147bdde4f80e"},
+ {file = "syrupy-3.0.4-py3-none-any.whl", hash = "sha256:85c4f5c51618eefab02e60e0172664a22987f20ea17efa815c4832cd64822fc6"},
+ {file = "syrupy-3.0.4.tar.gz", hash = "sha256:cbb1e28149340e31a01d3644a234d3195a4b6806c7b8c18e4930ca9add5c6af1"},
]
time-machine = [
{file = "time-machine-2.8.2.tar.gz", hash = "sha256:2ff3cd145c381ac87b1c35400475a8f019b15dc2267861aad0466f55b49e7813"},
@@ -1613,6 +1698,10 @@ typing-extensions = [
{file = "typing_extensions-4.4.0-py3-none-any.whl", hash = "sha256:16fa4864408f655d35ec496218b85f79b3437c829e93320c7c9215ccfd92489e"},
{file = "typing_extensions-4.4.0.tar.gz", hash = "sha256:1511434bb92bf8dd198c12b1cc812e800d4181cfcb867674e0f8279cc93087aa"},
]
+tzdata = [
+ {file = "tzdata-2022.6-py2.py3-none-any.whl", hash = "sha256:04a680bdc5b15750c39c12a448885a51134a27ec9af83667663f0b3a1bf3f342"},
+ {file = "tzdata-2022.6.tar.gz", hash = "sha256:91f11db4503385928c15598c98573e3af07e7229181bee5375bd30f1695ddcae"},
+]
urllib3 = [
{file = "urllib3-1.26.12-py2.py3-none-any.whl", hash = "sha256:b930dd878d5a8afb066a637fbb35144fe7901e3b209d1cd4f524bd0e9deee997"},
{file = "urllib3-1.26.12.tar.gz", hash = "sha256:3fa96cf423e6987997fc326ae8df396db2a8b7c667747d47ddd8ecba91f4a74e"},
diff --git a/pyproject.toml b/pyproject.toml
index 9b8b252a4..2f271373f 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -56,6 +56,9 @@ time-machine = "^2.6.0"
Jinja2 = "<3.1.0"
syrupy = "^3.0.0"
+[tool.poetry.group.dev.dependencies]
+mkdocs-rss-plugin = "^1.5.0"
+
[tool.black]
includes = "src"
diff --git a/src/textual/_doc.py b/src/textual/_doc.py
index 2d6bce67b..32c2ea31d 100644
--- a/src/textual/_doc.py
+++ b/src/textual/_doc.py
@@ -1,6 +1,8 @@
from __future__ import annotations
+import hashlib
import os
+from pathlib import Path
import shlex
from typing import Iterable
@@ -9,6 +11,9 @@ from textual.pilot import Pilot
from textual._import_app import import_app
+SCREENSHOT_CACHE = ".screenshot_cache"
+
+
# This module defines our "Custom Fences", powered by SuperFences
# @link https://facelessuser.github.io/pymdown-extensions/extensions/superfences/#custom-fences
def format_svg(source, language, css_class, options, md, attrs, **kwargs) -> str:
@@ -74,6 +79,24 @@ def take_svg_screenshot(
if title is None:
title = app.title
+ def get_cache_key(app: App) -> str:
+ hash = hashlib.md5()
+ file_paths = [app_path] + app.css_path
+ for path in file_paths:
+ with open(path, "rb") as source_file:
+ hash.update(source_file.read())
+ hash.update(f"{press}-{title}-{terminal_size}".encode("utf-8"))
+ cache_key = f"{hash.hexdigest()}.svg"
+ return cache_key
+
+ if app_path is not None:
+ screenshot_cache = Path(SCREENSHOT_CACHE)
+ screenshot_cache.mkdir(exist_ok=True)
+
+ screenshot_path = screenshot_cache / get_cache_key(app)
+ if screenshot_path.exists():
+ return screenshot_path.read_text()
+
async def auto_pilot(pilot: Pilot) -> None:
app = pilot.app
await pilot.press(*press)
@@ -85,6 +108,10 @@ def take_svg_screenshot(
auto_pilot=auto_pilot,
size=terminal_size,
)
+
+ if app_path is not None:
+ screenshot_path.write_text(svg)
+
assert svg is not None
return svg
@@ -99,11 +126,16 @@ def rich(source, language, css_class, options, md, attrs, **kwargs) -> str:
title = attrs.get("title", "Rich")
+ rows = int(attrs.get("lines", 24))
+ columns = int(attrs.get("columns", 80))
+
console = Console(
file=io.StringIO(),
record=True,
force_terminal=True,
color_system="truecolor",
+ width=columns,
+ height=rows,
)
error_console = Console(stderr=True)
diff --git a/src/textual/color.py b/src/textual/color.py
index e836452cb..a53a0abaf 100644
--- a/src/textual/color.py
+++ b/src/textual/color.py
@@ -8,7 +8,7 @@ You can convert from a Textual color to a Rich color with the [rich_color][textu
The following named colors are used by the [parse][textual.color.Color.parse] method.
-```{.rich title="colors"}
+```{.rich columns="80" title="colors"}
from textual._color_constants import COLOR_NAME_TO_RGB
from textual.color import Color
from rich.table import Table