diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index b1d514cc8..74f276b08 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -137,6 +137,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 + - uses: nikeee/setup-pandoc@v1 - name: Setup Python uses: actions/setup-python@v4 with: diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 1b5e3aa41..cf0f3e0f2 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -38,3 +38,8 @@ repos: rev: v1.1.1 hooks: - id: doc8 + + - repo: "https://github.com/kynan/nbstripout" + rev: "0.5.0" + hooks: + - id: nbstripout diff --git a/docs/community/setup.md b/docs/community/setup.md index 6b0747666..309e53ece 100644 --- a/docs/community/setup.md +++ b/docs/community/setup.md @@ -42,6 +42,7 @@ To simplify this process, we use a few helper tools: - [The Sphinx Theme Builder](https://sphinx-theme-builder.readthedocs.io/en/latest/) compiles web assets in an automated way. - [pre-commit](https://pre-commit.com/) for automatically enforcing code standards and quality checks before commits. - [nox](https://nox.thea.codes/) for automating common development tasks. +- [pandoc](https://pandoc.org/) the universal document converter. In particular, `nox` can be used to automatically create isolated local development environments with all the correct packages installed to work on the theme. The rest of this guide focuses on using `nox` to start with a basic environment. diff --git a/docs/community/topics/manual-dev.md b/docs/community/topics/manual-dev.md index 35964d5cc..2b05d5888 100644 --- a/docs/community/topics/manual-dev.md +++ b/docs/community/topics/manual-dev.md @@ -12,22 +12,26 @@ This is optional, but it's best to start with a fresh development environment so To do so, use a tool like [conda](https://docs.conda.io/en/latest/), [mamba](https://github.com/mamba-org/mamba), or [virtualenv](https://virtualenv.pypa.io/). -## Clone the repository locally +## Install dependencies -First clone this repository from the `pydata` organization, or from a fork that you have created: +You must install `sphinx-theme-builder` and Pandoc. + +We use the `sphinx-theme-builder` to install `nodejs` locally and to compile all CSS and JS assets needed for the theme. +Install it like so (note the `cli` option so that we can run it from the command line): ```console -$ git clone https://github.com/pydata/pydata-sphinx-theme -$ cd pydata-sphinx-theme +$ pip install "sphinx-theme-builder[cli]" ``` -## Install the `sphinx-theme-builder` +We use `nbsphinx` to support notebook (.ipynb) files in the documentation, which requires [installing Pandoc](https://pandoc.org/installing.html) at a system level (or within a Conda environment). -We use the `sphinx-theme-builder` to install `nodejs` locally and to compile all CSS and JS assets needed for the theme. -Install it like so (note the `cli` option so that we can run it from the command line): +## Clone the repository locally + +First clone this repository from the `pydata` organization, or from a fork that you have created: ```console -$ pip install sphinx-theme-builder[cli] +$ git clone https://github.com/pydata/pydata-sphinx-theme +$ cd pydata-sphinx-theme ``` ## Install this theme locally @@ -35,7 +39,7 @@ $ pip install sphinx-theme-builder[cli] Next, install this theme locally so that we have the necessary dependencies to build the documentation and testing suite: ```console -$ pip install -e .[dev] +$ pip install -e ".[dev]" ``` Note that the `sphinx-theme-builder` will automatically install a local copy of `nodejs` for building the theme's assets. diff --git a/docs/conf.py b/docs/conf.py index 77bedc9a2..b42beef44 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -34,18 +34,18 @@ "sphinx_design", "sphinx_copybutton", "autoapi.extension", - "_extension.gallery_directive", # For extension examples and demos + "myst_parser", "ablog", "jupyter_sphinx", - "matplotlib.sphinxext.plot_directive", - "myst_nb", "sphinxcontrib.youtube", - # "nbsphinx", # Uncomment and comment-out MyST-NB for local testing purposes. + "nbsphinx", "numpydoc", "sphinx_togglebutton", "jupyterlite_sphinx", "sphinx_favicon", + # custom extentions + "_extension.gallery_directive", ] # Add any paths that contain templates here, relative to this directory. @@ -66,11 +66,6 @@ sitemap_locales = [None] sitemap_url_scheme = "{link}" -# -- Internationalization ---------------------------------------------------- - -# specifying the natural language populates some key tags -language = "en" - # -- MyST options ------------------------------------------------------------ # This allows us to use ::: to denote directives, useful for admonitions @@ -78,6 +73,11 @@ myst_heading_anchors = 2 myst_substitutions = {"rtd": "[Read the Docs](https://readthedocs.org/)"} +# -- Internationalization ---------------------------------------------------- + +# specifying the natural language populates some key tags +language = "en" + # -- Ablog options ----------------------------------------------------------- blog_path = "examples/blog/index" diff --git a/docs/examples/pydata.ipynb b/docs/examples/pydata.ipynb new file mode 100644 index 000000000..34a8da267 --- /dev/null +++ b/docs/examples/pydata.ipynb @@ -0,0 +1,170 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# PyData Library Styles\n", + "\n", + "This theme has built-in support and special styling for several major visualization libraries in the PyData ecosystem.\n", + "This ensures that the images and output generated by these libraries looks good for both light and dark modes.\n", + "Below are examples of each that we use as a benchmark for reference.\n", + "\n", + "## Pandas" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import string\n", + "\n", + "import numpy as np\n", + "import pandas as pd\n", + "\n", + "rng = np.random.default_rng()\n", + "data = rng.standard_normal((100, 26))\n", + "df = pd.DataFrame(data, columns=list(string.ascii_lowercase))\n", + "df" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Matplotlib" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "nbsphinx": "hidden" + }, + "outputs": [], + "source": [ + "import matplotlib\n", + "\n", + "# avoid warnings upon doc build\n", + "matplotlib.set_loglevel(\"critical\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import matplotlib.pyplot as plt\n", + "\n", + "fig, ax = plt.subplots()\n", + "ax.scatter(df[\"a\"], df[\"b\"], c=df[\"b\"], s=3)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "\n", + "matplotlib.set_loglevel(\"critical\")\n", + "\n", + "rng = np.random.default_rng()\n", + "data = rng.standard_normal((3, 100))\n", + "fig, ax = plt.subplots()\n", + "ax.scatter(data[0], data[1], c=data[2], s=3)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Plotly\n", + "\n", + "The HTML below shouldn't display, but it uses RequireJS to make sure that all\n", + "works as expected. If the widgets don't show up, RequireJS may be broken." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import plotly.io as pio\n", + "import plotly.express as px\n", + "import plotly.offline as py\n", + "\n", + "pio.renderers.default = \"notebook\"\n", + "\n", + "df = px.data.iris()\n", + "fig = px.scatter(df, x=\"sepal_width\", y=\"sepal_length\", color=\"species\", size=\"sepal_length\")\n", + "fig" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Xarray\n", + "\n", + "Here we demonstrate `xarray` to ensure that it shows up properly." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import xarray as xr\n", + "data = xr.DataArray(\n", + " np.random.randn(2, 3),\n", + " dims=(\"x\", \"y\"),\n", + " coords={\"x\": [10, 20]}, attrs={\"foo\": \"bar\"}\n", + " )\n", + "data" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## ipyleaflet\n", + "\n", + "`ipyleaflet` is a **Jupyter**/**Leaflet** bridge enabling interactive maps in the Jupyter notebook environment. this demonstrate how you can integrate maps in your documentation." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from ipyleaflet import Map, basemaps\n", + "\n", + "# display a map centered on France\n", + "m = Map(basemap=basemaps.Esri.WorldImagery, zoom=5, center=[46.21, 2.21])\n", + "m" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "name": "python", + "version": "3.10.8" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/docs/examples/pydata.md b/docs/examples/pydata.md deleted file mode 100644 index e31a90905..000000000 --- a/docs/examples/pydata.md +++ /dev/null @@ -1,102 +0,0 @@ ---- -file_format: mystnb -kernelspec: - name: python3 - display_name: Python 3 ---- - -% To test this file with nbsphinx we need to convert to ipynb. To do this: -% - Run this command: jupytext docs/examples/pydata.md --to ipynb -% - _Temporarily_ delete the pydata.md file -% - Uncomment `nbsphinx` and comment `myst_nb` in "extensions" in our conf.py file -% - Build the docs and test that the results look OK -% - Undo everything in this list to make sure we revert back to the old structure - -# PyData Library Styles - -This theme has built-in support and special styling for several major visualization libraries in the PyData ecosystem. -This ensures that the images and output generated by these libraries looks good for both light and dark modes. -Below are examples of each that we use as a benchmark for reference. - -## Pandas - -```{code-cell} -import string - -import numpy as np -import pandas as pd - -rng = np.random.default_rng() -data = rng.standard_normal((100, 26)) -df = pd.DataFrame(data, columns=list(string.ascii_lowercase)) -df -``` - -## Matplotlib - -```{sidebar} -Here's a sidebar to test that the code cells behave as we'd expect when there is content to the right. The code cell should be displayed to the left and with no overlap. -``` - -```{code-cell} -import matplotlib.pyplot as plt - -fig, ax = plt.subplots() -ax.scatter(df["a"], df["b"], c=df["b"], s=3) -``` - -and with the Matplotlib `plot` directive: - -```{eval-rst} -.. plot:: - - import matplotlib.pyplot as plt - import numpy as np - rng = np.random.default_rng() - data = rng.standard_normal((3, 100)) - fig, ax = plt.subplots() - ax.scatter(data[0], data[1], c=data[2], s=3) -``` - -## Plotly - -The HTML below shouldn't display, but it uses RequireJS to make sure that all -works as expected. If the widgets don't show up, RequireJS may be broken. - -```{code-cell} -import plotly.io as pio -import plotly.express as px -import plotly.offline as py - -pio.renderers.default = "notebook" - -df = px.data.iris() -fig = px.scatter(df, x="sepal_width", y="sepal_length", color="species", size="sepal_length") -fig -``` - -## Xarray - -Here we demonstrate `xarray` to ensure that it shows up properly. - -```{code-cell} -import xarray as xr -data = xr.DataArray( - np.random.randn(2, 3), - dims=("x", "y"), - coords={"x": [10, 20]}, attrs={"foo": "bar"} - ) -data -``` - -## ipyleaflet - -`ipyleaflet` is a **Jupyter**/**Leaflet** bridge enabling interactive maps in the Jupyter notebook environment. this demonstrate how you can integrate maps in your documentation. - -```{code-cell} -from ipyleaflet import Map, basemaps - -# display a map centered on France -m = Map(basemap=basemaps.Esri.WorldImagery, zoom=5, center=[46.21, 2.21]) -m -``` diff --git a/docs/user_guide/theme-elements.md b/docs/user_guide/theme-elements.md index 919be251d..06e905224 100644 --- a/docs/user_guide/theme-elements.md +++ b/docs/user_guide/theme-elements.md @@ -161,7 +161,7 @@ In Python you can {python}`import sphinx`. ## Code execution This theme has support for Jupyter execution libraries so that you can programmatically update your documentation with each build. -For examples, see [](../examples/pydata.md). +For examples, see [](../examples/pydata.ipynb). ## Admonition sidebars diff --git a/pyproject.toml b/pyproject.toml index 05f162a50..26e04a2f2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -49,13 +49,13 @@ classifiers = [ [project.optional-dependencies] doc = [ "numpydoc", - "myst-nb", "linkify-it-py", # for link shortening "rich", "sphinxext-rediraffe", "sphinx-sitemap", "sphinx-autoapi", # For examples section + "myst-parser", "ablog>=0.11.0rc2", "jupyter_sphinx", "pandas", @@ -69,8 +69,7 @@ doc = [ "jupyterlite-sphinx", "sphinxcontrib-youtube<1.4", "sphinx-favicon>=1.0.1", - # Install nbsphinx in case we want to test it locally even though we can't load - # it at the same time as MyST-NB. + "ipykernel", "nbsphinx", "ipyleaflet", "colorama", diff --git a/readthedocs.yml b/readthedocs.yml index f70c87ecb..72526f538 100644 --- a/readthedocs.yml +++ b/readthedocs.yml @@ -6,7 +6,7 @@ formats: build: os: ubuntu-20.04 tools: - python: "3.9" + python: "3.10" jobs: # build the gallery of themes before building the doc post_install: diff --git a/src/pydata_sphinx_theme/assets/styles/content/_tables.scss b/src/pydata_sphinx_theme/assets/styles/content/_tables.scss index 480b653e3..15f37a3b6 100644 --- a/src/pydata_sphinx_theme/assets/styles/content/_tables.scss +++ b/src/pydata_sphinx_theme/assets/styles/content/_tables.scss @@ -5,8 +5,6 @@ // ensure table will fit in the article width and make them y-scrollable table { display: table; - width: fit-content; - max-width: 100%; overflow: auto; // default to table-center