Skip to content

Commit

Permalink
Enable semantic versioned sidebar (#6)
Browse files Browse the repository at this point in the history
  • Loading branch information
muellerzr authored Jun 9, 2023
1 parent 6f62e6c commit 8641b6d
Show file tree
Hide file tree
Showing 7 changed files with 220 additions and 29 deletions.
6 changes: 1 addition & 5 deletions docs/_quarto.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,7 @@ project:
website:
sidebar:
search: true
contents:
- index.qmd
- getting_started.qmd
- section: "Package Reference"
contents: package_reference/*
contents: auto
margin-header: |
![](/logo.png)
favicon: /logo.png
Expand Down
5 changes: 2 additions & 3 deletions docs/package_reference/processor.qmd
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ Processes notebook cells and comments in a notebook

</div><div style="background:#f7f7f7; border:2px solid #5a5a5a; border-top-width:2px; border-left-width: 2px; border-top-left-radius: 0.75rem; margin-top: 2rem; margin-bottom: 1.5rem; padding-left: 1rem; padding-right: .5rem;">
#### `process_cell` {#nbquarto.processor.NotebookProcessor.process_cell}
[\<source\>](https://github.com/muellerzr/nbquarto/blob/main/src/nbquarto/processor.py#L154){style="float:right;font-size:.875rem;"}
[\<source\>](https://github.com/muellerzr/nbquarto/blob/main/src/nbquarto/processor.py#L155){style="float:right;font-size:.875rem;"}
<p style="font-size:.875rem;line-height:1.25rem;">
(**`processor`**`: callable`, **`cell`**`: AttributeDictionary`)
</p>
Expand All @@ -151,7 +151,7 @@ explicitly and instead a user should use `process_notebook`
</div></div>
<div style="background:#f7f7f7; border:2px solid #5a5a5a; border-top-width:2px; border-left-width: 2px; border-top-left-radius: 0.75rem; margin-top: 2rem; margin-bottom: 1.5rem; padding-left: 1rem; padding-right: .5rem;">
#### `process_notebook` {#nbquarto.processor.NotebookProcessor.process_notebook}
[\<source\>](https://github.com/muellerzr/nbquarto/blob/main/src/nbquarto/processor.py#L172){style="float:right;font-size:.875rem;"}
[\<source\>](https://github.com/muellerzr/nbquarto/blob/main/src/nbquarto/processor.py#L173){style="float:right;font-size:.875rem;"}
<p style="font-size:.875rem;line-height:1.25rem;">
()
</p>
Expand All @@ -164,4 +164,3 @@ Processes the content of the notebook

</div>


49 changes: 41 additions & 8 deletions docs/package_reference/processors.qmd
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ Example usage:

```python
#| process
def my_function():
def my_function():
return "Hello world!"
```

Expand All @@ -36,10 +36,9 @@ Example outcome:
def my_function():
return "Hello world!"
```

<div style="background:#f7f7f7; border:2px solid #5a5a5a; border-top-width:2px; border-left-width: 2px; border-top-left-radius: 0.75rem; margin-top: 2rem; margin-bottom: 1.5rem; padding-left: 1rem; padding-right: .5rem;">

### `class AutoDocProcessor` {#nbquarto.processors.autodoc.AutoDocProcessor}
### `class AutoDocProcessor` {#nbquarto.processors.AutoDocProcessor}
[\<source\>](https://github.com/muellerzr/nbquarto/blob/main/src/nbquarto/processors/autodoc.py#L250){style="float:right;font-size:.875rem;"}
<p style="font-size:.875rem;line-height:1.25rem;">
(**`notebook`**, **`processor_args`**`: dict = {}`)
Expand All @@ -48,7 +47,7 @@ def my_function():
<div style="font-size:.875rem;line-height:1.25rem;margin-bottom:1.25em; margin-top:1.25em; padding_bottom:0;">

A processor which will automatically generate API documentation for a given class or method.
Largely relies on the implementation in [hf-doc-builder](https://github.comn/huggingface/doc-builder),
Largely relies on the implementation in [hf-doc-builder](https://github.com/huggingface/doc-builder),
while adding some customizations for Quarto.

This processor expects the following directives:
Expand Down Expand Up @@ -86,10 +85,9 @@ To expose all public methods and include special or hidden methods:
Example outcome:

(See the auto-generated docs that made this!)

<div style="background:#f7f7f7; border:2px solid #5a5a5a; border-top-width:2px; border-left-width: 2px; border-top-left-radius: 0.75rem; margin-top: 2rem; margin-bottom: 1.5rem; padding-left: 1rem; padding-right: .5rem;">

### `class CodeNoteProcessor` {#nbquarto.processors.codenotes.CodeNoteProcessor}
### `class CodeNoteProcessor` {#nbquarto.processors.CodeNoteProcessor}
[\<source\>](https://github.com/muellerzr/nbquarto/blob/main/src/nbquarto/processors/codenotes.py#L124){style="float:right;font-size:.875rem;"}
<p style="font-size:.875rem;line-height:1.25rem;">
(**`notebook`**`: AttributeDictionary`)
Expand Down Expand Up @@ -139,8 +137,43 @@ def addition(a,b):
```{.python}
addition(a,b)
```
:::{style='padding-top: 0px;'}
::::{style='padding-top: 0px;'}
This function adds two numbers together
::::
:::
:::

<div style="background:#f7f7f7; border:2px solid #5a5a5a; border-top-width:2px; border-left-width: 2px; border-top-left-radius: 0.75rem; margin-top: 2rem; margin-bottom: 1.5rem; padding-left: 1rem; padding-right: .5rem;">

### `class SemanticVersioningProcessor` {#nbquarto.processors.SemanticVersioningProcessor}
[\<source\>](https://github.com/muellerzr/nbquarto/blob/main/src/nbquarto/processors/semantic_versioning.py#L65){style="float:right;font-size:.875rem;"}
<p style="font-size:.875rem;line-height:1.25rem;">
(**`notebook`**`: AttributeDictionary`)
</p>

<div style="font-size:.875rem;line-height:1.25rem;margin-bottom:1.25em; margin-top:1.25em; padding_bottom:0;">

A processor which will inject javascript into the top of the `qmd` or
notebook to enable semantic versioning of the documentation.

Assumes your documentation structure is as follows:

```
- docs/
- version_1
- page_1.qmd
- page_2.qmd
- version_2
- page_1.qmd
- page_2.qmd
```

From here, the sidebar will be populated based on the
current opened page and its semantic version. So if
you are on `/docs/version_1/page_1`, the sidebar will
hide all of `version_2`'s pages (and any others there may be),
and only show `version_1`.

</div>
</div>

This processor also requires that your project is configured in a particular way. To read more be sure to check out the usage guide. **TO BE COMPLETED**
34 changes: 22 additions & 12 deletions nbs/package_reference/processors.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"#| autodoc nbquarto.processors.autodoc.AutoDocProcessor"
"#| autodoc nbquarto.processors.AutoDocProcessor"
]
},
{
Expand All @@ -54,22 +54,16 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"#| autodoc nbquarto.processors.codenotes.CodeNoteProcessor"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"Example outcome:"
"#| autodoc nbquarto.processors.CodeNoteProcessor"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"Example outcome:\n",
"\n",
"::: {.panel-tabset}\n",
"## Code\n",
"```python\n",
Expand All @@ -85,11 +79,27 @@
"```{.python}\n",
"addition(a,b)\n",
"```\n",
":::{style='padding-top: 0px;'}\n",
"::::{style='padding-top: 0px;'}\n",
"This function adds two numbers together\n",
":::\n",
"::::\n",
":::\n"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"#| autodoc nbquarto.processors.SemanticVersioningProcessor"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"This processor also requires that your project is configured in a particular way. To read more be sure to check out the usage guide. **TO BE COMPLETED**"
]
}
],
"metadata": {
Expand Down
1 change: 1 addition & 0 deletions src/nbquarto/processors/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
from .autodoc import AutoDocProcessor
from .codenotes import CodeNoteProcessor
from .semantic_versioning import SemanticVersioningProcessor
109 changes: 109 additions & 0 deletions src/nbquarto/processors/semantic_versioning.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
# Copyright 2023 Zachary Mueller. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import logging

from ..notebook import make_cell
from ..processor import Processor


logger = logging.getLogger(__name__)

# This is the javascript that will be injected into the top of the notebook
# to enable semantic versioning of the documentation

REFERENCE_JAVASCRIPT = """/**
* Enables semantic versioning through careful sidebar menu item selection.
* Hide sidebar menu items that are not related to the current page that is open.
* Assumes a directory structure of:
* - version_1
* - page_1
* - page_2
* - version_2
* - page_2
* - page_3
*
* If version_1 is open, then version_2 and it's pages will not be visible to the sidebar.
* These will also link to {url}/{version_num}/page_{num}.
*
* In the `_quarto.yml` sidebar *must* be set to `auto` for this to work.
*/
var all_versioned_menus = $(".sidebar-menu-container > .list-unstyled").children()
// Get the current url, which should be something like: /branch_name/{version_number}/{something}
// the latter parts after the version number are not important nor will be in there.
// eventually need to handle a special case when we use the latest stable version
var url = window.location.pathname.split("/")[1]
for (var versioned_menu of all_versioned_menus){
// Check if the current url extension is in the sidebar menu
var active_sidebar = $(versioned_menu).find(`a[href*="${url}"]`)[0]
// If it is, wrap it in a div so it's easily recognizeable
if (active_sidebar !== undefined){
$(active_sidebar).parent().parent().wrap("<div id='active-sidebar'></div>")
}
// Else hide the additional menus
else {
versioned_menu.style.display = "none"
}
}"""

# We inject it directly to the markdown so there doesn't have to be other random files we need to worry about
REFERENCE_JQUERY = '<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.3/jquery.min.js"></script>'
REFERENCE_JAVASCRIPT = f"<script>{REFERENCE_JAVASCRIPT}</script>"


class SemanticVersioningProcessor(Processor):
"""
A processor which will inject javascript into the top of the `qmd` or
notebook to enable semantic versioning of the documentation.
Assumes your documentation structure is as follows:
```
- docs/
- version_1
- page_1.qmd
- page_2.qmd
- version_2
- page_1.qmd
- page_2.qmd
```
From here, the sidebar will be populated based on the
current opened page and its semantic version. So if
you are on `/docs/version_1/page_1`, the sidebar will
hide all of `version_2`'s pages (and any others there may be),
and only show `version_1`.
"""

cell_types = "markdown"
found_markdown_cell = False
markdown_cell_index = None

def process(self, cell):
if self.is_first_markdown(cell):
# Create the new markdown cell
new_cell = make_cell("\n".join([REFERENCE_JQUERY, REFERENCE_JAVASCRIPT]), "markdown")
# Insert the new cell just after the first markdown cell
self.notebook.cells.insert(self.markdown_cell_index + 1, new_cell)
# Update the notebook order
for i, cell in enumerate(self.notebook.cells):
cell.index_ = i

def is_first_markdown(self, cell):
if not self.found_markdown_cell:
self.found_markdown_cell = True
self.markdown_cell_index = cell["index_"]
return True
else:
return False
45 changes: 44 additions & 1 deletion tests/test_process.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

from nbquarto.notebook import make_cell, new_notebook
from nbquarto.processor import NotebookProcessor, Processor
from nbquarto.processors import AutoDocProcessor, CodeNoteProcessor
from nbquarto.processors import AutoDocProcessor, CodeNoteProcessor, SemanticVersioningProcessor
from nbquarto.processors.semantic_versioning import REFERENCE_JAVASCRIPT, REFERENCE_JQUERY


class BasicProcessor(Processor):
Expand Down Expand Up @@ -117,3 +118,45 @@ def test_codenotes(self):
self.assertTrue(
"Applies the processor to a cell if the cell is of the" in self.notebook_processor.notebook.cells[2].source
)


class TestSemanticVersioning(unittest.TestCase):
processor = SemanticVersioningProcessor

def reset_cells(self):
test_cells = [
make_cell("# Test Notebook", "markdown"),
make_cell("Here's some text!", "markdown"),
]
self.test_notebooks = [
new_notebook(cells=test_cells),
new_notebook(cells=[make_cell("print('Some code!')")] + test_cells),
]

def setUp(self):
self.reset_cells()

def test_base_case(self):
"Checks if we can insert directly to the first cell"
self.notebook_processor = NotebookProcessor(
processors=[self.processor],
notebook=self.test_notebooks[0],
)
self.notebook_processor.process_notebook()
self.assertEqual(self.notebook_processor.notebook.cells[0].source, "# Test Notebook")
self.assertEqual(
self.notebook_processor.notebook.cells[1].source, f"{REFERENCE_JQUERY}\n{REFERENCE_JAVASCRIPT}"
)

def test_around_code_cell(self):
"Checks that it can be inserted under a markdown cell after a code cell in the very start"
self.notebook_processor = NotebookProcessor(
processors=[self.processor],
notebook=self.test_notebooks[1],
)
self.notebook_processor.process_notebook()
self.assertEqual(self.notebook_processor.notebook.cells[0].source, "print('Some code!')")
self.assertEqual(self.notebook_processor.notebook.cells[1].source, "# Test Notebook")
self.assertEqual(
self.notebook_processor.notebook.cells[2].source, f"{REFERENCE_JQUERY}\n{REFERENCE_JAVASCRIPT}"
)

0 comments on commit 8641b6d

Please sign in to comment.