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:
@@ -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!)
-
+
+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`.
+
+
+
+
+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**
\ No newline at end of file
diff --git a/nbs/package_reference/processors.ipynb b/nbs/package_reference/processors.ipynb
index a645ce2..2e9937a 100755
--- a/nbs/package_reference/processors.ipynb
+++ b/nbs/package_reference/processors.ipynb
@@ -36,7 +36,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "#| autodoc nbquarto.processors.autodoc.AutoDocProcessor"
+ "#| autodoc nbquarto.processors.AutoDocProcessor"
]
},
{
@@ -54,15 +54,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "#| autodoc nbquarto.processors.codenotes.CodeNoteProcessor"
- ]
- },
- {
- "attachments": {},
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Example outcome:"
+ "#| autodoc nbquarto.processors.CodeNoteProcessor"
]
},
{
@@ -70,6 +62,8 @@
"cell_type": "markdown",
"metadata": {},
"source": [
+ "Example outcome:\n",
+ "\n",
"::: {.panel-tabset}\n",
"## Code\n",
"```python\n",
@@ -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": {
diff --git a/src/nbquarto/processors/__init__.py b/src/nbquarto/processors/__init__.py
index 7e4cb46..0f3220c 100755
--- a/src/nbquarto/processors/__init__.py
+++ b/src/nbquarto/processors/__init__.py
@@ -1,2 +1,3 @@
from .autodoc import AutoDocProcessor
from .codenotes import CodeNoteProcessor
+from .semantic_versioning import SemanticVersioningProcessor
diff --git a/src/nbquarto/processors/semantic_versioning.py b/src/nbquarto/processors/semantic_versioning.py
new file mode 100644
index 0000000..7a6cd2f
--- /dev/null
+++ b/src/nbquarto/processors/semantic_versioning.py
@@ -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("")
+ }
+ // 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 = ''
+REFERENCE_JAVASCRIPT = f""
+
+
+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
diff --git a/tests/test_process.py b/tests/test_process.py
index 34a080a..d835730 100755
--- a/tests/test_process.py
+++ b/tests/test_process.py
@@ -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):
@@ -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}"
+ )