aboutsummaryrefslogtreecommitdiff
path: root/docs/extensions/refman_links.py
diff options
context:
space:
mode:
Diffstat (limited to 'docs/extensions/refman_links.py')
-rw-r--r--docs/extensions/refman_links.py108
1 files changed, 108 insertions, 0 deletions
diff --git a/docs/extensions/refman_links.py b/docs/extensions/refman_links.py
new file mode 100644
index 0000000..857d2cb
--- /dev/null
+++ b/docs/extensions/refman_links.py
@@ -0,0 +1,108 @@
+from pathlib import Path
+from json import loads
+import re
+
+from hotdoc.core.exceptions import HotdocSourceException
+from hotdoc.core.extension import Extension
+from hotdoc.core.tree import Page
+from hotdoc.core.project import Project
+from hotdoc.run_hotdoc import Application
+from hotdoc.core.formatter import Formatter
+from hotdoc.utils.loggable import Logger, warn, info
+
+import typing as T
+
+if T.TYPE_CHECKING:
+ import argparse
+
+Logger.register_warning_code('unknown-refman-link', HotdocSourceException, 'refman-links')
+
+class RefmanLinksExtension(Extension):
+ extension_name = 'refman-links'
+ argument_prefix = 'refman'
+
+ def __init__(self, app: Application, project: Project):
+ self.project: Project
+ super().__init__(app, project)
+ self._data_file: T.Optional[Path] = None
+ self._data: T.Dict[str, str] = {}
+
+ @staticmethod
+ def add_arguments(parser: 'argparse.ArgumentParser'):
+ group = parser.add_argument_group(
+ 'Refman links',
+ 'Custom Meson extension',
+ )
+
+ # Add Arguments with `group.add_argument(...)`
+ group.add_argument(
+ f'--refman-data-file',
+ help="JSON file with the mappings to replace",
+ default=None,
+ )
+
+ def parse_config(self, config: T.Dict[str, T.Any]) -> None:
+ super().parse_config(config)
+ self._data_file = config.get('refman_data_file')
+
+ def _formatting_page_cb(self, formatter: Formatter, page: Page) -> None:
+ ''' Replace Meson refman tags
+
+ Links of the form [[function]] are automatically replaced
+ with valid links to the correct URL. To reference objects / types use the
+ [[@object]] syntax.
+ '''
+ link_regex = re.compile(r'\[\[#?@?([ \n\t]*[a-zA-Z0-9_]+[ \n\t]*\.)*[ \n\t]*[a-zA-Z0-9_]+[ \n\t]*\]\]', re.MULTILINE)
+ for m in link_regex.finditer(page.formatted_contents):
+ i = m.group()
+ obj_id: str = i[2:-2]
+ obj_id = re.sub(r'[ \n\t]', '', obj_id) # Remove whitespaces
+
+ # Marked as inside a code block?
+ in_code_block = False
+ if obj_id.startswith('#'):
+ in_code_block = True
+ obj_id = obj_id[1:]
+
+ if obj_id not in self._data:
+ warn('unknown-refman-link', f'{Path(page.name).name}: Unknown Meson refman link: "{obj_id}"')
+ continue
+
+ # Just replaces [[!file.id]] paths with the page file (no fancy HTML)
+ if obj_id.startswith('!'):
+ page.formatted_contents = page.formatted_contents.replace(i, self._data[obj_id])
+ continue
+
+ # Fancy links for functions and methods
+ text = obj_id
+ if text.startswith('@'):
+ text = text[1:]
+ else:
+ text = text + '()'
+ if not in_code_block:
+ text = f'<code>{text}</code>'
+ link = f'<a href="{self._data[obj_id]}"><ins>{text}</ins></a>'
+ page.formatted_contents = page.formatted_contents.replace(i, link)
+
+ def setup(self) -> None:
+ super().setup()
+
+ if not self._data_file:
+ info('Meson refman extension DISABLED')
+ return
+
+ raw = Path(self._data_file).read_text(encoding='utf-8')
+ self._data = loads(raw)
+
+ # Register formater
+ for ext in self.project.extensions.values():
+ ext = T.cast(Extension, ext)
+ ext.formatter.formatting_page_signal.connect(self._formatting_page_cb)
+ info('Meson refman extension LOADED')
+
+ @staticmethod
+ def get_dependencies() -> T.List[T.Type[Extension]]:
+ return [] # In case this extension has dependencies on other extensions
+
+def get_extension_classes() -> T.List[T.Type[Extension]]:
+ return [RefmanLinksExtension]