diff options
Diffstat (limited to 'nikola/plugins/compile/rest/doc.py')
| -rw-r--r-- | nikola/plugins/compile/rest/doc.py | 81 |
1 files changed, 61 insertions, 20 deletions
diff --git a/nikola/plugins/compile/rest/doc.py b/nikola/plugins/compile/rest/doc.py index 99cce81..705c0bc 100644 --- a/nikola/plugins/compile/rest/doc.py +++ b/nikola/plugins/compile/rest/doc.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2015 Roberto Alsina and others. +# Copyright © 2012-2020 Roberto Alsina and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated @@ -29,12 +29,11 @@ from docutils import nodes from docutils.parsers.rst import roles -from nikola.utils import split_explicit_title +from nikola.utils import split_explicit_title, LOGGER, slugify from nikola.plugin_categories import RestExtension class Plugin(RestExtension): - """Plugin for doc role.""" name = 'rest_doc' @@ -43,16 +42,13 @@ class Plugin(RestExtension): """Set Nikola site.""" self.site = site roles.register_canonical_role('doc', doc_role) + self.site.register_shortcode('doc', doc_shortcode) doc_role.site = site - return super(Plugin, self).set_site(site) + return super().set_site(site) -def doc_role(name, rawtext, text, lineno, inliner, - options={}, content=[]): - """Handle the doc role.""" - # split link's text and post's slug in role content - has_explicit_title, title, slug = split_explicit_title(text) - # check if the slug given is part of our blog posts/pages +def _find_post(slug): + """Find a post with the given slug in posts or pages.""" twin_slugs = False post = None for p in doc_role.site.timeline: @@ -62,27 +58,72 @@ def doc_role(name, rawtext, text, lineno, inliner, else: twin_slugs = True break + return post, twin_slugs + + +def _doc_link(rawtext, text, options={}, content=[]): + """Handle the doc role.""" + # split link's text and post's slug in role content + has_explicit_title, title, slug = split_explicit_title(text) + if '#' in slug: + slug, fragment = slug.split('#', 1) + else: + fragment = None + + # Look for the unslugified input first, then try to slugify (Issue #3450) + post, twin_slugs = _find_post(slug) + if post is None: + slug = slugify(slug) + post, twin_slugs = _find_post(slug) try: if post is None: - raise ValueError + raise ValueError("No post with matching slug found.") except ValueError: + return False, False, None, None, slug + + if not has_explicit_title: + # use post's title as link's text + title = post.title() + permalink = post.permalink() + if fragment: + permalink += '#' + fragment + + return True, twin_slugs, title, permalink, slug + + +def doc_role(name, rawtext, text, lineno, inliner, options={}, content=[]): + """Handle the doc role.""" + success, twin_slugs, title, permalink, slug = _doc_link(rawtext, text, options, content) + if success: + if twin_slugs: + inliner.reporter.warning( + 'More than one post with the same slug. Using "{0}"'.format(permalink)) + LOGGER.warning( + 'More than one post with the same slug. Using "{0}" for doc role'.format(permalink)) + node = make_link_node(rawtext, title, permalink, options) + return [node], [] + else: msg = inliner.reporter.error( '"{0}" slug doesn\'t exist.'.format(slug), line=lineno) prb = inliner.problematic(rawtext, rawtext, msg) return [prb], [msg] - if not has_explicit_title: - # use post's title as link's text - title = post.title() - permalink = post.permalink() - if twin_slugs: - msg = inliner.reporter.warning( - 'More than one post with the same slug. Using "{0}"'.format(permalink)) - node = make_link_node(rawtext, title, permalink, options) - return [node], [] +def doc_shortcode(*args, **kwargs): + """Implement the doc shortcode.""" + text = kwargs['data'] + success, twin_slugs, title, permalink, slug = _doc_link(text, text, LOGGER) + if success: + if twin_slugs: + LOGGER.warning( + 'More than one post with the same slug. Using "{0}" for doc shortcode'.format(permalink)) + return '<a href="{0}">{1}</a>'.format(permalink, title) + else: + LOGGER.error( + '"{0}" slug doesn\'t exist.'.format(slug)) + return '<span class="error text-error" style="color: red;">Invalid link: {0}</span>'.format(text) def make_link_node(rawtext, text, url, options): |
