1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
|
# --------------------------------------------
# Main part of the plugin
# Defines the MacrosPlugin class
#
# Laurent Franceschetti (c) 2018
# MIT License
# --------------------------------------------
import os
import json
import logging
from bs4 import BeautifulSoup
from mkdocs.config.defaults import MkDocsConfig
from mkdocs.structure.files import Files
from super_collections import SuperDict
from mkdocs.plugins import BasePlugin
from mkdocs.structure.pages import Page
from mkdocs.structure.nav import Navigation
try:
from mkdocs.plugins import event_priority
except ImportError:
event_priority = lambda priority: lambda f: f # No-op fallback
from .common import TEST_DIRNAME, DOCS_DEFAULT_DIRNAME, PAGE_MAP, get_frontmatter
LOWEST_PRIORITY = -90
# ------------------------------------------
# Utilities
# ------------------------------------------
log = logging.getLogger(f"mkdocs.plugins.test")
def fmt(*args):
"Format text for the log"
items = ['[test] - '] + [str(arg) for arg in args]
return ' '.join(items)
def convert_object(object) -> SuperDict:
"Convert an object to a dictionary"
d = {key: value for key, value in object.__dict__.items()
if not key.startswith('_') and
isinstance(value, (str, int, float, dict))}
return SuperDict(d)
def check_dir(dest_file:str):
"Check that the directories of a destination file exist"
os.makedirs(os.path.dirname(dest_file), exist_ok=True)
# ------------------------------------------
# Plugin
# ------------------------------------------
class TestPlugin(BasePlugin):
"""
This plugin generates information necessary
for testing MkDocs project
"""
# ----------------------------
# Directories
# ----------------------------
@property
def docs_dir(self) -> str:
"The docs directory (relative to project dir)"
return self.config.get('docs_dir', DOCS_DEFAULT_DIRNAME)
@property
def test_dir(self) -> str:
"Return the test dir"
return TEST_DIRNAME
@property
def nav(self):
"Get the nav"
try:
return self._nav
except AttributeError:
raise AttributeError("Trying to access the nav attribute too early")
@property
def source_markdown(self) -> SuperDict:
"The table raw (target) markdown (used to complement the page table)"
try:
return self._source_markdown
except AttributeError:
self._source_markdown = SuperDict()
return self._source_markdown
# ----------------------------
# Pages
# ----------------------------
def get_page_map(self) -> SuperDict:
"""
Recursively build the mapping of pages from
self.nav: all pages, created by on_nav().
"""
pages = []
for page in self.nav.pages:
d = convert_object(page)
d.file = convert_object(page.file)
pages.append(d)
return SuperDict({page.file.src_uri: page for page in pages})
# ----------------------------
# Handling events
# ----------------------------
@event_priority(LOWEST_PRIORITY)
def on_nav(self, nav, config, files):
"Set the nav"
self._nav = nav
@event_priority(LOWEST_PRIORITY)
def on_post_build(self, config):
"""
The most important action: export all pages
This method is called at the end of the build process
"""
mapping = self.get_page_map()
out_file = os.path.join(self.test_dir, PAGE_MAP)
log.info(fmt("Debug file:", out_file))
check_dir(out_file)
with open(out_file, 'w') as f:
json.dump(mapping, f, indent=4)
|