5"""Markdown extension for xrefs and reference to other Markdown files.
7Xref is a reference of form [`symbol`][] or [text][`symbol`], where symbol
8is expected to be one of the following:
10 * package:-scheme URI - it will be resolved using .packages file in the
13 * C++ symbol - will be resolved through xref.json file (see README.md)
15Xrefs are converted to GitHub links.
17Additionally this extension retargets links pointing to markdown files to
18the html files produced
from these markdown files.
28import xml.etree.ElementTree as etree
29from typing import Dict, Optional
30from urllib.parse import urlparse
32from cpp_indexer import SymbolsIndex, load_index
33from markdown.extensions import Extension
34from markdown.inlinepatterns import InlineProcessor
35from markdown.treeprocessors import Treeprocessor
38class _XrefPattern(InlineProcessor):
39 """Converts xrefs into GitHub links.
41 Recognizes [`symbol`][] and [text][`symbol`] link formats where symbol
42 is expected to be one of the following:
44 * Fully qualified reference to a C++
class, method
or function;
45 * Package URI pointing to one of the packages included
in the SDK
47 * File reference to one of the file
in the SDK.
50 XREF_RE = r'\[`(?P<symbol>[^]]+)`\]?\[\]|\[(?P<text>[^]]*)\]\[`(?P<target>[^]]+)`\]'
52 def __init__(self, md, symbols_index: SymbolsIndex,
53 packages: Dict[str, str]):
54 super().
__init__(_XrefPattern.XREF_RE)
60 text = m.group(
'text')
61 symbol = m.group(
'symbol')
63 symbol = m.group(
'target')
69 self.
md.xrefs[f
"`{symbol}`"] = uri
73 anchor = etree.Element(
'a')
74 anchor.attrib[
'href'] = uri
75 anchor.attrib[
'target'] =
'_blank'
79 code = etree.Element(
'code')
80 code.text = re.sub(
r'^dart::',
'', symbol)
84 return anchor, m.start(0), m.end(0)
86 def _resolve_ref(self, ref: str) -> Optional[str]:
87 if ref.startswith(
'package:'):
90 (package_name, *path_to_file) = uri.path.split(
'/', 1)
91 package_path = self.
packages[package_name]
92 if len(path_to_file) == 0:
96 os.path.join(package_path, path_to_file[0]))
97 elif os.path.exists(ref):
106 logging.error(
'Failed to resolve xref %s', ref)
109 def _make_github_uri(self, file: str, lineno: Optional[int] =
None) -> str:
110 """Generates source link pointing to GitHub"""
111 fragment = f
'#L{lineno}' if lineno
is not None else ''
112 return f
'https://github.com/dart-lang/sdk/blob/{self.symbols_index.commit}/{file}{fragment}'
116 """Redirects links pointing to .md files to .html files built from them."""
119 for elem
in root.iter(
'a'):
120 href = elem.get(
'href')
123 parsed_href = urlparse(href)
124 if parsed_href.path.endswith(
'.md'):
127 parsed_href._replace(path=parsed_href.path[:-3] +
132 """Markdown extension which handles xrefs and links to markdown files."""
133 symbols_index: SymbolsIndex
134 packages: Dict[str, str]
139 self.
packages = XrefExtension._load_package_config()
145 md.inlinePatterns.register(
149 def _load_package_config() -> Dict[str, str]:
151 with open(
'.dart_tool/package_config.json',
152 encoding=
'utf-8')
as package_config_file:
153 package_config = json.load(package_config_file)
154 return dict([(pkg[
'name'],
156 os.path.join(
'.dart_tool/', pkg[
'rootUri'],
158 for pkg
in package_config[
'packages']
159 if 'packageUri' in pkg])
def extendMarkdown(self, md)
def handleMatch(self, m, data)
def __init__(self, md, SymbolsIndex symbols_index, Dict[str, str] packages)
str _make_github_uri(self, str file, Optional[int] lineno=None)
Optional[str] _resolve_ref(self, str ref)
SymbolsIndex load_index(str filename)