Ejemplo n.º 1
0
    def on_template_context(self, context, template_name, config, **kwargs):
        """
        The template_context event is called immediately after the context is created
        for the subject template and can be used to alter the context for that specific template only.

        See https://www.mkdocs.org/dev-guide/plugins/#on_template_context
        """
        if not self.config.get("enabled"):
            return

        # Save the page context
        # We'll use the same context of the last rendered page
        # And apply it to the print page as well (in on_post_build event)

        # Note a theme can have multiple templates
        # Found a bug where in the mkdocs theme,
        # the "sitemap.xml" static template
        # has incorrect 'extra_css' and 'extra_js' paths
        # leading to breaking the print page
        # at random (when sitemap.xml was rendered last)
        # we're assuming here all templates have a 404.html template
        # print(f"\nName: {template_name}\nContext: {context.get('extra_css')}")
        if template_name == "404.html":
            self.context = context
            # Make sure paths are OK
            if config.get('extra_css'):
                self.context['extra_css'] = [
                    get_relative_url(f, self.print_page.file.url)
                    for f in config.get('extra_css')
                ]
            if config.get('extra_javascript'):
                self.context['extra_javascript'] = [
                    get_relative_url(f, self.print_page.file.url)
                    for f in config.get('extra_javascript')
                ]
    def test_get_relative_url_empty(self):
        for url in ['', '.', '/.']:
            for other in ['', '.', '/', '/.']:
                self.assertEqual(utils.get_relative_url(url, other), '.')

        self.assertEqual(utils.get_relative_url('/', ''), './')
        self.assertEqual(utils.get_relative_url('/', '/'), './')
        self.assertEqual(utils.get_relative_url('/', '.'), './')
        self.assertEqual(utils.get_relative_url('/', '/.'), './')
Ejemplo n.º 3
0
 def test_get_relative_url(self):
     expected_results = {
         ('foo/bar', 'foo'): 'bar',
         ('foo/bar.txt', 'foo'): 'bar.txt',
         ('foo', 'foo/bar'): '..',
         ('foo', 'foo/bar.txt'): '.',
         ('foo/../../bar', '.'): 'bar',
         ('foo/../../bar', 'foo'): '../bar',
         ('foo//./bar/baz', 'foo/bar/baz'): '.',
         ('a/b/.././../c', '.'): 'c',
         ('a/b/c/d/ee', 'a/b/c/d/e'): '../ee',
         ('a/b/c/d/ee', 'a/b/z/d/e'): '../../../c/d/ee',
         ('foo', 'bar.'): 'foo',
         ('foo', 'bar./'): '../foo',
         ('foo', 'foo/bar./'): '..',
         ('foo', 'foo/bar./.'): '..',
         ('foo', 'foo/bar././'): '..',
         ('foo/', 'foo/bar././'): '../',
         ('foo', 'foo'): '.',
         ('.foo', '.foo'): '.foo',
         ('.foo/', '.foo'): '.foo/',
         ('.foo', '.foo/'): '.',
         ('.foo/', '.foo/'): './',
         ('///', ''): './',
         ('a///', ''): 'a/',
         ('a///', 'a'): './',
         ('.', 'here'): '..',
         ('..', 'here'): '..',
         ('../..', 'here'): '..',
         ('../../a', 'here'): '../a',
         ('..', 'here.txt'): '.',
         ('a', ''): 'a',
         ('a', '..'): 'a',
         ('a', 'b'): '../a',
         ('a', 'b/..'):
         '../a',  # The dots are considered a file. Documenting a long-standing bug.
         ('a', 'b/../..'): 'a',
         ('a/..../b', 'a/../b'): '../a/..../b',
         ('a/я/b', 'a/я/c'): '../b',
         ('a/я/b', 'a/яя/c'): '../../я/b',
     }
     for (url, other), expected_result in expected_results.items():
         # Leading slash intentionally ignored
         self.assertEqual(utils.get_relative_url(url, other),
                          expected_result)
         self.assertEqual(utils.get_relative_url('/' + url, other),
                          expected_result)
         self.assertEqual(utils.get_relative_url(url, '/' + other),
                          expected_result)
         self.assertEqual(utils.get_relative_url('/' + url, '/' + other),
                          expected_result)
Ejemplo n.º 4
0
def get_context(nav, files, config, page=None, base_url=''):
    """
    Return the template context for a given page or template.
    """

    if page is not None:
        base_url = utils.get_relative_url('.', page.url)

    extra_javascript = utils.create_media_urls(config['extra_javascript'],
                                               page, base_url)

    extra_css = utils.create_media_urls(config['extra_css'], page, base_url)

    if isinstance(files, Files):
        files = files.documentation_pages()

    return {
        'nav': nav,
        'pages': files,
        'base_url': base_url,
        'extra_css': extra_css,
        'extra_javascript': extra_javascript,
        'mkdocs_version': mkdocs.__version__,
        'build_date_utc': utils.get_build_datetime(),
        'config': config,
        'page': page,
    }
Ejemplo n.º 5
0
def _build_template(name, template, files, config, nav):
    """
    Return rendered output for given template as a string.
    """

    # Run `pre_template` plugin events.
    template = config['plugins'].run_event(
        'pre_template', template, template_name=name, config=config
    )

    if utils.is_error_template(name):
        # Force absolute URLs in the nav of error pages and account for the
        # possability that the docs root might be different than the server root.
        # See https://github.com/mkdocs/mkdocs/issues/77.
        # However, if site_url is not set, assume the docs root and server root
        # are the same. See https://github.com/mkdocs/mkdocs/issues/1598.
        base_url = urlparse(config['site_url'] or '/').path
    else:
        base_url = utils.get_relative_url('.', name)

    context = get_context(nav, files, config, base_url=base_url)

    # Run `template_context` plugin events.
    context = config['plugins'].run_event(
        'template_context', context, template_name=name, config=config
    )

    output = template.render(context)

    # Run `post_template` plugin events.
    output = config['plugins'].run_event(
        'post_template', output, template_name=name, config=config
    )

    return output
Ejemplo n.º 6
0
def get_context(nav, files, config, page=None, base_url=''):
    """
    Return the template context for a given page or template.
    """

    if page is not None:
        base_url = utils.get_relative_url('.', page.url)

    extra_javascript = utils.create_media_urls(config['extra_javascript'], page, base_url)

    extra_css = utils.create_media_urls(config['extra_css'], page, base_url)

    # Support SOURCE_DATE_EPOCH environment variable for "reproducible" builds.
    # See https://reproducible-builds.org/specs/source-date-epoch/
    timestamp = int(os.environ.get('SOURCE_DATE_EPOCH', timegm(datetime.utcnow().utctimetuple())))

    return {
        'nav': nav,
        'pages': files.documentation_pages(),

        'base_url': base_url,

        'extra_css': extra_css,
        'extra_javascript': extra_javascript,

        'mkdocs_version': mkdocs.__version__,
        'build_date_utc': datetime.utcfromtimestamp(timestamp),

        'config': config,
        'page': page,
    }
Ejemplo n.º 7
0
    def on_page_content(self, html, page, config, files, **kwargs):
        """
        The page_content event is called after the Markdown text is rendered to HTML.

        (but before being passed to a template) and can be used to alter the HTML body of the page.
        See https://www.mkdocs.org/user-guide/plugins/#on_page_content.
        """
        if not self.config.get("enabled"):
            return html

        # Save each page HTML *before* a template is applied inside the page class
        if page != self.print_page:
            page.html = html

        # We need to validate that the first heading on each page is a h1
        # This is required for the print page table of contents and enumeration logic
        if self.config.get("add_table_of_contents") or self.config.get(
                "enumerate_headings"):
            if page in self.all_pages_in_nav:
                match = re.search(r"\<h[0-6]", html)
                if match:
                    if not match.group() == "<h1":
                        msg = f"The page {page.title} ({page.file.src_path}) does not start with a level 1 heading."
                        msg += "This is required for print page Table of Contents and/or enumeration of headings."
                        raise AssertionError(msg)

        # Link to the PDF version of the entire site on a page.
        if self.config.get("path_to_pdf") != "":
            page.url_to_pdf = get_relative_url(self.config.get("path_to_pdf"),
                                               page.file.url)

        return html
Ejemplo n.º 8
0
def _build_template(name, template, files, config, nav):
    """
    Return rendered output for given template as a string.
    """

    # Run `pre_template` plugin events.
    template = config['plugins'].run_event(
        'pre_template', template, template_name=name, config=config
    )

    if utils.is_error_template(name):
        # Force absolute URLs in the nav of error pages and account for the
        # possability that the docs root might be different than the server root.
        # See https://github.com/mkdocs/mkdocs/issues/77.
        # However, if site_url is not set, assume the docs root and server root
        # are the same. See https://github.com/mkdocs/mkdocs/issues/1598.
        base_url = utils.urlparse(config['site_url'] or '/').path
    else:
        base_url = utils.get_relative_url('.', name)

    context = get_context(nav, files, config, base_url=base_url)

    # Run `template_context` plugin events.
    context = config['plugins'].run_event(
        'template_context', context, template_name=name, config=config
    )

    output = template.render(context)

    # Run `post_template` plugin events.
    output = config['plugins'].run_event(
        'post_template', output, template_name=name, config=config
    )

    return output
Ejemplo n.º 9
0
def get_context(nav, files, config, page=None, base_url=''):
    """
    Return the template context for a given page or template.
    """

    if page is not None:
        base_url = utils.get_relative_url('.', page.url)

    extra_javascript = utils.create_media_urls(config['extra_javascript'], page, base_url)

    extra_css = utils.create_media_urls(config['extra_css'], page, base_url)

    # Support SOURCE_DATE_EPOCH environment variable for "reproducible" builds.
    # See https://reproducible-builds.org/specs/source-date-epoch/
    timestamp = int(os.environ.get('SOURCE_DATE_EPOCH', timegm(datetime.utcnow().utctimetuple())))

    return {
        'nav': nav,
        'pages': files.documentation_pages(),

        'base_url': base_url,

        'extra_css': extra_css,
        'extra_javascript': extra_javascript,

        'mkdocs_version': mkdocs.__version__,
        'build_date_utc': datetime.utcfromtimestamp(timestamp),

        'config': config,
        'page': page,
    }
Ejemplo n.º 10
0
    def __render_tag_links(self, tag, pages):
        content = ["## <span class=\"md-tag\">{}</span>".format(tag), ""]
        for page in pages:
            url = utils.get_relative_url(page.file.src_path,
                                         self.tags_file.src_path)
            content.append("- [{}]({})".format(
                page.meta.get("title", page.title), url))

        # Return rendered tag links
        return "\n".join(content)
Ejemplo n.º 11
0
    def on_page_content(self, html, page, config, files, **kwargs):

        # Save each page HTML *before* a template is applied inside the page class
        if page != self.print_page:
            page.html = html

        if self.config.get("path_to_pdf") != "":
            page.url_to_pdf = get_relative_url(self.config.get("path_to_pdf"),
                                               page.file.url)

        return html
Ejemplo n.º 12
0
    def __render_tag_links(self, tag, pages):
        content = [f"## <span class=\"md-tag\">{tag}</span>", ""]
        for page in pages:
            url = utils.get_relative_url(
                page.file.src_path.replace(os.path.sep, "/"),
                self.tags_file.src_path.replace(os.path.sep, "/"))

            # Ensure forward slashes, as we have to use the path of the source
            # file which contains the operating system's path separator.
            content.append("- [{}]({})".format(
                page.meta.get("title", page.title), url))

        # Return rendered tag links
        return "\n".join(content)
Ejemplo n.º 13
0
    def on_page_content(self, html, page, config, files, **kwargs):
        """
        The page_content event is called after the Markdown text is rendered to HTML.

        (but before being passed to a template) and can be used to alter the HTML body of the page.
        See https://www.mkdocs.org/user-guide/plugins/#on_page_content.
        """
        # Save each page HTML *before* a template is applied inside the page class
        if page != self.print_page:
            page.html = html

        # Link to the PDF version of the entire site on a page.
        if self.config.get("path_to_pdf") != "":
            page.url_to_pdf = get_relative_url(self.config.get("path_to_pdf"),
                                               page.file.url)

        return html
Ejemplo n.º 14
0
 def url_relative_to(self, other):
     """ Return url for file relative to other file. """
     return utils.get_relative_url(self.url, other.url if isinstance(other, File) else other)
Ejemplo n.º 15
0
 def url(value):
     return normalize_url(value,
                          page=page,
                          base=get_relative_url('.', page.url))