1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921 |
- discard """
- output: '''
- [Suite] RST parsing
- [Suite] RST tables
- [Suite] RST indentation
- [Suite] Markdown indentation
- [Suite] Warnings
- [Suite] RST include directive
- [Suite] RST escaping
- [Suite] RST inline markup
- '''
- matrix: "--mm:refc; --mm:orc"
- """
- # tests for rst module
- import ../../lib/packages/docutils/[rstgen, rst, rstast]
- import unittest, strutils
- import std/private/miscdollars
- import os
- import std/[assertions, syncio]
- const preferMarkdown = {roPreferMarkdown, roSupportMarkdown, roNimFile, roSandboxDisabled}
- # legacy nimforum / old default mode:
- const preferRst = {roSupportMarkdown, roNimFile, roSandboxDisabled}
- const pureRst = {roNimFile, roSandboxDisabled}
- proc toAst(input: string,
- rstOptions: RstParseOptions = preferMarkdown,
- error: ref string = nil,
- warnings: ref seq[string] = nil): string =
- ## If `error` is nil then no errors should be generated.
- ## The same goes for `warnings`.
- proc testMsgHandler(filename: string, line, col: int, msgkind: MsgKind,
- arg: string) =
- let mc = msgkind.whichMsgClass
- let a = $msgkind % arg
- var message: string
- toLocation(message, filename, line, col + ColRstOffset)
- message.add " $1: $2" % [$mc, a]
- if mc == mcError:
- if error == nil:
- raise newException(EParseError, "[unexpected error] " & message)
- error[] = message
- # we check only first error because subsequent ones may be meaningless
- raise newException(EParseError, "")
- else:
- doAssert warnings != nil, "unexpected RST warning '" & message & "'"
- warnings[].add message
- try:
- const filen = "input"
- proc myFindFile(filename: string): string =
- # we don't find any files in online mode:
- result = ""
- var (rst, _, _) = rstParse(input, filen, line=LineRstInit, column=ColRstInit,
- rstOptions, myFindFile, nil, testMsgHandler)
- result = treeRepr(rst)
- except EParseError as e:
- if e.msg != "":
- result = e.msg
- suite "RST parsing":
- test "Standalone punctuation is not parsed as heading overlines":
- check(dedent"""
- Paragraph
- !""".toAst ==
- dedent"""
- rnInner
- rnParagraph
- rnLeaf 'Paragraph'
- rnParagraph
- rnLeaf '!'
- """)
- check(dedent"""
- Paragraph1
- ...
- Paragraph2""".toAst ==
- dedent"""
- rnInner
- rnParagraph
- rnLeaf 'Paragraph1'
- rnParagraph
- rnLeaf '...'
- rnParagraph
- rnLeaf 'Paragraph2'
- """)
- check(dedent"""
- ---
- Paragraph""".toAst ==
- dedent"""
- rnInner
- rnLeaf '---'
- rnLeaf ' '
- rnLeaf 'Paragraph'
- """)
- test "References are whitespace-neutral and case-insensitive":
- # refname is 'lexical-analysis', the same for all the 3 variants:
- check(dedent"""
- Lexical Analysis
- ================
- Ref. `Lexical Analysis`_ or `Lexical analysis`_ or `lexical analysis`_.
- """.toAst ==
- dedent"""
- rnInner
- rnHeadline level=1 anchor='lexical-analysis'
- rnLeaf 'Lexical'
- rnLeaf ' '
- rnLeaf 'Analysis'
- rnParagraph
- rnLeaf 'Ref'
- rnLeaf '.'
- rnLeaf ' '
- rnInternalRef
- rnInner
- rnLeaf 'Lexical'
- rnLeaf ' '
- rnLeaf 'Analysis'
- rnLeaf 'lexical-analysis'
- rnLeaf ' '
- rnLeaf 'or'
- rnLeaf ' '
- rnInternalRef
- rnInner
- rnLeaf 'Lexical'
- rnLeaf ' '
- rnLeaf 'analysis'
- rnLeaf 'lexical-analysis'
- rnLeaf ' '
- rnLeaf 'or'
- rnLeaf ' '
- rnInternalRef
- rnInner
- rnLeaf 'lexical'
- rnLeaf ' '
- rnLeaf 'analysis'
- rnLeaf 'lexical-analysis'
- rnLeaf '.'
- rnLeaf ' '
- """)
- test "RST quoted literal blocks":
- let expected =
- dedent"""
- rnInner
- rnLeaf 'Paragraph'
- rnLeaf ':'
- rnLiteralBlock
- rnLeaf '>x'
- """
- check(dedent"""
- Paragraph::
- >x""".toAst(rstOptions = preferRst) == expected)
- check(dedent"""
- Paragraph::
- >x""".toAst(rstOptions = preferRst) == expected)
- test "RST quoted literal blocks, :: at a separate line":
- let expected =
- dedent"""
- rnInner
- rnInner
- rnLeaf 'Paragraph'
- rnLiteralBlock
- rnLeaf '>x
- >>y'
- """
- check(dedent"""
- Paragraph
- ::
- >x
- >>y""".toAst(rstOptions = preferRst) == expected)
- check(dedent"""
- Paragraph
- ::
- >x
- >>y""".toAst(rstOptions = preferRst) == expected)
- test "Markdown quoted blocks":
- check(dedent"""
- Paragraph.
- >x""".toAst ==
- dedent"""
- rnInner
- rnLeaf 'Paragraph'
- rnLeaf '.'
- rnMarkdownBlockQuote
- rnMarkdownBlockQuoteItem quotationDepth=1
- rnLeaf 'x'
- """)
- # bug #17987
- check(dedent"""
- foo https://github.com/nim-lang/Nim/issues/8258
- > bar""".toAst ==
- dedent"""
- rnInner
- rnInner
- rnLeaf 'foo'
- rnLeaf ' '
- rnStandaloneHyperlink
- rnLeaf 'https://github.com/nim-lang/Nim/issues/8258'
- rnMarkdownBlockQuote
- rnMarkdownBlockQuoteItem quotationDepth=1
- rnLeaf 'bar'
- """)
- let expected = dedent"""
- rnInner
- rnLeaf 'Paragraph'
- rnLeaf '.'
- rnMarkdownBlockQuote
- rnMarkdownBlockQuoteItem quotationDepth=1
- rnInner
- rnLeaf 'x1'
- rnLeaf ' '
- rnLeaf 'x2'
- rnMarkdownBlockQuoteItem quotationDepth=2
- rnInner
- rnLeaf 'y1'
- rnLeaf ' '
- rnLeaf 'y2'
- rnMarkdownBlockQuoteItem quotationDepth=1
- rnLeaf 'z'
- """
- check(dedent"""
- Paragraph.
- >x1 x2
- >>y1 y2
- >z""".toAst == expected)
- check(dedent"""
- Paragraph.
- > x1 x2
- >> y1 y2
- > z""".toAst == expected)
- check(dedent"""
- >x
- >y
- >z""".toAst ==
- dedent"""
- rnMarkdownBlockQuote
- rnMarkdownBlockQuoteItem quotationDepth=1
- rnInner
- rnLeaf 'x'
- rnLeaf ' '
- rnLeaf 'y'
- rnLeaf ' '
- rnLeaf 'z'
- """)
- check(dedent"""
- > z
- > > >y
- """.toAst ==
- dedent"""
- rnMarkdownBlockQuote
- rnMarkdownBlockQuoteItem quotationDepth=1
- rnLeaf 'z'
- rnMarkdownBlockQuoteItem quotationDepth=3
- rnLeaf 'y'
- """)
- test "Markdown quoted blocks: lazy":
- let expected = dedent"""
- rnInner
- rnMarkdownBlockQuote
- rnMarkdownBlockQuoteItem quotationDepth=2
- rnInner
- rnLeaf 'x'
- rnLeaf ' '
- rnLeaf 'continuation1'
- rnLeaf ' '
- rnLeaf 'continuation2'
- rnParagraph
- rnLeaf 'newParagraph'
- """
- check(dedent"""
- >>x
- continuation1
- continuation2
- newParagraph""".toAst == expected)
- check(dedent"""
- >> x
- continuation1
- continuation2
- newParagraph""".toAst == expected)
- # however mixing more than 1 non-lazy line and lazy one(s) splits quote
- # in our parser, which appeared the easiest way to handle such cases:
- var warnings = new seq[string]
- check(dedent"""
- >> x
- >> continuation1
- continuation2
- newParagraph""".toAst(warnings=warnings) ==
- dedent"""
- rnInner
- rnMarkdownBlockQuote
- rnMarkdownBlockQuoteItem quotationDepth=2
- rnLeaf 'x'
- rnMarkdownBlockQuoteItem quotationDepth=2
- rnInner
- rnLeaf 'continuation1'
- rnLeaf ' '
- rnLeaf 'continuation2'
- rnParagraph
- rnLeaf 'newParagraph'
- """)
- check(warnings[] == @[
- "input(2, 1) Warning: RST style: two or more quoted lines " &
- "are followed by unquoted line 3"])
- test "Markdown quoted blocks: not lazy":
- # here is where we deviate from CommonMark specification: 'bar' below is
- # not considered as continuation of 2-level '>> foo' quote.
- check(dedent"""
- >>> foo
- > bar
- >> baz
- """.toAst() ==
- dedent"""
- rnMarkdownBlockQuote
- rnMarkdownBlockQuoteItem quotationDepth=3
- rnLeaf 'foo'
- rnMarkdownBlockQuoteItem quotationDepth=1
- rnLeaf 'bar'
- rnMarkdownBlockQuoteItem quotationDepth=2
- rnLeaf 'baz'
- """)
- test "Markdown quoted blocks: inline markup works":
- check(dedent"""
- > hi **bold** text
- """.toAst == dedent"""
- rnMarkdownBlockQuote
- rnMarkdownBlockQuoteItem quotationDepth=1
- rnInner
- rnLeaf 'hi'
- rnLeaf ' '
- rnStrongEmphasis
- rnLeaf 'bold'
- rnLeaf ' '
- rnLeaf 'text'
- """)
- test "Markdown quoted blocks: blank line separator":
- let expected = dedent"""
- rnInner
- rnMarkdownBlockQuote
- rnMarkdownBlockQuoteItem quotationDepth=1
- rnInner
- rnLeaf 'x'
- rnLeaf ' '
- rnLeaf 'y'
- rnMarkdownBlockQuote
- rnMarkdownBlockQuoteItem quotationDepth=1
- rnInner
- rnLeaf 'z'
- rnLeaf ' '
- rnLeaf 't'
- """
- check(dedent"""
- >x
- >y
- > z
- > t""".toAst == expected)
- check(dedent"""
- >x
- y
- > z
- t""".toAst == expected)
- test "Markdown quoted blocks: nested body blocks/elements work #1":
- let expected = dedent"""
- rnMarkdownBlockQuote
- rnMarkdownBlockQuoteItem quotationDepth=1
- rnBulletList
- rnBulletItem
- rnInner
- rnLeaf 'x'
- rnBulletItem
- rnInner
- rnLeaf 'y'
- """
- check(dedent"""
- > - x
- - y
- """.toAst == expected)
- # TODO: if bug #17340 point 28 is resolved then this may work:
- # check(dedent"""
- # > - x
- # - y
- # """.toAst == expected)
- check(dedent"""
- > - x
- > - y
- """.toAst == expected)
- check(dedent"""
- >
- > - x
- >
- > - y
- >
- """.toAst == expected)
- test "Markdown quoted blocks: nested body blocks/elements work #2":
- let expected = dedent"""
- rnAdmonition adType=note
- [nil]
- [nil]
- rnDefList
- rnDefItem
- rnDefName
- rnLeaf 'deflist'
- rnLeaf ':'
- rnDefBody
- rnMarkdownBlockQuote
- rnMarkdownBlockQuoteItem quotationDepth=2
- rnInner
- rnLeaf 'quote'
- rnLeaf ' '
- rnLeaf 'continuation'
- """
- check(dedent"""
- .. Note:: deflist:
- >> quote
- continuation
- """.toAst(rstOptions = preferRst) == expected)
- check(dedent"""
- .. Note::
- deflist:
- >> quote
- continuation
- """.toAst(rstOptions = preferRst) == expected)
- check(dedent"""
- .. Note::
- deflist:
- >> quote
- >> continuation
- """.toAst(rstOptions = preferRst) == expected)
- # spaces are not significant between `>`:
- check(dedent"""
- .. Note::
- deflist:
- > > quote
- > > continuation
- """.toAst(rstOptions = preferRst) == expected)
- test "Markdown quoted blocks: de-indent handled well":
- check(dedent"""
- >
- > - x
- > - y
- >
- > Paragraph.
- """.toAst(rstOptions = preferRst) == dedent"""
- rnMarkdownBlockQuote
- rnMarkdownBlockQuoteItem quotationDepth=1
- rnInner
- rnBlockQuote
- rnBulletList
- rnBulletItem
- rnInner
- rnLeaf 'x'
- rnBulletItem
- rnInner
- rnLeaf 'y'
- rnParagraph
- rnLeaf 'Paragraph'
- rnLeaf '.'
- """)
- let expectCodeBlock = dedent"""
- rnCodeBlock
- [nil]
- rnFieldList
- rnField
- rnFieldName
- rnLeaf 'default-language'
- rnFieldBody
- rnLeaf 'Nim'
- rnLiteralBlock
- rnLeaf '
- let a = 1
- ```'
- """
- test "Markdown code blocks with more > 3 backticks":
- check(dedent"""
- ````
- let a = 1
- ```
- ````""".toAst == expectCodeBlock)
- test "Markdown code blocks with ~~~":
- check(dedent"""
- ~~~
- let a = 1
- ```
- ~~~""".toAst == expectCodeBlock)
- check(dedent"""
- ~~~~~
- let a = 1
- ```
- ~~~~~""".toAst == expectCodeBlock)
- test "Markdown code blocks with Nim-specific arguments":
- check(dedent"""
- ```nim number-lines=1 test
- let a = 1
- ```""".toAst ==
- dedent"""
- rnCodeBlock
- rnDirArg
- rnLeaf 'nim'
- rnFieldList
- rnField
- rnFieldName
- rnLeaf 'number-lines'
- rnFieldBody
- rnLeaf '1'
- rnField
- rnFieldName
- rnLeaf 'test'
- rnFieldBody
- rnLiteralBlock
- rnLeaf '
- let a = 1'
- """)
- check(dedent"""
- ```nim test = "nim c $1" number-lines = 1
- let a = 1
- ```""".toAst ==
- dedent"""
- rnCodeBlock
- rnDirArg
- rnLeaf 'nim'
- rnFieldList
- rnField
- rnFieldName
- rnLeaf 'test'
- rnFieldBody
- rnLeaf '"nim c $1"'
- rnField
- rnFieldName
- rnLeaf 'number-lines'
- rnFieldBody
- rnLeaf '1'
- rnLiteralBlock
- rnLeaf '
- let a = 1'
- """)
- test "additional indentation < 4 spaces is handled fine":
- check(dedent"""
- Indentation
- ```nim
- let a = 1
- ```""".toAst ==
- dedent"""
- rnInner
- rnParagraph
- rnLeaf 'Indentation'
- rnParagraph
- rnCodeBlock
- rnDirArg
- rnLeaf 'nim'
- [nil]
- rnLiteralBlock
- rnLeaf '
- let a = 1'
- """)
- # | |
- # | \ indentation of exactly two spaces before 'let a = 1'
- test "no blank line is required before or after Markdown code block":
- let inputBacktick = dedent"""
- Some text
- ```
- CodeBlock()
- ```
- Other text"""
- let inputTilde = dedent"""
- Some text
- ~~~~~~~~~
- CodeBlock()
- ~~~~~~~~~
- Other text"""
- let expected = dedent"""
- rnInner
- rnParagraph
- rnLeaf 'Some'
- rnLeaf ' '
- rnLeaf 'text'
- rnParagraph
- rnCodeBlock
- [nil]
- rnFieldList
- rnField
- rnFieldName
- rnLeaf 'default-language'
- rnFieldBody
- rnLeaf 'Nim'
- rnLiteralBlock
- rnLeaf '
- CodeBlock()'
- rnLeaf ' '
- rnLeaf 'Other'
- rnLeaf ' '
- rnLeaf 'text'
- """
- check inputBacktick.toAst == expected
- check inputTilde.toAst == expected
- test "option list has priority over definition list":
- for opt in [preferMarkdown, preferRst]:
- check(dedent"""
- --defusages
- file
- -o set
- """.toAst(rstOptions = opt) ==
- dedent"""
- rnOptionList
- rnOptionListItem order=1
- rnOptionGroup
- rnLeaf '--'
- rnLeaf 'defusages'
- rnDescription
- rnInner
- rnLeaf 'file'
- rnOptionListItem order=2
- rnOptionGroup
- rnLeaf '-'
- rnLeaf 'o'
- rnDescription
- rnLeaf 'set'
- """)
- test "items of 1 option list can be separated by blank lines":
- check(dedent"""
- -a desc1
- -b desc2
- """.toAst ==
- dedent"""
- rnOptionList
- rnOptionListItem order=1
- rnOptionGroup
- rnLeaf '-'
- rnLeaf 'a'
- rnDescription
- rnLeaf 'desc1'
- rnOptionListItem order=2
- rnOptionGroup
- rnLeaf '-'
- rnLeaf 'b'
- rnDescription
- rnLeaf 'desc2'
- """)
- test "definition list does not gobble up the following blocks":
- check(dedent"""
- defName
- defBody
- -b desc2
- """.toAst(rstOptions = preferRst) ==
- dedent"""
- rnInner
- rnDefList
- rnDefItem
- rnDefName
- rnLeaf 'defName'
- rnDefBody
- rnInner
- rnLeaf 'defBody'
- rnOptionList
- rnOptionListItem order=1
- rnOptionGroup
- rnLeaf '-'
- rnLeaf 'b'
- rnDescription
- rnLeaf 'desc2'
- """)
- test "definition lists work correctly with additional indentation in Markdown":
- check(dedent"""
- Paragraph:
- -c desc1
- -b desc2
- """.toAst() ==
- dedent"""
- rnInner
- rnInner
- rnLeaf 'Paragraph'
- rnLeaf ':'
- rnOptionList
- rnOptionListItem order=1
- rnOptionGroup
- rnLeaf '-'
- rnLeaf 'c'
- rnDescription
- rnLeaf 'desc1'
- rnOptionListItem order=2
- rnOptionGroup
- rnLeaf '-'
- rnLeaf 'b'
- rnDescription
- rnLeaf 'desc2'
- """)
- test "RST comment":
- check(dedent"""
- .. comment1
- comment2
- someParagraph""".toAst ==
- dedent"""
- rnLeaf 'someParagraph'
- """)
- check(dedent"""
- ..
- comment1
- comment2
- someParagraph""".toAst ==
- dedent"""
- rnLeaf 'someParagraph'
- """)
- test "check that additional line right after .. ends comment":
- check(dedent"""
- ..
- notAcomment1
- notAcomment2
- someParagraph""".toAst(rstOptions = preferRst) ==
- dedent"""
- rnInner
- rnBlockQuote
- rnInner
- rnLeaf 'notAcomment1'
- rnLeaf ' '
- rnLeaf 'notAcomment2'
- rnParagraph
- rnLeaf 'someParagraph'
- """)
- test "check that additional line right after .. ends comment (Markdown mode)":
- # in Markdown small indentation does not matter so this should
- # just be split to 2 paragraphs.
- check(dedent"""
- ..
- notAcomment1
- notAcomment2
- someParagraph""".toAst ==
- dedent"""
- rnInner
- rnInner
- rnLeaf 'notAcomment1'
- rnLeaf ' '
- rnLeaf 'notAcomment2'
- rnParagraph
- rnLeaf 'someParagraph'
- """)
- test "but blank lines after 2nd non-empty line don't end the comment":
- check(dedent"""
- ..
- comment1
- comment2
- someParagraph""".toAst ==
- dedent"""
- rnLeaf 'someParagraph'
- """)
- test "using .. as separator b/w directives and block quotes":
- check(dedent"""
- .. note:: someNote
- ..
- someBlockQuote""".toAst(rstOptions = preferRst) ==
- dedent"""
- rnInner
- rnAdmonition adType=note
- [nil]
- [nil]
- rnLeaf 'someNote'
- rnBlockQuote
- rnInner
- rnLeaf 'someBlockQuote'
- """)
- test "no redundant blank lines in literal blocks":
- check(dedent"""
- Check::
- code
- """.toAst(rstOptions = preferRst) ==
- dedent"""
- rnInner
- rnLeaf 'Check'
- rnLeaf ':'
- rnLiteralBlock
- rnLeaf 'code'
- """)
- test "Markdown indented code blocks":
- check(dedent"""
- See
- some code""".toAst ==
- dedent"""
- rnInner
- rnInner
- rnLeaf 'See'
- rnLiteralBlock
- rnLeaf 'some code'
- """)
- # not a code block -- no blank line before:
- check(dedent"""
- See
- some code""".toAst ==
- dedent"""
- rnInner
- rnLeaf 'See'
- rnLeaf ' '
- rnLeaf 'some'
- rnLeaf ' '
- rnLeaf 'code'
- """)
- suite "RST tables":
- test "formatting in tables works":
- check(
- dedent"""
- ========= ===
- `build` `a`
- ========= ===
- """.toAst ==
- dedent"""
- rnTable colCount=2
- rnTableRow
- rnTableDataCell
- rnInlineCode
- rnDirArg
- rnLeaf 'nim'
- [nil]
- rnLiteralBlock
- rnLeaf 'build'
- rnTableDataCell
- rnInlineCode
- rnDirArg
- rnLeaf 'nim'
- [nil]
- rnLiteralBlock
- rnLeaf 'a'
- """)
- test "tables with slightly overflowed cells cause an error (1)":
- var error = new string
- check(
- dedent"""
- ====== ======
- Inputs Output
- ====== ======
- """.toAst(rstOptions = pureRst, error = error) == "")
- check(error[] == "input(2, 2) Error: Illformed table: " &
- "this word crosses table column from the right")
- # In nimforum compatibility mode & Markdown we raise a warning instead:
- let expected = dedent"""
- rnTable colCount=2
- rnTableRow
- rnTableDataCell
- rnLeaf 'Inputs'
- rnTableDataCell
- rnLeaf 'Output'
- """
- for opt in [preferRst, preferMarkdown]:
- var warnings = new seq[string]
- check(
- dedent"""
- ====== ======
- Inputs Output
- ====== ======
- """.toAst(rstOptions = opt, warnings = warnings) == expected)
- check(warnings[] == @[
- "input(2, 2) Warning: RST style: this word crosses table column from the right"])
- test "tables with slightly overflowed cells cause an error (2)":
- var error = new string
- check("" == dedent"""
- ===== ===== ======
- Input Output
- ===== ===== ======
- False False False
- ===== ===== ======
- """.toAst(rstOptions = pureRst, error = error))
- check(error[] == "input(2, 8) Error: Illformed table: " &
- "this word crosses table column from the right")
- test "tables with slightly underflowed cells cause an error":
- var error = new string
- check("" == dedent"""
- ===== ===== ======
- Input Output
- ===== ===== ======
- False False False
- ===== ===== ======
- """.toAst(rstOptions = pureRst, error = error))
- check(error[] == "input(2, 7) Error: Illformed table: " &
- "this word crosses table column from the left")
- test "tables with unequal underlines should be reported (1)":
- var error = new string
- error[] = "none"
- check("" == dedent"""
- ===== ======
- Input Output
- ===== ======
- False False
- ===== =======
- """.toAst(rstOptions = pureRst, error = error))
- check(error[] == "input(5, 14) Error: Illformed table: " &
- "end of table column #2 should end at position 13")
- test "tables with unequal underlines should be reported (2)":
- var error = new string
- check("" == dedent"""
- ===== ======
- Input Output
- ===== =======
- False False
- ===== ======
- """.toAst(rstOptions = pureRst, error = error))
- check(error[] == "input(3, 14) Error: Illformed table: " &
- "end of table column #2 should end at position 13")
- test "tables with empty first cells":
- check(
- dedent"""
- = = =
- x y z
- t
- = = =
- """.toAst ==
- dedent"""
- rnTable colCount=3
- rnTableRow
- rnTableDataCell
- rnLeaf 'x'
- rnTableDataCell
- rnInner
- rnLeaf 'y'
- rnLeaf ' '
- rnTableDataCell
- rnInner
- rnLeaf 'z'
- rnLeaf ' '
- rnLeaf 't'
- """)
- test "tables with spanning cells & separators":
- check(
- dedent"""
- ===== ===== ======
- Inputs Output
- ------------ ------
- A B A or B
- ===== ===== ======
- False False False
- True False True
- ----- ----- ------
- False True True
- True True True
- ===== ===== ======
- """.toAst ==
- dedent"""
- rnTable colCount=3
- rnTableRow
- rnTableHeaderCell span=2
- rnLeaf 'Inputs'
- rnTableHeaderCell span=1
- rnLeaf 'Output'
- rnTableRow endsHeader
- rnTableHeaderCell
- rnLeaf 'A'
- rnTableHeaderCell
- rnLeaf 'B'
- rnTableHeaderCell
- rnInner
- rnLeaf 'A'
- rnLeaf ' '
- rnLeaf 'or'
- rnLeaf ' '
- rnLeaf 'B'
- rnTableRow
- rnTableDataCell
- rnLeaf 'False'
- rnTableDataCell
- rnLeaf 'False'
- rnTableDataCell
- rnLeaf 'False'
- rnTableRow
- rnTableDataCell span=1
- rnLeaf 'True'
- rnTableDataCell span=1
- rnLeaf 'False'
- rnTableDataCell span=1
- rnLeaf 'True'
- rnTableRow
- rnTableDataCell
- rnLeaf 'False'
- rnTableDataCell
- rnLeaf 'True'
- rnTableDataCell
- rnLeaf 'True'
- rnTableRow
- rnTableDataCell
- rnLeaf 'True'
- rnTableDataCell
- rnLeaf 'True'
- rnTableDataCell
- rnLeaf 'True'
- """)
- test "tables with spanning cells with uneqal underlines cause an error":
- var error = new string
- check(
- dedent"""
- ===== ===== ======
- Inputs Output
- ------------- ------
- A B A or B
- ===== ===== ======
- """.toAst(error=error) == "")
- check(error[] == "input(3, 1) Error: Illformed table: " &
- "spanning underline does not match main table columns")
- let expTable = dedent"""
- rnTable colCount=2
- rnTableRow
- rnTableDataCell
- rnLeaf 'Inputs'
- rnTableDataCell
- rnLeaf 'Output'
- """
- test "only tables with `=` columns specs are allowed (1)":
- var warnings = new seq[string]
- check(
- dedent"""
- ------ ------
- Inputs Output
- ------ ------
- """.toAst(warnings=warnings) ==
- expTable)
- check(warnings[] ==
- @["input(1, 1) Warning: RST style: " &
- "only tables with `=` columns specification are allowed",
- "input(3, 1) Warning: RST style: " &
- "only tables with `=` columns specification are allowed"])
- test "only tables with `=` columns specs are allowed (2)":
- var warnings = new seq[string]
- check(
- dedent"""
- ====== ======
- Inputs Output
- ~~~~~~ ~~~~~~
- """.toAst(warnings=warnings) ==
- expTable)
- check(warnings[] ==
- @["input(3, 1) Warning: RST style: "&
- "only tables with `=` columns specification are allowed"])
- suite "RST indentation":
- test "nested bullet lists":
- let input = dedent """
- * - bullet1
- - bullet2
- * - bullet3
- - bullet4
- """
- let output = input.toAst
- check(output == dedent"""
- rnBulletList
- rnBulletItem
- rnBulletList
- rnBulletItem
- rnInner
- rnLeaf 'bullet1'
- rnBulletItem
- rnInner
- rnLeaf 'bullet2'
- rnBulletItem
- rnBulletList
- rnBulletItem
- rnInner
- rnLeaf 'bullet3'
- rnBulletItem
- rnInner
- rnLeaf 'bullet4'
- """)
- test "nested markup blocks":
- let input = dedent"""
- #) .. Hint:: .. Error:: none
- #) .. Warning:: term0
- Definition0
- #) some
- paragraph1
- #) term1
- Definition1
- term2
- Definition2
- """
- check(input.toAst(rstOptions = preferRst) == dedent"""
- rnEnumList labelFmt=1)
- rnEnumItem
- rnAdmonition adType=hint
- [nil]
- [nil]
- rnAdmonition adType=error
- [nil]
- [nil]
- rnLeaf 'none'
- rnEnumItem
- rnAdmonition adType=warning
- [nil]
- [nil]
- rnDefList
- rnDefItem
- rnDefName
- rnLeaf 'term0'
- rnDefBody
- rnInner
- rnLeaf 'Definition0'
- rnEnumItem
- rnInner
- rnLeaf 'some'
- rnLeaf ' '
- rnLeaf 'paragraph1'
- rnEnumItem
- rnDefList
- rnDefItem
- rnDefName
- rnLeaf 'term1'
- rnDefBody
- rnInner
- rnLeaf 'Definition1'
- rnDefItem
- rnDefName
- rnLeaf 'term2'
- rnDefBody
- rnInner
- rnLeaf 'Definition2'
- """)
- test "code-block parsing":
- let input1 = dedent"""
- .. code-block:: nim
- :test: "nim c $1"
- template additive(typ: typedesc) =
- discard
- """
- let input2 = dedent"""
- .. code-block:: nim
- :test: "nim c $1"
- template additive(typ: typedesc) =
- discard
- """
- let input3 = dedent"""
- .. code-block:: nim
- :test: "nim c $1"
- template additive(typ: typedesc) =
- discard
- """
- let inputWrong = dedent"""
- .. code-block:: nim
- :test: "nim c $1"
- template additive(typ: typedesc) =
- discard
- """
- let ast = dedent"""
- rnCodeBlock
- rnDirArg
- rnLeaf 'nim'
- rnFieldList
- rnField
- rnFieldName
- rnLeaf 'test'
- rnFieldBody
- rnInner
- rnLeaf '"'
- rnLeaf 'nim'
- rnLeaf ' '
- rnLeaf 'c'
- rnLeaf ' '
- rnLeaf '$'
- rnLeaf '1'
- rnLeaf '"'
- rnField
- rnFieldName
- rnLeaf 'default-language'
- rnFieldBody
- rnLeaf 'Nim'
- rnLiteralBlock
- rnLeaf 'template additive(typ: typedesc) =
- discard'
- """
- check input1.toAst == ast
- check input2.toAst == ast
- check input3.toAst == ast
- # "template..." should be parsed as a definition list attached to ":test:":
- check inputWrong.toAst != ast
- test "Markdown definition lists work in conjunction with bullet lists":
- check(dedent"""
- * some term
- : the definition
- Paragraph.""".toAst ==
- dedent"""
- rnInner
- rnBulletList
- rnBulletItem
- rnMdDefList
- rnDefItem
- rnDefName
- rnLeaf 'some'
- rnLeaf ' '
- rnLeaf 'term'
- rnDefBody
- rnInner
- rnLeaf 'the'
- rnLeaf ' '
- rnLeaf 'definition'
- rnParagraph
- rnLeaf 'Paragraph'
- rnLeaf '.'
- """)
- test "Markdown definition lists work with blank lines and extra paragraphs":
- check(dedent"""
- Term1
- : Definition1
- Term2 *inline markup*
- : Definition2
- Paragraph2
- Term3
- : * point1
- * point2
- : term3definition2
- """.toAst == dedent"""
- rnMdDefList
- rnDefItem
- rnDefName
- rnLeaf 'Term1'
- rnDefBody
- rnInner
- rnLeaf 'Definition1'
- rnDefItem
- rnDefName
- rnLeaf 'Term2'
- rnLeaf ' '
- rnEmphasis
- rnLeaf 'inline'
- rnLeaf ' '
- rnLeaf 'markup'
- rnDefBody
- rnParagraph
- rnLeaf 'Definition2'
- rnParagraph
- rnLeaf 'Paragraph2'
- rnDefItem
- rnDefName
- rnLeaf 'Term3'
- rnDefBody
- rnBulletList
- rnBulletItem
- rnInner
- rnLeaf 'point1'
- rnBulletItem
- rnInner
- rnLeaf 'point2'
- rnDefBody
- rnInner
- rnLeaf 'term3definition2'
- """)
- suite "Markdown indentation":
- test "Markdown paragraph indentation":
- # Additional spaces (<=3) of indentation does not break the paragraph.
- # TODO: in 2nd case de-indentation causes paragraph to break, this is
- # reasonable but does not seem to conform the Markdown spec.
- check(dedent"""
- Start1
- stop1
- Start2
- stop2
- """.toAst ==
- dedent"""
- rnInner
- rnParagraph
- rnLeaf 'Start1'
- rnLeaf ' '
- rnLeaf 'stop1'
- rnParagraph
- rnLeaf 'Start2'
- rnParagraph
- rnLeaf 'stop2'
- rnLeaf ' '
- """)
- suite "Warnings":
- test "warnings for broken footnotes/links/substitutions":
- let input = dedent"""
- firstParagraph
- footnoteRef [som]_
- link `a broken Link`_
- substitution |undefined subst|
- link short.link_
- lastParagraph
- """
- var warnings = new seq[string]
- let output = input.toAst(rstOptions=preferRst, warnings=warnings)
- check(warnings[] == @[
- "input(3, 14) Warning: broken link 'citation-som'",
- "input(5, 7) Warning: broken link 'a broken Link'",
- "input(7, 15) Warning: unknown substitution 'undefined subst'",
- "input(9, 6) Warning: broken link 'short.link'"
- ])
- test "Pandoc Markdown concise link warning points to target":
- var warnings = new seq[string]
- check(
- "ref [here][target]".toAst(warnings=warnings) ==
- dedent"""
- rnInner
- rnLeaf 'ref'
- rnLeaf ' '
- rnPandocRef
- rnInner
- rnLeaf 'here'
- rnInner
- rnLeaf 'target'
- """)
- check warnings[] == @["input(1, 12) Warning: broken link 'target'"]
- test "With include directive and blank lines at the beginning":
- "other.rst".writeFile(dedent"""
- firstParagraph
- here brokenLink_""")
- let input = ".. include:: other.rst"
- var warnings = new seq[string]
- let output = input.toAst(warnings=warnings)
- check warnings[] == @["other.rst(5, 6) Warning: broken link 'brokenLink'"]
- check(output == dedent"""
- rnInner
- rnParagraph
- rnLeaf 'firstParagraph'
- rnParagraph
- rnLeaf 'here'
- rnLeaf ' '
- rnRstRef
- rnLeaf 'brokenLink'
- """)
- removeFile("other.rst")
- test "warnings for ambiguous links (references + anchors)":
- # Reference like `x`_ generates a link alias x that may clash with others
- let input = dedent"""
- Manual reference: `foo <#foo,string,string>`_
- .. _foo:
- Paragraph.
- Ref foo_
- """
- var warnings = new seq[string]
- let output = input.toAst(warnings=warnings)
- check(warnings[] == @[
- dedent """
- input(7, 5) Warning: ambiguous doc link `foo`
- clash:
- (3, 8): (manual directive anchor)
- (1, 45): (implicitly-generated hyperlink alias)"""
- ])
- # reference should be resolved to the manually set anchor:
- check(output ==
- dedent"""
- rnInner
- rnParagraph
- rnLeaf 'Manual'
- rnLeaf ' '
- rnLeaf 'reference'
- rnLeaf ':'
- rnLeaf ' '
- rnHyperlink
- rnInner
- rnLeaf 'foo'
- rnInner
- rnLeaf '#foo,string,string'
- rnParagraph anchor='foo'
- rnLeaf 'Paragraph'
- rnLeaf '.'
- rnParagraph
- rnLeaf 'Ref'
- rnLeaf ' '
- rnInternalRef
- rnInner
- rnLeaf 'foo'
- rnLeaf 'foo'
- rnLeaf ' '
- """)
- suite "RST include directive":
- test "Include whole":
- "other.rst".writeFile("**test1**")
- let input = ".. include:: other.rst"
- doAssert "<strong>test1</strong>" == rstToHtml(input, {roSandboxDisabled}, defaultConfig())
- removeFile("other.rst")
- test "Include starting from":
- "other.rst".writeFile("""
- And this should **NOT** be visible in `docs.html`
- OtherStart
- *Visible*
- """)
- let input = """
- .. include:: other.rst
- :start-after: OtherStart
- """
- check "<em>Visible</em>" == rstToHtml(input, {roSandboxDisabled}, defaultConfig())
- removeFile("other.rst")
- test "Include everything before":
- "other.rst".writeFile("""
- *Visible*
- OtherEnd
- And this should **NOT** be visible in `docs.html`
- """)
- let input = """
- .. include:: other.rst
- :end-before: OtherEnd
- """
- doAssert "<em>Visible</em>" == rstToHtml(input, {roSandboxDisabled}, defaultConfig())
- removeFile("other.rst")
- test "Include everything between":
- "other.rst".writeFile("""
- And this should **NOT** be visible in `docs.html`
- OtherStart
- *Visible*
- OtherEnd
- And this should **NOT** be visible in `docs.html`
- """)
- let input = """
- .. include:: other.rst
- :start-after: OtherStart
- :end-before: OtherEnd
- """
- check "<em>Visible</em>" == rstToHtml(input, {roSandboxDisabled}, defaultConfig())
- removeFile("other.rst")
- test "Ignore premature ending string":
- "other.rst".writeFile("""
- OtherEnd
- And this should **NOT** be visible in `docs.html`
- OtherStart
- *Visible*
- OtherEnd
- And this should **NOT** be visible in `docs.html`
- """)
- let input = """
- .. include:: other.rst
- :start-after: OtherStart
- :end-before: OtherEnd
- """
- doAssert "<em>Visible</em>" == rstToHtml(input, {roSandboxDisabled}, defaultConfig())
- removeFile("other.rst")
- suite "RST escaping":
- test "backspaces":
- check("""\ this""".toAst == dedent"""
- rnLeaf 'this'
- """)
- check("""\\ this""".toAst == dedent"""
- rnInner
- rnLeaf '\'
- rnLeaf ' '
- rnLeaf 'this'
- """)
- check("""\\\ this""".toAst == dedent"""
- rnInner
- rnLeaf '\'
- rnLeaf 'this'
- """)
- check("""\\\\ this""".toAst == dedent"""
- rnInner
- rnLeaf '\'
- rnLeaf '\'
- rnLeaf ' '
- rnLeaf 'this'
- """)
- suite "RST inline markup":
- test "* and ** surrounded by spaces are not inline markup":
- check("a * b * c ** d ** e".toAst == dedent"""
- rnInner
- rnLeaf 'a'
- rnLeaf ' '
- rnLeaf '*'
- rnLeaf ' '
- rnLeaf 'b'
- rnLeaf ' '
- rnLeaf '*'
- rnLeaf ' '
- rnLeaf 'c'
- rnLeaf ' '
- rnLeaf '**'
- rnLeaf ' '
- rnLeaf 'd'
- rnLeaf ' '
- rnLeaf '**'
- rnLeaf ' '
- rnLeaf 'e'
- """)
- test "end-string has repeating symbols":
- check("*emphasis content****".toAst == dedent"""
- rnEmphasis
- rnLeaf 'emphasis'
- rnLeaf ' '
- rnLeaf 'content'
- rnLeaf '***'
- """)
- check("""*emphasis content\****""".toAst == dedent"""
- rnEmphasis
- rnLeaf 'emphasis'
- rnLeaf ' '
- rnLeaf 'content'
- rnLeaf '*'
- rnLeaf '**'
- """) # exact configuration of leafs with * is not really essential,
- # only total number of * is essential
- check("**strong content****".toAst == dedent"""
- rnStrongEmphasis
- rnLeaf 'strong'
- rnLeaf ' '
- rnLeaf 'content'
- rnLeaf '**'
- """)
- check("""**strong content*\****""".toAst == dedent"""
- rnStrongEmphasis
- rnLeaf 'strong'
- rnLeaf ' '
- rnLeaf 'content'
- rnLeaf '*'
- rnLeaf '*'
- rnLeaf '*'
- """)
- check("``lit content`````".toAst == dedent"""
- rnInlineLiteral
- rnLeaf 'lit'
- rnLeaf ' '
- rnLeaf 'content'
- rnLeaf '```'
- """)
- test "interpreted text parsing: code fragments":
- check(dedent"""
- .. default-role:: option
- `--gc:refc`""".toAst ==
- dedent"""
- rnInner
- rnDefaultRole
- rnDirArg
- rnLeaf 'option'
- [nil]
- [nil]
- rnParagraph
- rnCodeFragment
- rnInner
- rnLeaf '--'
- rnLeaf 'gc'
- rnLeaf ':'
- rnLeaf 'refc'
- rnLeaf 'option'
- """)
- test """interpreted text can be ended with \` """:
- let output = (".. default-role:: literal\n" & """`\``""").toAst
- check(output.endsWith """
- rnParagraph
- rnInlineLiteral
- rnLeaf '`'""" & "\n")
- let output2 = """`\``""".toAst
- check(output2 == dedent"""
- rnInlineCode
- rnDirArg
- rnLeaf 'nim'
- [nil]
- rnLiteralBlock
- rnLeaf '`'
- """)
- let output3 = """`proc \`+\``""".toAst
- check(output3 == dedent"""
- rnInlineCode
- rnDirArg
- rnLeaf 'nim'
- [nil]
- rnLiteralBlock
- rnLeaf 'proc `+`'
- """)
- check("""`\\`""".toAst ==
- dedent"""
- rnInlineCode
- rnDirArg
- rnLeaf 'nim'
- [nil]
- rnLiteralBlock
- rnLeaf '\\'
- """)
- test "Markdown-style code/backtick":
- # no whitespace is required before `
- check("`try`...`except`".toAst ==
- dedent"""
- rnInner
- rnInlineCode
- rnDirArg
- rnLeaf 'nim'
- [nil]
- rnLiteralBlock
- rnLeaf 'try'
- rnLeaf '...'
- rnInlineCode
- rnDirArg
- rnLeaf 'nim'
- [nil]
- rnLiteralBlock
- rnLeaf 'except'
- """)
- test """inline literals can contain \ anywhere""":
- check("""``\``""".toAst == dedent"""
- rnInlineLiteral
- rnLeaf '\'
- """)
- check("""``\\``""".toAst == dedent"""
- rnInlineLiteral
- rnLeaf '\'
- rnLeaf '\'
- """)
- check("""``\```""".toAst == dedent"""
- rnInlineLiteral
- rnLeaf '\'
- rnLeaf '`'
- """)
- check("""``\\```""".toAst == dedent"""
- rnInlineLiteral
- rnLeaf '\'
- rnLeaf '\'
- rnLeaf '`'
- """)
- check("""``\````""".toAst == dedent"""
- rnInlineLiteral
- rnLeaf '\'
- rnLeaf '`'
- rnLeaf '`'
- """)
- test "references with _ at the end":
- check(dedent"""
- .. _lnk: https
- lnk_""".toAst ==
- dedent"""
- rnHyperlink
- rnInner
- rnLeaf 'lnk'
- rnInner
- rnLeaf 'https'
- """)
- test "not a hyper link":
- check(dedent"""
- .. _lnk: https
- lnk___""".toAst ==
- dedent"""
- rnInner
- rnLeaf 'lnk'
- rnLeaf '___'
- """)
- test "no punctuation in the end of a standalone URI is allowed":
- check(dedent"""
- [see (http://no.org)], end""".toAst(rstOptions = preferRst) ==
- dedent"""
- rnInner
- rnLeaf '['
- rnLeaf 'see'
- rnLeaf ' '
- rnLeaf '('
- rnStandaloneHyperlink
- rnLeaf 'http://no.org'
- rnLeaf ')'
- rnLeaf ']'
- rnLeaf ','
- rnLeaf ' '
- rnLeaf 'end'
- """)
- # but `/` at the end is OK
- check(
- dedent"""
- See http://no.org/ end""".toAst ==
- dedent"""
- rnInner
- rnLeaf 'See'
- rnLeaf ' '
- rnStandaloneHyperlink
- rnLeaf 'http://no.org/'
- rnLeaf ' '
- rnLeaf 'end'
- """)
- # a more complex URL with some made-up ending '&='.
- # Github Markdown would include final &= and
- # so would rst2html.py in contradiction with RST spec.
- check(
- dedent"""
- See https://www.google.com/url?sa=t&source=web&cd=&cad=rja&url=https%3A%2F%2Fnim-lang.github.io%2FNim%2Frst.html%23features&usg=AO&= end""".toAst ==
- dedent"""
- rnInner
- rnLeaf 'See'
- rnLeaf ' '
- rnStandaloneHyperlink
- rnLeaf 'https://www.google.com/url?sa=t&source=web&cd=&cad=rja&url=https%3A%2F%2Fnim-lang.github.io%2FNim%2Frst.html%23features&usg=AO'
- rnLeaf '&'
- rnLeaf '='
- rnLeaf ' '
- rnLeaf 'end'
- """)
- test "Markdown-style link can be split to a few lines":
- check(dedent"""
- is [term-rewriting
- macros](manual.html#term-rewriting-macros)""".toAst ==
- dedent"""
- rnInner
- rnLeaf 'is'
- rnLeaf ' '
- rnHyperlink
- rnLeaf 'term-rewriting macros'
- rnLeaf 'manual.html#term-rewriting-macros'
- """)
- test "URL with balanced parentheses (Markdown rule)":
- # 2 balanced parens, 1 unbalanced:
- check(dedent"""
- https://en.wikipedia.org/wiki/APL_((programming_language)))""".toAst ==
- dedent"""
- rnInner
- rnStandaloneHyperlink
- rnLeaf 'https://en.wikipedia.org/wiki/APL_((programming_language))'
- rnLeaf ')'
- """)
- # the same for Markdown-style link:
- check(dedent"""
- [foo [bar]](https://en.wikipedia.org/wiki/APL_((programming_language))))""".toAst ==
- dedent"""
- rnInner
- rnHyperlink
- rnLeaf 'foo [bar]'
- rnLeaf 'https://en.wikipedia.org/wiki/APL_((programming_language))'
- rnLeaf ')'
- """)
- # unbalanced (here behavior is more RST-like actually):
- check(dedent"""
- https://en.wikipedia.org/wiki/APL_(programming_language(""".toAst ==
- dedent"""
- rnInner
- rnStandaloneHyperlink
- rnLeaf 'https://en.wikipedia.org/wiki/APL_(programming_language'
- rnLeaf '('
- """)
- # unbalanced [, but still acceptable:
- check(dedent"""
- [my {link example](http://example.com/bracket_(symbol_[))""".toAst ==
- dedent"""
- rnHyperlink
- rnLeaf 'my {link example'
- rnLeaf 'http://example.com/bracket_(symbol_[)'
- """)
- test "not a Markdown link":
- # bug #17340 (27) `f` will be considered as a protocol and blocked as unsafe
- var warnings = new seq[string]
- check("[T](f: var Foo)".toAst(warnings = warnings) ==
- dedent"""
- rnInner
- rnLeaf '['
- rnLeaf 'T'
- rnLeaf ']'
- rnLeaf '('
- rnLeaf 'f'
- rnLeaf ':'
- rnLeaf ' '
- rnLeaf 'var'
- rnLeaf ' '
- rnLeaf 'Foo'
- rnLeaf ')'
- """)
- check(warnings[] == @["input(1, 5) Warning: broken link 'f'"])
|