Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ENH] Add tag options to _config.yml for conditional content #1630

Open
wants to merge 4 commits into
base: master
Choose a base branch
from

Conversation

jdanke
Copy link

@jdanke jdanke commented Feb 4, 2022

Add support to specify tags in _config.yml. Requires Jupyter Book processing of the Sphinx object (app) in sphinx_build to manipulate tags, similar to how latex_documents are configured. No support for adding tags in the jupyter book command line.

This addresses issue #1290 (mistakenly refers to "open" directive). Possibly also #1425.

(comment similar to the prior PR #1618 for command line tags)

The background context is that the tags are set, added, and removed during initialization of a Sphinx object. Sphinx achieves this by executing conf.py to call the Tags.add() and Tags.remove() methods. That's why conf.py contains lines like tags.add('cowboy') and tag entries in the confoverrides dict passed to build_sphinx result in warnings when building (e.g., WARNING: unknown config value 'tags_add' in override, ignoring).

Users may add/remove tags in _config.yml like

  config                    :   # key-value pairs to directly over-ride the Sphinx configuration
    html_theme              : sphinx_book_theme
    tags_add                : cowboy
    tags_remove             : cowgirl

Changes
config.yaml_to_sphinx() parses the _config.yml and the keys tags_add and tags_remove are removed from the sphinx_config dict and returned in a separate dict. config.get_final_config() handles updating a default with this user-supplied config and also returns this new dict.

cli.main.sphinx() uses this new dict to append the tags.add() and tags.remove() lines when writing conf.py, and sphinx.build_sphinx() uses the new dict to adjust app.tags.tags :

Note that passing the new conf.py and its location confdir to Sphinx in sphinx.build_sphinx() (below) would handle adding and removing tags, but is prevented because of patch_docutils. I don't know why that is there, so it's probably not wise to tinker with it. But I think that would be an alternate entry point.

with patch_docutils(confdir), docutils_namespace():
        app = Sphinx(
            srcdir=sourcedir,
            confdir=confdir,
            outdir=outputdir,
            doctreedir=doctreedir,
            buildername=builder,
            confoverrides=sphinx_config,

After initialization, the Spinx object is reconfigured with the new dict created through parsing _config.yml

    tags_add = tags_config.get("tags_add", None)
    if tags_add:
        for tag in tags_add:
            app.tags.tags[tag] = True

    tags_remove = tags_config.get("tags_remove", None)
    if tags_remove:
        for tag in tags_remove:
            app.tags.tags.pop(tag, None)

@choldgraf
Copy link
Member

choldgraf commented Feb 11, 2022

Thanks for this PR and all of the explanation - I will try and figure out what's going on here :-) maybe @chrisjsewell also has a moment to look since he's more familiar with the guts of Sphinx's machinery than I am.

One thing that would be helpful is a user-level explanation of this feature in the docs. What are tags and why would somebody want to use them? What's the minimal use-case that this functionality is designed for? Where can a person go to learn more if they really want to dive into this feature? I think motivating the PR with a clear example would be a helpful way to understand the value that this functionality is bringing.

@jdanke
Copy link
Author

jdanke commented Feb 13, 2022

Thanks for the feedback. I'll look through the docs to see where this would fit.

Quick answer here: a typical use is to mark content that is rendered only for certain builders or audiences. For example, a textbook might have additional content in the teacher edition.

The _conf_teacher.yaml uses tags_add like below to include content that is not rendered for students, whose _conf_student.yaml lacks that line.

sphinx:
  config                    :   # key-value pairs to directly over-ride the Sphinx configuration
    html_theme              : sphinx_book_theme
    tags_add                : teacher    # this line only in _conf_teacher.yaml

Command jupyter-book build --config textbook/_conf_teacher.yaml textbook includes content with the teacher tag following the only directive.

```{only} teacher
This is the answer key!
````

@jdanke
Copy link
Author

jdanke commented Mar 7, 2022

Latest commit adds explanation. Similar to toggling and cell tags, so I added it to hiding.md even though it's nested under web and internet features.

Any advice on relocating? I considered placing into content-blocks.md because it's a directive-level block. Also considered mentioning on advanced Sphinx usage but I didn't want to over-do it.

@jmshea
Copy link
Contributor

jmshea commented Apr 14, 2023

It looks like this PR has been left to languish. @choldgraf @chrisjsewell Any chance we can get something like this, or at least get only support?

See also:
#1618
#1425

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants