mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Replace :file: and :samp: roles by class based implementation
This commit is contained in:
1
CHANGES
1
CHANGES
@@ -116,6 +116,7 @@ Deprecated
|
||||
* ``sphinx.io.SphinxRSTFileInput``
|
||||
* ``sphinx.registry.SphinxComponentRegistry.add_source_input()``
|
||||
* ``sphinx.roles.abbr_role()``
|
||||
* ``sphinx.roles.emph_literal_role()``
|
||||
* ``sphinx.roles.menusel_role()``
|
||||
* ``sphinx.roles.index_role()``
|
||||
* ``sphinx.roles.indexmarkup_role()``
|
||||
|
||||
@@ -380,6 +380,11 @@ The following is a list of deprecated interfaces.
|
||||
- 4.0
|
||||
- ``sphinx.roles.Abbreviation``
|
||||
|
||||
* - ``sphinx.roles.emph_literal_role()``
|
||||
- 2.0
|
||||
- 4.0
|
||||
- ``sphinx.roles.EmphasizedLiteral``
|
||||
|
||||
* - ``sphinx.roles.menusel_role()``
|
||||
- 2.0
|
||||
- 4.0
|
||||
|
||||
@@ -393,6 +393,9 @@ parens_re = re.compile(r'(\\*{|\\*})')
|
||||
def emph_literal_role(typ, rawtext, text, lineno, inliner,
|
||||
options={}, content=[]):
|
||||
# type: (str, str, str, int, Inliner, Dict, List[str]) -> Tuple[List[nodes.Node], List[nodes.system_message]] # NOQA
|
||||
warnings.warn('emph_literal_role() is deprecated. '
|
||||
'Please use EmphasizedLiteral class instead.',
|
||||
RemovedInSphinx40Warning, stacklevel=2)
|
||||
env = inliner.document.settings.env
|
||||
if not typ:
|
||||
assert env.temp_data['default_role']
|
||||
@@ -440,6 +443,58 @@ def emph_literal_role(typ, rawtext, text, lineno, inliner,
|
||||
return [retnode], []
|
||||
|
||||
|
||||
class EmphasizedLiteral(SphinxRole):
|
||||
parens_re = re.compile(r'(\\\\|\\{|\\}|{|})')
|
||||
|
||||
def run(self):
|
||||
# type: () -> Tuple[List[nodes.Node], List[nodes.system_message]]
|
||||
children = self.parse(self.text)
|
||||
node = nodes.literal(self.rawtext, '', *children,
|
||||
role=self.name.lower(), classes=[self.name])
|
||||
|
||||
return [node], []
|
||||
|
||||
def parse(self, text):
|
||||
# type: (str) -> List[nodes.Node]
|
||||
result = [] # type: List[nodes.Node]
|
||||
|
||||
stack = ['']
|
||||
for part in self.parens_re.split(text):
|
||||
if part == '\\\\': # escaped backslash
|
||||
stack[-1] += '\\'
|
||||
elif part == '{':
|
||||
if len(stack) >= 2 and stack[-2] == "{": # nested
|
||||
stack[-1] += "{"
|
||||
else:
|
||||
# start emphasis
|
||||
stack.append('{')
|
||||
stack.append('')
|
||||
elif part == '}':
|
||||
if len(stack) == 3 and stack[1] == "{" and len(stack[2]) > 0:
|
||||
# emphasized word found
|
||||
if stack[0]:
|
||||
result.append(nodes.Text(stack[0], stack[0]))
|
||||
result.append(nodes.emphasis(stack[2], stack[2]))
|
||||
stack = ['']
|
||||
else:
|
||||
# emphasized word not found; the rparen is not a special symbol
|
||||
stack.append('}')
|
||||
stack = [''.join(stack)]
|
||||
elif part == '\\{': # escaped left-brace
|
||||
stack[-1] += '{'
|
||||
elif part == '\\}': # escaped right-brace
|
||||
stack[-1] += '}'
|
||||
else: # others (containing escaped braces)
|
||||
stack[-1] += part
|
||||
|
||||
if ''.join(stack):
|
||||
# remaining is treated as Text
|
||||
text = ''.join(stack)
|
||||
result.append(nodes.Text(text, text))
|
||||
|
||||
return result
|
||||
|
||||
|
||||
_abbr_re = re.compile(r'\((.*)\)$', re.S)
|
||||
|
||||
|
||||
@@ -538,8 +593,8 @@ specific_docroles = {
|
||||
'rfc': RFC(),
|
||||
'guilabel': GUILabel(),
|
||||
'menuselection': MenuSelection(),
|
||||
'file': emph_literal_role,
|
||||
'samp': emph_literal_role,
|
||||
'file': EmphasizedLiteral(),
|
||||
'samp': EmphasizedLiteral(),
|
||||
'abbr': Abbreviation(),
|
||||
'index': Index(),
|
||||
} # type: Dict[str, RoleFunction]
|
||||
|
||||
@@ -184,24 +184,6 @@ def get_verifier(verify, verify_re):
|
||||
'code</span>   <span class="pre">sample</span></code></p>'),
|
||||
r'\\sphinxcode{\\sphinxupquote{code sample}}',
|
||||
),
|
||||
(
|
||||
# correct interpretation of code with whitespace
|
||||
'verify_re',
|
||||
':samp:`code sample`',
|
||||
('<p><code class="(samp )?docutils literal notranslate"><span class="pre">'
|
||||
'code</span>   <span class="pre">sample</span></code></p>'),
|
||||
r'\\sphinxcode{\\sphinxupquote{code sample}}',
|
||||
),
|
||||
(
|
||||
# interpolation of braces in samp and file roles (HTML only)
|
||||
'verify',
|
||||
':samp:`a{b}c`',
|
||||
('<p><code class="samp docutils literal notranslate">'
|
||||
'<span class="pre">a</span>'
|
||||
'<em><span class="pre">b</span></em>'
|
||||
'<span class="pre">c</span></code></p>'),
|
||||
'\\sphinxcode{\\sphinxupquote{a\\sphinxstyleemphasis{b}c}}',
|
||||
),
|
||||
(
|
||||
# interpolation of arrows in menuselection
|
||||
'verify',
|
||||
@@ -314,6 +296,36 @@ def test_inline(get_verifier, type, rst, html_expected, latex_expected):
|
||||
verifier(rst, html_expected, latex_expected)
|
||||
|
||||
|
||||
def test_samp_role(parse):
|
||||
# no braces
|
||||
text = ':samp:`a{b}c`'
|
||||
doctree = parse(text)
|
||||
assert_node(doctree[0], [nodes.paragraph, nodes.literal, ("a",
|
||||
[nodes.emphasis, "b"],
|
||||
"c")])
|
||||
# nested braces
|
||||
text = ':samp:`a{{b}}c`'
|
||||
doctree = parse(text)
|
||||
assert_node(doctree[0], [nodes.paragraph, nodes.literal, ("a",
|
||||
[nodes.emphasis, "{b"],
|
||||
"}c")])
|
||||
|
||||
# half-opened braces
|
||||
text = ':samp:`a{bc`'
|
||||
doctree = parse(text)
|
||||
assert_node(doctree[0], [nodes.paragraph, nodes.literal, "a{bc"])
|
||||
|
||||
# escaped braces
|
||||
text = ':samp:`a\\\\{b}c`'
|
||||
doctree = parse(text)
|
||||
assert_node(doctree[0], [nodes.paragraph, nodes.literal, "a{b}c"])
|
||||
|
||||
# no braces (whitespaces are keeped as is)
|
||||
text = ':samp:`code sample`'
|
||||
doctree = parse(text)
|
||||
assert_node(doctree[0], [nodes.paragraph, nodes.literal, "code sample"])
|
||||
|
||||
|
||||
@pytest.mark.sphinx('dummy', testroot='prolog')
|
||||
def test_rst_prolog(app, status, warning):
|
||||
app.builder.build_all()
|
||||
|
||||
Reference in New Issue
Block a user