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