Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions docs/src/_templates/tags_links.need
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{# Render plain clickable text links for each tag #}
{% if tags %}
:strong:`Tags:` {{ " " }} {%- for t in tags -%}
{%- if t and t.startswith('topic_') -%}
:ref:`{{ t }} <{{ t }}>`
{%- else -%}
{{ t }}
{%- endif -%}
{%- if not loop.last %} | {% endif -%}
{%- endfor %}
{% endif %}
49 changes: 49 additions & 0 deletions docs/src/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,8 @@ def _dotv(version):
"sphinx_gallery.gen_gallery",
"matplotlib.sphinxext.mathmpl",
"matplotlib.sphinxext.plot_directive",
"sphinx_needs",
"user_manual_directives",
]

if skip_api == "1":
Expand Down Expand Up @@ -441,3 +443,50 @@ def reset_modules(gallery_conf, fname):
"section": "Section %s",
"table": "Table %s",
}

# -- sphinx-needs config ------------------------------------------------------
# See https://sphinx-needs.readthedocs.io/en/latest/configuration.html

# TODO: namespace these types as Diataxis for max clarity?
needs_types = [
{
"directive": "tutorial",
"title": "Tutorial",
"prefix": "",
"color": "",
"style": "node",
},
{
"directive": "how-to",
"title": "How To",
"prefix": "",
"color": "",
"style": "node",
},
{
"directive": "explanation",
"title": "Explanation",
"prefix": "",
"color": "",
"style": "node",
},
{
"directive": "reference",
"title": "Reference",
"prefix": "",
"color": "",
"style": "node",
},
]
# The layout whenever a 'need item' directive is used. I.e. at the top of each
# user manual page.
needs_default_layout = "focus"
# IDs must be used in needtables, as the only way to link to the item. Using
# the title makes for the most readable / least jarring links.
needs_id_from_title = True
# The `tags_links` jinja template displays a list of tags where every topic_*
# tag is a link to the relevant section in user_manual/index.rst.
needs_template_folder = "_templates"
needs_global_options = {
"post_template": {"default": "tags_links"},
}
24 changes: 0 additions & 24 deletions docs/src/further_topics/index.rst

This file was deleted.

2 changes: 1 addition & 1 deletion docs/src/further_topics/ux_guide.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
Reviewing the Iris User Experience
**********************************

.. todo:: https://github.com/SciTools/iris/issues/6511; this page belongs in 'Explanation'
.. todo:: https://github.com/SciTools/iris/issues/6867; this page belongs in 'Get Involved'

Often, improving and updating the existing user experience can fall behind fixing create new features,
or quashing pesky bugs. To combat this, we plan to have regular development discussions to ensure
Expand Down
Empty file added docs/src/get_started/index.rst
Empty file.
19 changes: 5 additions & 14 deletions docs/src/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,13 @@ For more information see :ref:`why_iris`.
plotting and more.

+++
.. button-ref:: user_guide_index
.. button-ref:: user_manual_index
:ref-type: ref
:color: primary
:outline:
:expand:

User Guide
User Manual

.. grid-item-card::
:text-align: center
Expand Down Expand Up @@ -159,12 +159,12 @@ The legacy support resources:


.. toctree::
:caption: User Guide
:caption: User Manual
:maxdepth: 1
:name: userguide_index
:name: user_manual
:hidden:

userguide/index
user_manual/index


.. toctree::
Expand All @@ -176,15 +176,6 @@ The legacy support resources:
developers_guide/contributing_getting_involved


.. toctree::
:caption: Community
:maxdepth: 1
:name: community_index
:hidden:

Community <community/index>


.. toctree::
:caption: What's New in Iris
:maxdepth: 1
Expand Down
141 changes: 141 additions & 0 deletions docs/src/sphinxext/user_manual_directives.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
# TODO: header
# TODO: docstrings/comments. How to document an extension/directive?
# TODO: linting

# TODO: include a validation routine, calling to sphinx-needs to confirm that
# all User Manual pages have the minimum metadata.
# - sphinx-need directive
# - :tags: including a topic_xxx tag
# - think sphinx-needs will already insist on a valid type?
# - think sphinx-needs will already insist on a title?
# - think sphinx-needs will already insist on a description?
# - as it stands this would exclude all section indexes, unless the section
# indexes get their own Diataxis tab.

from pathlib import Path
import enum
import re

from docutils import nodes # type: ignore[import-untyped]
from docutils.parsers.rst import Directive # type: ignore[import-untyped]
from docutils.statemachine import StringList # type: ignore[import-untyped]


class Diataxis(enum.StrEnum):
# TODO: should user manual section indexes also get their own Diataxis tab?
# This would allow topic-based filtering, and allow all pages to be found
# through the same route.

ALL = "all"
TUTORIAL = "tutorial"
HOW_TO = "how-to"
REFERENCE = "reference"
EXPLANATION = "explanation"


DIATAXIS_CAPTIONS = {
Diataxis.TUTORIAL: "Guided lessons for understanding a topic. (Supports **study**, via **action**)",
Diataxis.HOW_TO: "Step by step instructions for achieving a specific goal. (Supports **work**, via **action**)",
Diataxis.EXPLANATION: "In-depth discussion for understanding concepts. (Supports **study**, via **theory**)",
Diataxis.REFERENCE: "Concise information to look up when needed. (Supports **work**, via **theory**)",
}


class DiataxisDirective(Directive):
has_content = True

@staticmethod
def _indent(text: str) -> str:
indented = [" " + line for line in text.splitlines()]
return "\n".join(indented)

def _needtable(self, types: Diataxis, tags: str) -> str:
options = [
':columns: id as "Link";title;content as " "',
":colwidths: 10;30;60",
":style: table",
":filter_warning: No pages for this filter.",
]
# TODO: should the table somehow include what section the page belongs
# to? This isn't standard sphinx-needs metadata so would need
# `needs_extra_options` in conf.py.
if types is not Diataxis.ALL:
options.append(f":types: {types}")
# TODO: is looking for `topic_all` brittle hard-coding?
if tags != "topic_all":
options.append(f":tags: {tags}")
options_str = "\n".join(options)
needtable = "\n".join([
".. needtable::",
self._indent(options_str),
])
return needtable

def _tab_item(self, diataxis: Diataxis, tags: str) -> str:
needtable = self._needtable(types=diataxis, tags=tags)
tab_item_title = diataxis.capitalize()
# TODO: should there be a caption for ALL as well? Even if that's just
# for visual consistency.
caption = DIATAXIS_CAPTIONS.get(diataxis, "")
if diataxis is not Diataxis.ALL:
tab_item_title += "s"
content = [
f":sync: {diataxis}",
"",
caption,
"",
needtable,
]
content_str = "\n".join(content)
tab_item = "\n".join([
f".. tab-item:: {tab_item_title}",
self._indent(content_str),
])
return tab_item

def run(self):
rst_path = Path(self.state.document['source'])
# user_manual.index.rst
if not (rst_path.parent.name == "user_manual" and rst_path.name == "index.rst"):
message = "Expected directive to only be used in user_manual/index.rst"
error = self.state_machine.reporter.error(
message, line=self.lineno
)
return [error]
label_pattern = re.compile(r"^\.\. _(topic_.+):$", re.MULTILINE)
topic_labels = label_pattern.findall(rst_path.read_text())
badges = {
label: "bdg-ref-primary" if label == self.content[0] else "bdg-ref-primary-line"
for label in topic_labels
}
# Parse the badges as RST.
node = nodes.Element()
self.state.nested_parse(
StringList([f":{badge}:`{label}`" for label, badge in badges.items()]),
self.content_offset,
node
)

tab_items = [
self._tab_item(diataxis=diataxis, tags=self.content[0])
for diataxis in Diataxis
]
tab_items_str = "\n\n".join(tab_items)
tab_set = "\n".join([
".. tab-set::",
"",
self._indent(tab_items_str),
])
# Parse the tab set as RST.
self.state.nested_parse(
StringList(tab_set.splitlines()),
self.content_offset,
node
)

return node.children


def setup(app):
app.add_directive("diataxis-page-list", DiataxisDirective)
return {"version": "0.1"}
83 changes: 83 additions & 0 deletions docs/src/user_manual/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
.. comment:
now that User Manual is the official top-level, and the User Guide is a
sub-section, the original labels have been relocated here.

.. _user_guide_index:
.. _user_guide_introduction:
.. _user_manual_index:

User Manual
===========

Welcome to the Iris User Manual!

We encourage exploring our User Manual pages using the tabbed sections below,
which combine the `Diataxis`_ framework and topic-based filters to find content
best suited to your purpose today. Alternatively, you can use the sidebar to
navigate by section.

.. todo:
Should the sections also be offered as another Diataxis tab? This would allow
topic-based filtering, and allow all pages to be found through the same
route.

.. comment:
The tree structure for user_manual is specified here. As mentioned in the
text, we prefer readers to use the tabbed sections below, so the toctree is
hidden - not rendered in the text, only in the sidebar. This toctree is
expected to be exclusively section_indexes/* pages; with those pages
providing the remaining sub-structure.


.. toctree::
:maxdepth: 1
:hidden:

section_indexes/userguide
section_indexes/dask_best_practices
section_indexes/mesh_support
section_indexes/metadata_arithmetic
section_indexes/community
section_indexes/general

.. _topic_all:

All
---

.. diataxis-page-list:: topic_all

By Topic
--------

.. _topic_data_model:

topic: ``data_model``
^^^^^^^^^^^^^^^^^^^^^

Pages about the :class:`~iris.cube.Cube` class and its associated components
such as :class:`~iris.coords.Coord` and :class:`~iris.mesh.Mesh`.

.. diataxis-page-list:: topic_data_model

.. _topic_load_save:

topic: ``load_save``
^^^^^^^^^^^^^^^^^^^^

Pages about reading from files into the data model, and writing from the data
model to files.

.. diataxis-page-list:: topic_load_save

.. _topic_lazy_data:

topic: ``lazy_data``
^^^^^^^^^^^^^^^^^^^^

Pages about Iris' implementation of parallel and out-of-core data handling, via
Dask. See :term:`Lazy Data`.

.. diataxis-page-list:: topic_lazy_data

.. _Diataxis: https://diataxis.fr/
Loading
Loading