Skip to content
Open
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
6 changes: 6 additions & 0 deletions docs/options.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ plugins:
add_to_navigation: false
print_page_title: 'Print Site'
print_page_basename: 'print_page'
print_by_section: false
add_print_site_banner: false
# Table of contents
add_table_of_contents: true
Expand All @@ -34,6 +35,11 @@ plugins:
`print_page_basename`
: Default is `'print_page'`. Can be used to cutomized the path to the print page in the URL.

`print_by_section`
: Default is `false`. Used to generate a print page per level one section. The section print page will be generated at the root level of the site, with the `print_page_basename` followed by an `_` and the section title cleansed from all special characters and punctuation.

For example, a section named "Bob's list" will be availlable as `print_page_bobslist/`

`add_table_of_contents`
: Default is `true`. Adds a table of contents section at the beginning of the print page (in print version, the HTML version has a different sidebar ToC).

Expand Down
65 changes: 58 additions & 7 deletions src/mkdocs_print_site_plugin/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
from mkdocs_print_site_plugin.renderer import Renderer
from mkdocs_print_site_plugin.urls import is_external
from mkdocs_print_site_plugin.utils import get_theme_name
from mkdocs_print_site_plugin.utils import generate_link_from

logger = logging.getLogger("mkdocs.plugins")

Expand Down Expand Up @@ -46,6 +47,7 @@ class PrintSitePlugin(BasePlugin):
("include_css", config_options.Type(bool, default=True)),
("enabled", config_options.Type(bool, default=True)),
("exclude", config_options.Type(list, default=[])),
("print_by_section", config_options.Type(bool, default=False)),
)

def on_config(self, config, **kwargs):
Expand Down Expand Up @@ -186,12 +188,34 @@ def on_nav(self, nav, config, files, **kwargs):

# Save the (order of) pages and sections in the navigation before adding the print page
self.renderer.items = nav.items
self.section_print_pages = []

# Optionally add the print page to the site navigation
if self.config.get("add_to_navigation"):
nav.items.append(self.print_page)
nav.pages.append(self.print_page)

if self.config.get("print_by_section"):
for item in nav.items:
if hasattr(item, "children") and item.children:
# This is a section
section_print_file = File(
path=f"{self.config.get('print_page_basename')}_{generate_link_from(item.title)}.md",
src_dir="",
dest_dir=config["site_dir"],
use_directory_urls=config.get("use_directory_urls"),
)
section_print_page = Page(
title=f"{self.config.get('print_page_title')} - {item.title}",
file=section_print_file,
config=config,
)
section_print_page.edit_url = None

# Add section print page to the navigation
nav.pages.append(section_print_page)
self.section_print_pages.append(section_print_page)

return nav

def on_page_content(self, html, page, config, files, **kwargs):
Expand Down Expand Up @@ -303,15 +327,42 @@ def on_post_build(self, config, **kwargs):
if css_file in os.listdir(os.path.join(HERE, "css")):
css_file_path = os.path.join(css_output_base_path, css_file)
copy_file(os.path.join(os.path.join(HERE, "css"), css_file), css_file_path)


self._render_print_page(self.print_page, self.renderer, config)

if self.config.get("print_by_section"):
for section_page in self.section_print_pages:
#self.js_loaded_for_section = False
# Find the corresponding section item from nav
section_title = section_page.title.split(" - ")[-1]
section_item = None
for item in self.renderer.items: # self.renderer.items has all nav items
if hasattr(item, "title") and item.title == section_title:
section_item = item
break

if section_item:
section_renderer = Renderer(
plugin_config=self.config,
mkdocs_config=config,
cover_page_template_path=self.cover_page_template_path,
banner_template_path=self.banner_template_path,
print_page=section_page,
)
section_renderer.items = [section_item]
self._render_print_page(section_page, section_renderer, config)

def _render_print_page(self, page, renderer, config):
"""
Renders a given page to a print page.
"""
# Combine the HTML of all pages present in the navigation
self.print_page.content, self.print_page.toc = self.renderer.write_combined()

page.content, page.toc = renderer.write_combined()
# Get the info for MkDocs to be able to apply a theme template on our print page
env = config["theme"].get_env()
# env.list_templates()
template = env.get_template("main.html")
self.context["page"] = self.print_page
self.context["page"] = page
# Render the theme template for the print page
html = template.render(self.context)

Expand All @@ -323,15 +374,15 @@ def on_post_build(self, config, **kwargs):
# As this plugin adds some javascript to every page
# It should be included in the print site also
if config.get("plugins", {}).get("charts"):
html = config.get("plugins", {}).get("charts").add_javascript_variables(html, self.print_page, config)
html = config.get("plugins", {}).get("charts").add_javascript_variables(html, page, config)

# Compatibility with mkdocs-drawio
# As this plugin adds renderer html for every drawio diagram
# referenced in your markdown files. This rendering happens
# in the on_post_page event, which is skipped by this plugin
# therefore we need to manual execute the drawio plugin renderer here.
if config.get("plugins", {}).get("drawio"):
html = config.get("plugins", {}).get("drawio").render_drawio_diagrams(html, self.print_page)
html = config.get("plugins", {}).get("drawio").render_drawio_diagrams(html, page)

# Compatibility with mkdocs-autorefs
# As this plugin processes cross-references in the on_env event,
Expand Down Expand Up @@ -447,4 +498,4 @@ def print_page_url_mapper(identifier, from_url=None):
html = html.replace("</head>", print_site_js + "</head>")

# Write the print_page file to the output folder
write_file(html.encode("utf-8", errors="xmlcharrefreplace"), self.print_page.file.abs_dest_path)
write_file(html.encode("utf-8", errors="xmlcharrefreplace"), page.file.abs_dest_path)
14 changes: 14 additions & 0 deletions src/mkdocs_print_site_plugin/utils.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import os
import unicodedata


def get_theme_name(config) -> str:
Expand Down Expand Up @@ -28,3 +29,16 @@ def get_theme_name(config) -> str:

def get_section_id(section_number: str) -> str:
return f"section-{section_number.replace('.', '-')}"


def generate_link_from(title: str) -> str:
"""
Generates a link from the provided title.
"""
ndf_string = unicodedata.normalize('NFD', title.lower())
is_not_accent = lambda char: unicodedata.category(char) != 'Mn'
is_punctuation = lambda char: unicodedata.category(char).startswith('P')
is_separator = lambda char: unicodedata.category(char).startswith('Z')
return ''.join(
char for char in ndf_string if is_not_accent(char) and not is_punctuation(char) and not is_separator(char)
)
4 changes: 3 additions & 1 deletion tests/fixtures/projects/nested_sections/docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,6 @@

Goal of this site is to show a very nested section navigation.

See [mkdocs-print-site-plugin#27](https://github.com/timvink/mkdocs-print-site-plugin/issues/27)
See [mkdocs-print-site-plugin#27](https://github.com/timvink/mkdocs-print-site-plugin/issues/27)

GFp6NVqU7S
4 changes: 3 additions & 1 deletion tests/fixtures/projects/nested_sections/docs/page1.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# page1

hello
hello

lRLw8LcChv
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
site_name: Test

theme:
name: material
palette:
- scheme: default
toggle:
icon: material/toggle-switch-off-outline
name: Switch to dark mode
- scheme: slate
toggle:
icon: material/toggle-switch
name: Switch to light mode

plugins:
- print-site:
enumerate_headings: false
print_by_section: true

nav:
- index.md
- Section:
- page1.md
- page5.md
- Subsection:
- page2.md
- Another subsection:
- page3.md
- And another:
- page6.md
- page7.md
- page4.md
- page8.md
- info.md

12 changes: 12 additions & 0 deletions tests/test_building.py
Original file line number Diff line number Diff line change
Expand Up @@ -330,3 +330,15 @@ def test_basic_build99(tmp_path):
)
assert text_in_page(prj_path, "print_page/index.html", '<h1 id="a-a">A')
assert text_in_page(prj_path, "print_page/index.html", '<h1 id="z-z">Z')

def test_print_by_section(tmp_path):
"""
Check if print_section works.
"""
prj_path = check_build(tmp_path, "nested_sections/mkdocs_print_by_section.yml")

# Check that page1 content is included in print page section
assert text_in_page(prj_path, "print_page_section/index.html", "lRLw8LcChv")

# Check that index content is not included in print page section
assert not text_in_page(prj_path, "print_page_section/index.html", "GFp6NVqU7S")
25 changes: 25 additions & 0 deletions tests/test_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import pytest

from mkdocs_print_site_plugin.utils import (
generate_link_from,
)

def test_generate_link_from():
"""
Test generate_link_from.
"""

title = ''
assert generate_link_from(title) == ''

title = 'thisshouldstayunmodified'
assert generate_link_from(title) == 'thisshouldstayunmodified'

title = 'Separa-tors not in url'
assert generate_link_from(title) == 'separatorsnotinurl'

title = "Punctuation.not'in;url"
assert generate_link_from(title) == 'punctuationnotinurl'

title = 'AccéntèdChärsNotinUrl'
assert generate_link_from(title) == 'accentedcharsnotinurl'