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

feat: Allow addings additional options to sidebar #370

Merged
merged 7 commits into from
Nov 4, 2024

Conversation

gadenbuie
Copy link
Contributor

@gadenbuie gadenbuie commented Oct 9, 2024

Currently, (AFAICT) it's not possible to configure the sidebar generated by quartodoc.

This PR adds support using a dictionary for quartodoc.sidebar which is then passed directly to Quarto, after filling in the id and contents created by quartodoc.

quartodoc:
  package: quartodoc.tests.example
  sidebar: 
    file: _reference.yml
    style: docked
    search: true

A string quartodoc.sidebar is still allowed, and is immediately expanded to a dictionary where file is the key for the sidebar file.

quartodoc:
  sidebar: "_my-pkg.yml"

and automatically expanding to a full dictionary equivalent to

quartodoc:
  sidebar:
    file: "_my-pkg.yml"

If a dictionary not containing file is given to sidebar, we default to a file named _quartodoc-sidebar.yml. This leaves the mechanism for including a sidebar the same: the presence of a non-None value for quartodoc.sidebar indicates that a sidebar file should be written.

quartodoc:
  package: quartodoc.tests.example
  sidebar: 
    # file: _quartodoc-sidebar_.yml # implied default
    style: docked
    search: true

This allows users to choose id and customize contents. id now defaults to dir but follows the user preference, but contents allows further customization using a placeholder value to signal where to put quartodoc's contents, following these rules:

  1. If no contents, use quartodoc's contents.
  2. If contents and no sentinel value, append quartodoc's contents to the end of the contents.
  3. Place quartodoc's contents in a content item that matches {{ contents }}. This includes nested contents!

The example in the tests uses this construction. Note that we recursively look for a string in a list exactly matching "{{ contents }}".

quartodoc:
  package: quartodoc.tests.example
  sidebar:
    style: docked
    search: true
    contents:
      - text: "Introduction"
        href: introduction.qmd
      - section: "Reference"
        contents:
         - "{{ contents }}"
      - text: "Basics"
        href: basics-summary.qmd

@machow
Copy link
Owner

machow commented Oct 9, 2024

Thanks for taking the time to work on this! I'm onboard with either approach, so whatever you think is better! It seems like an advantage of having a single sidebar: config is we could address it on a single page easily (somehow it seems simpler than explaining there are two sidebar fields).

(RE quarto using a file:, seems okay to workaround if we ever come to it)

edit: I think I understand the contents piece more now and am big into it

@machow
Copy link
Owner

machow commented Oct 9, 2024

* Use `file` to specify the sidebar file
* Use "{{ contents }}" as a placeholder for quartodoc's contents anywhere in `quartodoc.sidebar.contents`.
@gadenbuie
Copy link
Contributor Author

@machow I've reworked the PR to use a dictionary for quartodoc.sidebar. I also rewrote the PR description above to give a better overview of the current state of the feature.

One place I could use your expertise in the review is making sure there aren't unwanted upstream consequences. I think I've caught everywhere that self.sidebar (previously a string or None) has become self.sidebar["file"], but it could use another look.

Comment on lines 600 to 602
if self.sidebar:
_log.info(f"Writing sidebar yaml to {self.sidebar}")
_log.info(f"Writing sidebar yaml to {self.sidebar['file']}")
self.write_sidebar(blueprint)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, I think I've convinced myself that everything is all good. Here's where we decide whether or not to write the sidebar, by which point self.sidebar is guaranteed to be a dictionary containing at least a file item (in Builder.__init__ just above in the diff).

@gadenbuie gadenbuie changed the title feat: Add sidebar_options for configuring the sidebar feat: Allow addings additional options to sidebar Oct 18, 2024
Copy link
Owner

@machow machow left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, this looks really great! I left a small nit asking whether we could pull out the splice function onto the class or as a top-level function. It took a second to get the gist of what was happening, but as a general function it seems like it'd be quick to pick up on what's happening!

if not isinstance(sidebar["contents"], list):
raise TypeError("`sidebar.contents` must be a list")

def splice_contents_recursive(sidebar, contents):
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mind pulling this into a staticmethod on the class (or a function outside the class)? It feels like if it were called _insert_contents(x: dict | list, contents: ?) or similar, the idea of a utility function putting contents where a sentinel string is is a bit easier to think about outside of the context of the sidebar.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@machow No problem! I refactored splice_contents_recursive() into a top-level _insert_contents() function, generalized the names a bit, and added a docstring.

@machow machow self-requested a review November 4, 2024 16:28
@codecov-commenter
Copy link

codecov-commenter commented Nov 4, 2024

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

Attention: Patch coverage is 89.13043% with 5 lines in your changes missing coverage. Please review.

Project coverage is 88.78%. Comparing base (8d7ade2) to head (07d4a0f).

Files with missing lines Patch % Lines
quartodoc/autosummary.py 84.84% 5 Missing ⚠️

❗ Your organization needs to install the Codecov GitHub app to enable full functionality.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #370      +/-   ##
==========================================
+ Coverage   88.72%   88.78%   +0.05%     
==========================================
  Files          37       37              
  Lines        2963     3004      +41     
==========================================
+ Hits         2629     2667      +38     
- Misses        334      337       +3     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link
Owner

@machow machow left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for making the changes -- hope it's okay, I moved some of the advanced sidebar piece into its own section on the sidebar page

Copy link
Owner

@machow machow left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for making the changes -- hope it's okay, I moved some of the advanced sidebar piece into its own section on the sidebar page

@machow machow merged commit 334bdc1 into machow:main Nov 4, 2024
5 of 6 checks passed
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.

3 participants