diff options
author | Andrey Makarov <ph.makarov@gmail.com> | 2021-03-17 20:08:13 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-03-17 18:08:13 +0100 |
commit | 144e338abb33debfa6ec6abdf3a110aade779485 (patch) | |
tree | 172c716e7165d1b34cceffd01522ff8dbd8523b4 | |
parent | e9b5543bd503ffebbd7fc4b5328d8a9c69419908 (diff) | |
download | Nim-144e338abb33debfa6ec6abdf3a110aade779485.tar.gz |
allow short-style rst references with symbols (#17372)
-rw-r--r-- | lib/packages/docutils/rst.nim | 41 | ||||
-rw-r--r-- | tests/stdlib/trstgen.nim | 25 |
2 files changed, 55 insertions, 11 deletions
diff --git a/lib/packages/docutils/rst.nim b/lib/packages/docutils/rst.nim index ea0c079da..d54d7fa27 100644 --- a/lib/packages/docutils/rst.nim +++ b/lib/packages/docutils/rst.nim @@ -1011,14 +1011,21 @@ proc parseSmiley(p: var RstParser): PRstNode = result.text = val return +proc validRefnamePunct(x: string): bool = + ## https://docutils.sourceforge.io/docs/ref/rst/restructuredtext.html#reference-names + x.len == 1 and x[0] in {'-', '_', '.', ':', '+'} + proc isUrl(p: RstParser, i: int): bool = result = p.tok[i+1].symbol == ":" and p.tok[i+2].symbol == "//" and p.tok[i+3].kind == tkWord and p.tok[i].symbol in ["http", "https", "ftp", "telnet", "file"] -proc parseWordOrUrl(p: var RstParser, father: PRstNode) = - #if currentTok(p).symbol[strStart] == '<': - if isUrl(p, p.idx): +proc parseWordOrRef(p: var RstParser, father: PRstNode) = + ## Parses a normal word or may be a reference or URL. + if nextTok(p).kind != tkPunct: # <- main path, a normal word + father.add newLeaf(p) + inc p.idx + elif isUrl(p, p.idx): # URL http://something var n = newRstNode(rnStandaloneHyperlink) while true: case currentTok(p).kind @@ -1031,10 +1038,26 @@ proc parseWordOrUrl(p: var RstParser, father: PRstNode) = inc p.idx father.add(n) else: - var n = newLeaf(p) + # check for reference (probably, long one like some.ref.with.dots_ ) + var saveIdx = p.idx + var isRef = false inc p.idx - if currentTok(p).symbol == "_": n = parsePostfix(p, n) - father.add(n) + while currentTok(p).kind in {tkWord, tkPunct}: + if currentTok(p).kind == tkPunct: + if isInlineMarkupEnd(p, "_"): + isRef = true + break + if not validRefnamePunct(currentTok(p).symbol): + break + inc p.idx + if isRef: + let r = newRstNode(rnRef) + for i in saveIdx..p.idx-1: r.add newLeaf(p.tok[i].symbol) + father.add r + inc p.idx # skip final _ + else: # 1 normal word + father.add newLeaf(p.tok[saveIdx].symbol) + p.idx = saveIdx + 1 proc parseBackslash(p: var RstParser, father: PRstNode) = assert(currentTok(p).kind == tkPunct) @@ -1154,10 +1177,6 @@ proc getFootnoteType(label: PRstNode): (FootnoteType, int) = else: result = (fnCitation, -1) -proc validRefnamePunct(x: string): bool = - ## https://docutils.sourceforge.io/docs/ref/rst/restructuredtext.html#reference-names - x.len == 1 and x[0] in {'-', '_', '.', ':', '+'} - proc parseFootnoteName(p: var RstParser, reference: bool): PRstNode = ## parse footnote/citation label. Precondition: start at `[`. ## Label text should be valid ref. name symbol, otherwise nil is returned. @@ -1258,7 +1277,7 @@ proc parseInline(p: var RstParser, father: PRstNode) = if n != nil: father.add(n) return - parseWordOrUrl(p, father) + parseWordOrRef(p, father) of tkAdornment, tkOther, tkWhite: if roSupportMarkdown in p.s.options and currentTok(p).symbol == "```": inc p.idx diff --git a/tests/stdlib/trstgen.nim b/tests/stdlib/trstgen.nim index 7d5c0e28f..61e4d44e7 100644 --- a/tests/stdlib/trstgen.nim +++ b/tests/stdlib/trstgen.nim @@ -1184,6 +1184,31 @@ Test1 doAssert "Ref. <a class=\"reference internal\" " & "href=\"#some-definition\">some definition</a>" in output1 + test "RST references (additional symbols)": + # check that ., _, -, +, : are allowed symbols in references without ` ` + let input1 = dedent """ + sec.1 + ----- + + 2-other:sec+c_2 + ^^^^^^^^^^^^^^^ + + .. _link.1_2021: + + Paragraph + + Ref. sec.1_! and 2-other:sec+c_2_;and link.1_2021_. + """ + let output1 = input1.toHtml + doAssert "id=\"secdot1\"" in output1 + doAssert "id=\"Z2minusothercolonsecplusc-2\"" in output1 + doAssert "id=\"linkdot1-2021\"" in output1 + let ref1 = "<a class=\"reference internal\" href=\"#secdot1\">sec.1</a>" + let ref2 = "<a class=\"reference internal\" href=\"#Z2minusothercolonsecplusc-2\">2-other:sec+c_2</a>" + let ref3 = "<a class=\"reference internal\" href=\"#linkdot1-2021\">link.1_2021</a>" + let refline = "Ref. " & ref1 & "! and " & ref2 & ";and " & ref3 & "." + doAssert refline in output1 + suite "RST/Code highlight": test "Basic Python code highlight": let pythonCode = """ |