├── Tests ├── Input │ ├── paragraph_empty │ ├── bulletlist_single │ ├── paragraph_single │ ├── paragraph_multiple │ ├── paragraph_single_newline │ ├── inlinemarkupemphasis_simple │ ├── inlinemarkupliteral_simple │ ├── lineblock_simple │ ├── bulletlist_multiple │ ├── definitionlist_simple │ ├── inlinemarkupliteral_backslash │ ├── inlinemarkupliteral_backslash_end │ ├── section_empty │ ├── section_short │ ├── inlinemarkupinterpretedtext_simple │ ├── inlinemarkupliteral_backslash_inside │ ├── paragraph_multiline │ ├── bulletlist_emptyitemabove │ ├── comment_doublecolons │ ├── inlinemarkupinterpretedtext_multiple │ ├── inlinemarkupinterpretedtext_titled │ ├── paragraph_simple │ ├── section_paragraph │ ├── blockquote_simple │ ├── comment_bulletlist_trailing │ ├── comment_commentandparagraph │ ├── comment_directive │ ├── enumeratedlist_empty │ ├── literalblock_quoted │ ├── section_paragraph_noblankline │ ├── bulletlist_beginwithnewline │ ├── comment_multiple │ ├── definitionlist_paragraph │ ├── literalblock_minimized │ ├── literalblock_partial │ ├── paragraph_multiplesinglelines │ ├── inlinemarkupemphasis_crossline │ ├── section_overline │ ├── comment_citation │ ├── literalblock_expanded │ ├── section_numbered │ ├── comment_substitution │ ├── comment_twolinescommentandparagraph │ ├── definitionlist_two │ ├── enumeratedlist_simple │ ├── inlinemarkupliteral_apostrophe │ ├── inlinemarkupliteral_endswithbackslash │ ├── literalblock_quoted_twoblanklines │ ├── section_paragraph_surrounded │ ├── bulletlist_multilinebody │ ├── bulletlist_multiple_noblankline │ ├── comment_hyperlinktarget │ ├── inlinemarkupliteral_interpretedtext │ ├── inlinemarkupstrongemphasis_apostrophe │ ├── literalblock_quoted_multiline │ ├── section_overline_inset │ ├── blockquote_nested │ ├── bulletlist_multilinebody_noblankline │ ├── lineblock_indentation │ ├── section_blockquote │ ├── definitionlist_classifier_multiple │ ├── literalblock_multiline │ ├── inlinemarkupemphasis_asterisk │ ├── inlinemarkupemphasis_quotes │ ├── inlinemarkupstrongemphasis_asterisk │ ├── inlinemarkupstrongemphasis_notstrong │ ├── comment_definitionlist │ ├── literalblock_minimized_space │ ├── definitionlist_classifier_multiple_inlinemarkup │ ├── definitionlist_two_noblankline │ ├── comment_definitionlist_comment │ ├── definitionlist_classifier_literal │ ├── enumeratedlist_noblanklines │ ├── literalblock_wonky │ ├── bulletlist_differentmarker │ ├── paragraph_multilines │ ├── section_inlinemarkup │ ├── blockquote_attribution_simple2 │ ├── inlinemarkupemphasis_multiple │ ├── definitionlist_classifier │ ├── bulletlist_unicode │ ├── comment_bulletlist_comment │ ├── comment_multiplelines │ ├── inlinemarkupliteral_quoted │ ├── inlinemarkupstrongemphasis_quoted │ ├── lineblock_multiple │ ├── comment_bulletlist │ ├── blockquote_attribution_simple │ ├── full_linestart │ ├── inlinemarkupliteral_quote │ ├── blockquote_attribution │ ├── enumeratedlist_scrambled │ ├── full_linenumbers │ ├── blockquote_comment │ ├── comment_followedbyempty │ ├── enumeratedlist_multiplebody │ ├── definitionlist_nested │ ├── enumeratedlist_nonordinal │ ├── section_nested │ ├── blockquote_attribution_emdash │ ├── literalblock_two │ ├── blockquote_nested2 │ ├── section_nested_overline_level3 │ ├── blockquote_attribution_complicated │ ├── definitionlist_classifier_without │ ├── blockquote_attribution_multiline │ ├── section_shorts │ ├── blockquote_definitionlist │ ├── enumeratedlist_different │ ├── section_nested_overline │ └── inlinemarkupemphasis_punctuation ├── xunit.runner.json ├── TestUtils.cs ├── Tests.csproj ├── LineBlockTest.cs ├── RealTest.cs ├── InlineMarkupInterpretedTextTest.cs ├── InlineMarkupStrongEmphasisTest.cs ├── ParagraphTest.cs ├── BulletListTest.cs ├── FullTest.cs ├── EnumeratedListTest.cs ├── LiteralBlockTest.cs ├── InlineMarkupLiteralTest.cs └── InlineMarkupEmphasisTest.cs ├── dist.server.bat ├── dist.server.sh ├── ReStructuredText ├── Scope.cs ├── ITextArea.cs ├── Term.cs ├── Definition.cs ├── Literal.cs ├── Classifier.cs ├── InterpretedText.cs ├── Emphasis.cs ├── IParent.cs ├── Strong.cs ├── IElement.cs ├── Attribution.cs ├── Line.cs ├── ReStructuredText.csproj ├── ElementType.cs ├── Properties │ └── AssemblyInfo.cs ├── DefinitionList.cs ├── Comment.cs ├── BulletList.cs ├── LineBlock.cs ├── LiteralBlock.cs ├── EnumeratedList.cs ├── TextArea.cs ├── BackTickText.cs ├── ListItem.cs ├── Content.cs ├── Section.cs ├── BlockQuote.cs ├── Paragraph.cs ├── DefinitionListItem.cs ├── Document.cs └── ReStructuredText.g4 ├── Server ├── Services │ ├── LanguageServiceBase.cs │ ├── CompletionItemService.cs │ ├── WorkspaceService.cs │ ├── InitializaionService.cs │ └── TextDocumentService.cs ├── Utility.cs ├── Settings.cs ├── Properties │ └── AssemblyInfo.cs ├── Server.csproj ├── SphinxProject.cs ├── DiagnosticProvider.cs └── Program.cs ├── dist.server.ps1 ├── LICENSE ├── readme.md ├── azure-pipelines.yml ├── ReStructuredText.sln ├── .gitattributes └── .gitignore /Tests/Input/paragraph_empty: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Tests/Input/bulletlist_single: -------------------------------------------------------------------------------- 1 | 2 | - item 3 | -------------------------------------------------------------------------------- /Tests/Input/paragraph_single: -------------------------------------------------------------------------------- 1 | 2 | A paragraph. -------------------------------------------------------------------------------- /dist.server.bat: -------------------------------------------------------------------------------- 1 | powershell -file dist.server.ps1 -------------------------------------------------------------------------------- /Tests/Input/paragraph_multiple: -------------------------------------------------------------------------------- 1 | 2 | A paragraph. 3 | -------------------------------------------------------------------------------- /Tests/Input/paragraph_single_newline: -------------------------------------------------------------------------------- 1 | 2 | A paragraph. 3 | -------------------------------------------------------------------------------- /Tests/Input/inlinemarkupemphasis_simple: -------------------------------------------------------------------------------- 1 | 2 | *emphasis* 3 | -------------------------------------------------------------------------------- /Tests/Input/inlinemarkupliteral_simple: -------------------------------------------------------------------------------- 1 | 2 | ``literal`` 3 | -------------------------------------------------------------------------------- /Tests/Input/lineblock_simple: -------------------------------------------------------------------------------- 1 | 2 | | This is a line block. 3 | -------------------------------------------------------------------------------- /Tests/Input/bulletlist_multiple: -------------------------------------------------------------------------------- 1 | 2 | * item 1 3 | 4 | * item 2 5 | -------------------------------------------------------------------------------- /Tests/Input/definitionlist_simple: -------------------------------------------------------------------------------- 1 | 2 | term 3 | definition 4 | -------------------------------------------------------------------------------- /Tests/Input/inlinemarkupliteral_backslash: -------------------------------------------------------------------------------- 1 | 2 | ``\\literal`` 3 | -------------------------------------------------------------------------------- /Tests/Input/inlinemarkupliteral_backslash_end: -------------------------------------------------------------------------------- 1 | 2 | ``literal\\`` 3 | -------------------------------------------------------------------------------- /Tests/Input/section_empty: -------------------------------------------------------------------------------- 1 | 2 | Empty Section 3 | ============= 4 | -------------------------------------------------------------------------------- /Tests/Input/section_short: -------------------------------------------------------------------------------- 1 | 2 | ABC 3 | === 4 | 5 | Short title. 6 | -------------------------------------------------------------------------------- /dist.server.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | pwsh -file dist.server.ps1 4 | -------------------------------------------------------------------------------- /Tests/Input/inlinemarkupinterpretedtext_simple: -------------------------------------------------------------------------------- 1 | 2 | `interpreted` 3 | -------------------------------------------------------------------------------- /Tests/Input/inlinemarkupliteral_backslash_inside: -------------------------------------------------------------------------------- 1 | 2 | ``lite\\ral`` 3 | -------------------------------------------------------------------------------- /Tests/Input/paragraph_multiline: -------------------------------------------------------------------------------- 1 | 2 | Line 1. 3 | Line 2. 4 | Line 3. 5 | -------------------------------------------------------------------------------- /Tests/Input/bulletlist_emptyitemabove: -------------------------------------------------------------------------------- 1 | 2 | - 3 | 4 | empty item above 5 | -------------------------------------------------------------------------------- /Tests/Input/comment_doublecolons: -------------------------------------------------------------------------------- 1 | 2 | .. A comment:: 3 | 4 | Paragraph. 5 | -------------------------------------------------------------------------------- /Tests/Input/inlinemarkupinterpretedtext_multiple: -------------------------------------------------------------------------------- 1 | 2 | `foo` :x:`bar` :x:y 3 | -------------------------------------------------------------------------------- /Tests/Input/inlinemarkupinterpretedtext_titled: -------------------------------------------------------------------------------- 1 | 2 | :title:`interpreted` 3 | -------------------------------------------------------------------------------- /Tests/Input/paragraph_simple: -------------------------------------------------------------------------------- 1 | 2 | A. Einstein was a really 3 | smart dude. 4 | -------------------------------------------------------------------------------- /Tests/Input/section_paragraph: -------------------------------------------------------------------------------- 1 | 2 | Title 3 | ===== 4 | 5 | Paragraph. 6 | -------------------------------------------------------------------------------- /Tests/Input/blockquote_simple: -------------------------------------------------------------------------------- 1 | 2 | Line 1. 3 | Line 2. 4 | 5 | Indented. 6 | -------------------------------------------------------------------------------- /Tests/Input/comment_bulletlist_trailing: -------------------------------------------------------------------------------- 1 | 2 | + bullet 3 | .. trailing comment 4 | -------------------------------------------------------------------------------- /Tests/Input/comment_commentandparagraph: -------------------------------------------------------------------------------- 1 | 2 | .. A comment 3 | 4 | Paragraph. 5 | -------------------------------------------------------------------------------- /Tests/Input/comment_directive: -------------------------------------------------------------------------------- 1 | 2 | .. 3 | A comment:: 4 | 5 | Paragraph. 6 | -------------------------------------------------------------------------------- /Tests/Input/enumeratedlist_empty: -------------------------------------------------------------------------------- 1 | 2 | 1. 3 | empty item above, no blank line 4 | -------------------------------------------------------------------------------- /Tests/Input/literalblock_quoted: -------------------------------------------------------------------------------- 1 | 2 | A paragraph:: 3 | 4 | > A literal block. 5 | -------------------------------------------------------------------------------- /Tests/Input/section_paragraph_noblankline: -------------------------------------------------------------------------------- 1 | 2 | Title 3 | ===== 4 | Paragraph. 5 | -------------------------------------------------------------------------------- /Tests/Input/bulletlist_beginwithnewline: -------------------------------------------------------------------------------- 1 | 2 | - 3 | 1 4 | - 5 | 2 6 | - 7 | 3 8 | -------------------------------------------------------------------------------- /Tests/Input/comment_multiple: -------------------------------------------------------------------------------- 1 | 2 | .. A comment. 3 | .. Another. 4 | 5 | Paragraph. 6 | -------------------------------------------------------------------------------- /Tests/Input/definitionlist_paragraph: -------------------------------------------------------------------------------- 1 | 2 | term 3 | definition 4 | 5 | paragraph 6 | -------------------------------------------------------------------------------- /Tests/Input/literalblock_minimized: -------------------------------------------------------------------------------- 1 | 2 | A paragraph:: 3 | 4 | A literal block. 5 | -------------------------------------------------------------------------------- /Tests/Input/literalblock_partial: -------------------------------------------------------------------------------- 1 | 2 | A paragraph: :: 3 | 4 | A literal block. 5 | -------------------------------------------------------------------------------- /Tests/Input/paragraph_multiplesinglelines: -------------------------------------------------------------------------------- 1 | 2 | Paragraph 1. 3 | 4 | Paragraph 2. 5 | -------------------------------------------------------------------------------- /Tests/Input/inlinemarkupemphasis_crossline: -------------------------------------------------------------------------------- 1 | 2 | *emphasized sentence 3 | across lines* 4 | -------------------------------------------------------------------------------- /Tests/Input/section_overline: -------------------------------------------------------------------------------- 1 | 2 | ===== 3 | Title 4 | ===== 5 | 6 | Test overline title. 7 | -------------------------------------------------------------------------------- /Tests/Input/comment_citation: -------------------------------------------------------------------------------- 1 | 2 | .. 3 | [comment] Not a citation. 4 | 5 | Paragraph. 6 | -------------------------------------------------------------------------------- /Tests/Input/literalblock_expanded: -------------------------------------------------------------------------------- 1 | 2 | A paragraph: 3 | 4 | :: 5 | 6 | A literal block. 7 | -------------------------------------------------------------------------------- /Tests/Input/section_numbered: -------------------------------------------------------------------------------- 1 | 2 | 1. Numbered Title 3 | ================= 4 | 5 | Paragraph. 6 | -------------------------------------------------------------------------------- /Tests/Input/comment_substitution: -------------------------------------------------------------------------------- 1 | 2 | .. 3 | |comment| image:: bogus.png 4 | 5 | Paragraph. 6 | -------------------------------------------------------------------------------- /Tests/Input/comment_twolinescommentandparagraph: -------------------------------------------------------------------------------- 1 | 2 | .. A comment 3 | block. 4 | 5 | Paragraph. 6 | -------------------------------------------------------------------------------- /Tests/Input/definitionlist_two: -------------------------------------------------------------------------------- 1 | 2 | term 1 3 | definition 1 4 | 5 | term 2 6 | definition 2 7 | -------------------------------------------------------------------------------- /Tests/Input/enumeratedlist_simple: -------------------------------------------------------------------------------- 1 | 2 | 1. Item one. 3 | 4 | 2. Item two. 5 | 6 | 3. Item three. 7 | -------------------------------------------------------------------------------- /Tests/Input/inlinemarkupliteral_apostrophe: -------------------------------------------------------------------------------- 1 | 2 | l'``literal`` and l’``literal`` with apostrophe 3 | -------------------------------------------------------------------------------- /Tests/Input/inlinemarkupliteral_endswithbackslash: -------------------------------------------------------------------------------- 1 | 2 | Python ``list``\s use square bracket syntax. 3 | -------------------------------------------------------------------------------- /Tests/Input/literalblock_quoted_twoblanklines: -------------------------------------------------------------------------------- 1 | 2 | A paragraph:: 3 | 4 | 5 | > A literal block. 6 | -------------------------------------------------------------------------------- /Tests/Input/section_paragraph_surrounded: -------------------------------------------------------------------------------- 1 | 2 | Paragraph. 3 | 4 | Title 5 | ===== 6 | Paragraph. 7 | -------------------------------------------------------------------------------- /Tests/Input/bulletlist_multilinebody: -------------------------------------------------------------------------------- 1 | 2 | - item 1, para 1. 3 | 4 | item 1, para 2. 5 | 6 | - item 2 7 | -------------------------------------------------------------------------------- /Tests/Input/bulletlist_multiple_noblankline: -------------------------------------------------------------------------------- 1 | 2 | No blank line between: 3 | 4 | + item 1 5 | + item 2 6 | -------------------------------------------------------------------------------- /Tests/Input/comment_hyperlinktarget: -------------------------------------------------------------------------------- 1 | 2 | .. 3 | _comment: http://example.org 4 | 5 | Paragraph. 6 | -------------------------------------------------------------------------------- /Tests/Input/inlinemarkupliteral_interpretedtext: -------------------------------------------------------------------------------- 1 | 2 | Find the ```interpreted text``` in this paragraph! 3 | -------------------------------------------------------------------------------- /Tests/Input/inlinemarkupstrongemphasis_apostrophe: -------------------------------------------------------------------------------- 1 | 2 | l'**strong** and l’**literal** with apostrophe 3 | -------------------------------------------------------------------------------- /Tests/Input/literalblock_quoted_multiline: -------------------------------------------------------------------------------- 1 | 2 | A paragraph:: 3 | 4 | > A literal block. 5 | > Line 2. 6 | -------------------------------------------------------------------------------- /Tests/Input/section_overline_inset: -------------------------------------------------------------------------------- 1 | 2 | ======= 3 | Title 4 | ======= 5 | 6 | Test overline title. 7 | -------------------------------------------------------------------------------- /Tests/Input/blockquote_nested: -------------------------------------------------------------------------------- 1 | 2 | Line 1. 3 | Line 2. 4 | 5 | Indented 1. 6 | 7 | Indented 2. 8 | -------------------------------------------------------------------------------- /Tests/Input/bulletlist_multilinebody_noblankline: -------------------------------------------------------------------------------- 1 | 2 | - item 1, para 1. 3 | item 1, para 2. 4 | - item 2 5 | -------------------------------------------------------------------------------- /Tests/Input/lineblock_indentation: -------------------------------------------------------------------------------- 1 | 2 | | In line blocks, 3 | | Initial indentation is *also* preserved. 4 | -------------------------------------------------------------------------------- /Tests/Input/section_blockquote: -------------------------------------------------------------------------------- 1 | 2 | Paragraph 3 | 4 | ABC 5 | == 6 | 7 | Underline too short. 8 | -------------------------------------------------------------------------------- /Tests/Input/definitionlist_classifier_multiple: -------------------------------------------------------------------------------- 1 | 2 | Term : classifier one : classifier two 3 | Definition 4 | -------------------------------------------------------------------------------- /Tests/Input/literalblock_multiline: -------------------------------------------------------------------------------- 1 | 2 | A paragraph 3 | on more than 4 | one line:: 5 | 6 | A literal block. 7 | -------------------------------------------------------------------------------- /Tests/Input/inlinemarkupemphasis_asterisk: -------------------------------------------------------------------------------- 1 | 2 | Emphasized asterisk: *\** 3 | 4 | Emphasized double asterisk: *\*** 5 | -------------------------------------------------------------------------------- /Tests/Input/inlinemarkupemphasis_quotes: -------------------------------------------------------------------------------- 1 | 2 | Quotes around inline markup: 3 | 4 | '*emphasis*' "*emphasis*" Straight, 5 | -------------------------------------------------------------------------------- /Tests/Input/inlinemarkupstrongemphasis_asterisk: -------------------------------------------------------------------------------- 1 | 2 | Strong asterisk: ***** 3 | 4 | Strong double asterisk: ****** 5 | -------------------------------------------------------------------------------- /Tests/Input/inlinemarkupstrongemphasis_notstrong: -------------------------------------------------------------------------------- 1 | 2 | (**strong**) but not (**) or '(** ' or x**2 or \**kwargs or ** 3 | -------------------------------------------------------------------------------- /Tests/Input/comment_definitionlist: -------------------------------------------------------------------------------- 1 | 2 | term 1 3 | definition 1 4 | 5 | .. a comment 6 | 7 | term 2 8 | definition 2 9 | -------------------------------------------------------------------------------- /Tests/Input/literalblock_minimized_space: -------------------------------------------------------------------------------- 1 | 2 | A paragraph with a space after the colons:: 3 | 4 | A literal block. 5 | -------------------------------------------------------------------------------- /Tests/Input/definitionlist_classifier_multiple_inlinemarkup: -------------------------------------------------------------------------------- 1 | 2 | Term : **classifier one** : classifier two 3 | Definition 4 | -------------------------------------------------------------------------------- /Tests/Input/definitionlist_two_noblankline: -------------------------------------------------------------------------------- 1 | 2 | term 1 3 | definition 1 (no blank line below) 4 | term 2 5 | definition 2 6 | -------------------------------------------------------------------------------- /Tests/xunit.runner.json: -------------------------------------------------------------------------------- 1 | { 2 | "shadowCopy": false, 3 | "parallelizeTestCollections": false, 4 | "maxParallelThreads": 1 5 | } -------------------------------------------------------------------------------- /Tests/Input/comment_definitionlist_comment: -------------------------------------------------------------------------------- 1 | 2 | term 1 3 | definition 1 4 | 5 | .. a comment 6 | 7 | term 2 8 | definition 2 9 | -------------------------------------------------------------------------------- /Tests/Input/definitionlist_classifier_literal: -------------------------------------------------------------------------------- 1 | 2 | ``Term : not a classifier`` 3 | Because the ' : ' is inside an inline literal. 4 | -------------------------------------------------------------------------------- /Tests/Input/enumeratedlist_noblanklines: -------------------------------------------------------------------------------- 1 | 2 | No blank lines between items: 3 | 4 | 1. Item one. 5 | 2. Item two. 6 | 3. Item three. 7 | -------------------------------------------------------------------------------- /Tests/Input/literalblock_wonky: -------------------------------------------------------------------------------- 1 | 2 | A paragraph:: 3 | 4 | A wonky literal block. 5 | Literal line 2. 6 | Literal line 3. 7 | -------------------------------------------------------------------------------- /Tests/Input/bulletlist_differentmarker: -------------------------------------------------------------------------------- 1 | 2 | Different bullets: 3 | 4 | - item 1 5 | 6 | + item 2 7 | 8 | * item 3 9 | - item 4 10 | -------------------------------------------------------------------------------- /Tests/Input/paragraph_multilines: -------------------------------------------------------------------------------- 1 | 2 | Paragraph 1, Line 1. 3 | Line 2. 4 | Line 3. 5 | 6 | Paragraph 2, Line 1. 7 | Line 2. 8 | Line 3. 9 | -------------------------------------------------------------------------------- /Tests/Input/section_inlinemarkup: -------------------------------------------------------------------------------- 1 | 2 | Title containing *inline* **markup** 3 | ==================================== 4 | 5 | Paragraph. 6 | -------------------------------------------------------------------------------- /Tests/Input/blockquote_attribution_simple2: -------------------------------------------------------------------------------- 1 | 2 | Paragraph. 3 | 4 | Block quote 1. 5 | 6 | -- Attribution 1 7 | 8 | Block quote 2. 9 | -------------------------------------------------------------------------------- /Tests/Input/inlinemarkupemphasis_multiple: -------------------------------------------------------------------------------- 1 | 2 | l'*emphasis* with the *emphasis*' apostrophe. 3 | l’*emphasis* with the *emphasis*’ apostrophe. 4 | -------------------------------------------------------------------------------- /Tests/Input/definitionlist_classifier: -------------------------------------------------------------------------------- 1 | 2 | Term : classifier 3 | The ' : ' indicates a classifier in 4 | definition list item terms only. 5 | -------------------------------------------------------------------------------- /Tests/Input/bulletlist_unicode: -------------------------------------------------------------------------------- 1 | 2 | Unicode bullets: 3 | 4 | \u2022 BULLET 5 | 6 | \u2023 TRIANGULAR BULLET 7 | 8 | \u2043 HYPHEN BULLET 9 | 10 | -------------------------------------------------------------------------------- /Tests/Input/comment_bulletlist_comment: -------------------------------------------------------------------------------- 1 | 2 | + bullet paragraph 1 3 | 4 | .. comment between bullet paragraphs 1 (leader) and 2 5 | 6 | bullet paragraph 2 7 | -------------------------------------------------------------------------------- /Tests/Input/comment_multiplelines: -------------------------------------------------------------------------------- 1 | 2 | .. 3 | A comment consisting of multiple lines 4 | starting on the line after the 5 | explicit markup start. 6 | -------------------------------------------------------------------------------- /Tests/Input/inlinemarkupliteral_quoted: -------------------------------------------------------------------------------- 1 | 2 | quoted '``literal``', quoted "``literal``" 3 | quoted ‘``literal``’, quoted “``literal``”, 4 | quoted «``literal``» 5 | -------------------------------------------------------------------------------- /Tests/Input/inlinemarkupstrongemphasis_quoted: -------------------------------------------------------------------------------- 1 | 2 | quoted '**strong**', quoted "**strong**", 3 | quoted ‘**strong**’, quoted “**strong**”, 4 | quoted «**strong**» 5 | -------------------------------------------------------------------------------- /Tests/Input/lineblock_multiple: -------------------------------------------------------------------------------- 1 | 2 | | This is a line block. 3 | | Line breaks are *preserved*. 4 | 5 | | This is a second line block. 6 | 7 | | This is a third. 8 | -------------------------------------------------------------------------------- /Tests/Input/comment_bulletlist: -------------------------------------------------------------------------------- 1 | 2 | + bullet paragraph 1 3 | 4 | bullet paragraph 2 5 | 6 | .. comment between bullet paragraphs 2 and 3 7 | 8 | bullet paragraph 3 9 | -------------------------------------------------------------------------------- /Tests/Input/blockquote_attribution_simple: -------------------------------------------------------------------------------- 1 | 2 | Paragraph. 3 | 4 | Block quote 1. 5 | 6 | -- Attribution 1 7 | 8 | Block quote 2. 9 | 10 | -- Attribution 2 11 | -------------------------------------------------------------------------------- /Tests/Input/full_linestart: -------------------------------------------------------------------------------- 1 | - :doc: 2 | - :doc:` 3 | - :doc:`/ 4 | - :doc:`/test2 5 | - :doc:`/test2/ 6 | - :doc:`/test2/` 7 | - :doc:`/test2/`/ 8 | - :doc:`/` 9 | - :doc:``/ 10 | -------------------------------------------------------------------------------- /Tests/Input/inlinemarkupliteral_quote: -------------------------------------------------------------------------------- 1 | 2 | ``'literal'`` with quotes, ``"literal"`` with quotes, 3 | ``‘literal’`` with quotes, ``“literal”`` with quotes, 4 | ``«literal»`` with quotes 5 | -------------------------------------------------------------------------------- /Tests/Input/blockquote_attribution: -------------------------------------------------------------------------------- 1 | 2 | Paragraph. 3 | 4 | Block quote. 5 | 6 | -- Attribution 7 | 8 | Paragraph. 9 | 10 | Block quote. 11 | 12 | --Attribution 13 | -------------------------------------------------------------------------------- /Tests/Input/enumeratedlist_scrambled: -------------------------------------------------------------------------------- 1 | 2 | Scrambled: 3 | 4 | 3. Item three. 5 | 6 | 2. Item two. 7 | 8 | 1. Item one. 9 | 10 | 3. Item three. 11 | 2. Item two. 12 | 1. Item one. 13 | -------------------------------------------------------------------------------- /Tests/Input/full_linenumbers: -------------------------------------------------------------------------------- 1 | 2 | ======= 3 | Section 4 | ======= 5 | 6 | Paragraph. Line 1. 7 | Line 2. 8 | 9 | - :doc:`/test/` 10 | - :doc:`/test2/` 11 | 12 | Test para :doc:`/ 13 | -------------------------------------------------------------------------------- /Tests/Input/blockquote_comment: -------------------------------------------------------------------------------- 1 | 2 | Unindented paragraph. 3 | 4 | Block quote 1. 5 | 6 | -- Attribution 1 7 | 8 | Block quote 2. 9 | 10 | .. 11 | 12 | Block quote 3. 13 | -------------------------------------------------------------------------------- /Tests/Input/comment_followedbyempty: -------------------------------------------------------------------------------- 1 | 2 | .. Next is an empty comment, which serves to end this comment and 3 | prevents the following block quote being swallowed up. 4 | 5 | .. 6 | 7 | A block quote. 8 | -------------------------------------------------------------------------------- /Tests/Input/enumeratedlist_multiplebody: -------------------------------------------------------------------------------- 1 | 2 | 1. Item one: line 1, 3 | line 2. 4 | 2. Item two: line 1, 5 | line 2. 6 | 3. Item three: paragraph 1, line 1, 7 | line 2. 8 | 9 | Paragraph 2. 10 | -------------------------------------------------------------------------------- /Tests/Input/definitionlist_nested: -------------------------------------------------------------------------------- 1 | 2 | term 1 3 | definition 1 4 | 5 | term 1a 6 | definition 1a 7 | 8 | term 1b 9 | definition 1b 10 | 11 | term 2 12 | definition 2 13 | 14 | paragraph 15 | -------------------------------------------------------------------------------- /Tests/Input/enumeratedlist_nonordinal: -------------------------------------------------------------------------------- 1 | 2 | Start with non-ordinal-1: 3 | 4 | 0. Item zero. 5 | 1. Item one. 6 | 2. Item two. 7 | 3. Item three. 8 | 9 | And again: 10 | 11 | 2. Item two. 12 | 3. Item three. 13 | -------------------------------------------------------------------------------- /Tests/Input/section_nested: -------------------------------------------------------------------------------- 1 | 2 | Title 1 3 | ======= 4 | Paragraph 1. 5 | 6 | Title 2 7 | ------- 8 | Paragraph 2. 9 | 10 | Title 3 11 | ======= 12 | Paragraph 3. 13 | 14 | Title 4 15 | ------- 16 | Paragraph 4. 17 | -------------------------------------------------------------------------------- /Tests/Input/blockquote_attribution_emdash: -------------------------------------------------------------------------------- 1 | 2 | Alternative: true em-dash. 3 | 4 | Block quote. 5 | 6 | — Attribution 7 | 8 | Alternative: three hyphens. 9 | 10 | Block quote. 11 | 12 | --- Attribution 13 | -------------------------------------------------------------------------------- /Tests/Input/literalblock_two: -------------------------------------------------------------------------------- 1 | 2 | A paragraph:: 3 | 4 | A literal block. 5 | 6 | Another paragraph:: 7 | 8 | Another literal block. 9 | With two blank lines following. 10 | 11 | 12 | A final paragraph. 13 | -------------------------------------------------------------------------------- /Tests/Input/blockquote_nested2: -------------------------------------------------------------------------------- 1 | 2 | Here is a paragraph. 3 | 4 | Indent 8 spaces. 5 | 6 | Indent 4 spaces. 7 | 8 | Is this correct? Should it generate a warning? 9 | Yes, it is correct, no warning necessary. 10 | -------------------------------------------------------------------------------- /Tests/Input/section_nested_overline_level3: -------------------------------------------------------------------------------- 1 | 2 | Title 1 3 | ======= 4 | Paragraph 1. 5 | 6 | Title 2 7 | ------- 8 | Paragraph 2. 9 | 10 | Title 3 11 | +++++++ 12 | Paragraph 3. 13 | 14 | Title 4 15 | ------- 16 | Paragraph 4. 17 | -------------------------------------------------------------------------------- /ReStructuredText/Scope.cs: -------------------------------------------------------------------------------- 1 | namespace Lextm.ReStructuredText 2 | { 3 | public struct Scope 4 | { 5 | public int LineStart; 6 | public int LineEnd; 7 | public int ColumnStart; 8 | public int ColumnEnd; 9 | } 10 | } -------------------------------------------------------------------------------- /Tests/Input/blockquote_attribution_complicated: -------------------------------------------------------------------------------- 1 | 2 | Paragraph. 3 | 4 | -- Not a valid attribution 5 | 6 | Block quote 1. 7 | 8 | --Attribution 1 9 | 10 | --Invalid attribution 11 | 12 | Block quote 2. 13 | 14 | --Attribution 2 15 | -------------------------------------------------------------------------------- /Tests/Input/definitionlist_classifier_without: -------------------------------------------------------------------------------- 1 | 2 | Term: not a classifier 3 | Because there's no space before the colon. 4 | Term :not a classifier 5 | Because there's no space after the colon. 6 | Term \: not a classifier 7 | Because the colon is escaped. 8 | -------------------------------------------------------------------------------- /Tests/Input/blockquote_attribution_multiline: -------------------------------------------------------------------------------- 1 | 2 | Paragraph. 3 | 4 | Block quote. 5 | 6 | -- Attribution line one 7 | and line two 8 | 9 | Paragraph. 10 | 11 | Block quote. 12 | 13 | -- Attribution line one 14 | and line two 15 | 16 | Paragraph. 17 | -------------------------------------------------------------------------------- /Server/Services/LanguageServiceBase.cs: -------------------------------------------------------------------------------- 1 | using JsonRpc.Server; 2 | 3 | namespace Lextm.ReStructuredText.LanguageServer.Services 4 | { 5 | public class LanguageServiceBase : JsonRpcService 6 | { 7 | protected SessionState Session => RequestContext.Features.Get(); 8 | } 9 | } -------------------------------------------------------------------------------- /Tests/Input/section_shorts: -------------------------------------------------------------------------------- 1 | 2 | === 3 | One 4 | === 5 | 6 | The bubble-up parser strategy conflicts with short titles 7 | (<= 3 char-long over- & underlines). 8 | 9 | === 10 | Two 11 | === 12 | 13 | The parser currently contains a work-around kludge. 14 | Without it, the parser ends up in an infinite loop. 15 | -------------------------------------------------------------------------------- /Tests/Input/blockquote_definitionlist: -------------------------------------------------------------------------------- 1 | 2 | Paragraph. 3 | 4 | -- Not an attribution 5 | 6 | Paragraph. 7 | 8 | Block quote. 9 | 10 | \-- Not an attribution 11 | 12 | Paragraph. 13 | 14 | Block quote. 15 | 16 | -- Not an attribution line one 17 | and line two 18 | and line three 19 | -------------------------------------------------------------------------------- /Tests/Input/enumeratedlist_different: -------------------------------------------------------------------------------- 1 | Different enumeration sequences: 2 | 3 | 1. Item 1. 4 | 2. Item 2. 5 | 3. Item 3. 6 | 7 | A. Item A. 8 | B. Item B. 9 | C. Item C. 10 | 11 | a. Item a. 12 | b. Item b. 13 | c. Item c. 14 | 15 | I. Item I. 16 | II. Item II. 17 | III. Item III. 18 | 19 | i. Item i. 20 | ii. Item ii. 21 | iii. Item iii. 22 | -------------------------------------------------------------------------------- /Tests/Input/section_nested_overline: -------------------------------------------------------------------------------- 1 | 2 | Test return to existing, highest-level section (Title 3, with overlines). 3 | 4 | ======= 5 | Title 1 6 | ======= 7 | Paragraph 1. 8 | 9 | ------- 10 | Title 2 11 | ------- 12 | Paragraph 2. 13 | 14 | ======= 15 | Title 3 16 | ======= 17 | Paragraph 3. 18 | 19 | ------- 20 | Title 4 21 | ------- 22 | Paragraph 4. 23 | -------------------------------------------------------------------------------- /Tests/TestUtils.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | 3 | namespace Lextm.ReStructuredText.Tests 4 | { 5 | public static class TestUtils 6 | { 7 | public static Document Test(string fileName) 8 | { 9 | var path = Path.Combine("Input", fileName); 10 | var result = ReStructuredTextParser.ParseDocument(path); 11 | return result; 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /ReStructuredText/ITextArea.cs: -------------------------------------------------------------------------------- 1 | namespace Lextm.ReStructuredText 2 | { 3 | /// 4 | /// 5 | /// 6 | public interface ITextArea 7 | { 8 | bool IsIndented { get; } 9 | Content Content { get; } 10 | int Indentation { get; set; } 11 | bool IsQuoted { get; } 12 | ElementType TypeCode { get; } 13 | Scope Scope { get; } 14 | } 15 | } -------------------------------------------------------------------------------- /Server/Utility.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using Newtonsoft.Json.Serialization; 3 | 4 | namespace Lextm.ReStructuredText.LanguageServer 5 | { 6 | internal static class Utility 7 | { 8 | public static readonly JsonSerializer CamelCaseJsonSerializer = new JsonSerializer 9 | { 10 | ContractResolver = new CamelCasePropertyNamesContractResolver() 11 | }; 12 | } 13 | } -------------------------------------------------------------------------------- /ReStructuredText/Term.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace Lextm.ReStructuredText 5 | { 6 | public class Term 7 | { 8 | public Term(IEnumerable take) 9 | { 10 | take.Last().Content.RemoveEnd(); 11 | TextAreas = take.ToList(); 12 | } 13 | 14 | public IList TextAreas { get; } 15 | } 16 | } -------------------------------------------------------------------------------- /ReStructuredText/Definition.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Lextm.ReStructuredText 4 | { 5 | public class Definition 6 | { 7 | public Definition() 8 | { 9 | Elements = new List(); 10 | } 11 | 12 | public IList Elements { get; } 13 | 14 | public IParent Add(IElement element) 15 | { 16 | Elements.Add(element); 17 | return element; 18 | } 19 | 20 | public int Indentation { get; set; } 21 | } 22 | } -------------------------------------------------------------------------------- /Tests/Input/inlinemarkupemphasis_punctuation: -------------------------------------------------------------------------------- 1 | 2 | some punctuation is allowed around inline markup, e.g. 3 | /*emphasis*/, -*emphasis*-, and :*emphasis*: (delimiters), 4 | (*emphasis*), [*emphasis*], <*emphasis*>, {*emphasis*} (open/close pairs) 5 | *emphasis*., *emphasis*,, *emphasis*!, and *emphasis* (closing delimiters), 6 | 7 | but not 8 | )*emphasis*(, ]*emphasis*[, >*emphasis*>, }*emphasis*{ (close/open pairs), 9 | (*), [*], '*' or '"*"' ("quoted" star-string), 10 | x*2* or 2*x* (alphanumeric char before), 11 | \*args or * (escaped, whitespace behind start-string), 12 | or *the\* *stars\* *inside* (escaped, whitespace before end-string). 13 | 14 | what about *this**? 15 | -------------------------------------------------------------------------------- /ReStructuredText/Literal.cs: -------------------------------------------------------------------------------- 1 | namespace Lextm.ReStructuredText 2 | { 3 | public class Literal : ITextArea 4 | { 5 | private readonly TextArea _textArea; 6 | 7 | public Literal(TextArea textArea) 8 | { 9 | _textArea = textArea; 10 | } 11 | 12 | public bool IsIndented => _textArea.IsIndented; 13 | public Content Content => _textArea.Content; 14 | public int Indentation 15 | { 16 | get => _textArea.Indentation; 17 | set => _textArea.Indentation = value; 18 | } 19 | 20 | public bool IsQuoted => _textArea.IsQuoted; 21 | public ElementType TypeCode => ElementType.Literal; 22 | 23 | public Scope Scope => _textArea.Scope; 24 | } 25 | } -------------------------------------------------------------------------------- /ReStructuredText/Classifier.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace Lextm.ReStructuredText 5 | { 6 | public class Classifier 7 | { 8 | public IList TextAreas; 9 | 10 | public Classifier(List textAreas) 11 | { 12 | textAreas.Last().Content.RemoveEnd(); 13 | textAreas.First().Content.RemoveStart(); 14 | TextAreas = new List(); 15 | foreach (var item in textAreas) 16 | { 17 | if (string.IsNullOrWhiteSpace(item.Content.Text)) 18 | { 19 | continue; 20 | } 21 | 22 | TextAreas.Add(item); 23 | } 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /Server/Settings.cs: -------------------------------------------------------------------------------- 1 | namespace Lextm.ReStructuredText.LanguageServer 2 | { 3 | 4 | public class SettingsRoot 5 | { 6 | public ReStructuredTextSettings ReStructuredText { get; set; } 7 | } 8 | 9 | public class ReStructuredTextSettings 10 | { 11 | public string ConfPath { get; set; } 12 | public LanguageServerSettings LanguageServer { get; set; } = new LanguageServerSettings(); 13 | } 14 | 15 | public class LanguageServerSettings 16 | { 17 | public int MaxNumberOfProblems { get; set; } = 10; 18 | 19 | public LanguageServerTraceSettings Trace { get; } = new LanguageServerTraceSettings(); 20 | } 21 | 22 | public class LanguageServerTraceSettings 23 | { 24 | public string Server { get; set; } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Server/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyCopyright("Copyright © 2017")] 8 | [assembly: AssemblyTrademark("")] 9 | [assembly: AssemblyCulture("")] 10 | 11 | // Setting ComVisible to false makes the types in this assembly not visible 12 | // to COM components. If you need to access a type in this assembly from 13 | // COM, set the ComVisible attribute to true on that type. 14 | [assembly: ComVisible(false)] 15 | 16 | // The following GUID is for the ID of the typelib if this project is exposed to COM 17 | [assembly: Guid("62CB65C4-24BA-408C-BF52-9209C239B969")] 18 | -------------------------------------------------------------------------------- /Server/Services/CompletionItemService.cs: -------------------------------------------------------------------------------- 1 | using JsonRpc.Contracts; 2 | using LanguageServer.VsCode.Contracts; 3 | 4 | namespace Lextm.ReStructuredText.LanguageServer.Services 5 | { 6 | [JsonRpcScope(MethodPrefix = "completionItem/")] 7 | public class CompletionItemService : LanguageServiceBase 8 | { 9 | // The request is sent from the client to the server to resolve additional information 10 | // for a given completion item. 11 | [JsonRpcMethod(AllowExtensionData = true)] 12 | public CompletionItem Resolve() 13 | { 14 | var item = RequestContext.Request.Parameters.ToObject(Utility.CamelCaseJsonSerializer); 15 | // Add a pair of square brackets around the inserted text. 16 | item.InsertText = $"{item.Label}"; 17 | return item; 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /ReStructuredText/InterpretedText.cs: -------------------------------------------------------------------------------- 1 | namespace Lextm.ReStructuredText 2 | { 3 | public class InterpretedText : ITextArea 4 | { 5 | public string RoleName { get; } 6 | public Scope Scope => _textArea.Scope; 7 | 8 | private readonly TextArea _textArea; 9 | 10 | public InterpretedText(string title, TextArea textArea) 11 | { 12 | RoleName = title; 13 | _textArea = textArea; 14 | } 15 | 16 | public bool IsIndented => _textArea.IsIndented; 17 | public Content Content => _textArea.Content; 18 | public int Indentation 19 | { 20 | get => _textArea.Indentation; 21 | set => _textArea.Indentation = value; 22 | } 23 | 24 | public bool IsQuoted => _textArea.IsQuoted; 25 | public ElementType TypeCode => ElementType.InterpretedText; 26 | } 27 | } -------------------------------------------------------------------------------- /dist.server.ps1: -------------------------------------------------------------------------------- 1 | Remove-Item -Recurse -Force output 2 | Set-Location Server 3 | dotnet publish --self-contained -r win-x86 -c release -o ..\output\win32_x86 -p:PublishSingleFile=true 4 | dotnet publish --self-contained -r win-x64 -c release -o ..\output\win32_x64 -p:PublishSingleFile=true 5 | dotnet publish --self-contained -r linux-x64 -c release -o ..\output\linux_x64 -p:PublishSingleFile=true 6 | dotnet publish --self-contained -r osx-x64 -c release -o ..\output\darwin_x64 -p:PublishSingleFile=true 7 | Set-Location .. 8 | 9 | Set-Location output 10 | Set-Location win32_x86 11 | Compress-Archive * -DestinationPath ..\win32_x86.zip 12 | Set-Location .. 13 | Set-Location win32_x64 14 | Compress-Archive * -DestinationPath ..\win32_x64.zip 15 | Set-Location .. 16 | Set-Location linux_x64 17 | chmod a+x Server 18 | Compress-Archive * -DestinationPath ..\linux_x64.zip 19 | Set-Location .. 20 | Set-Location darwin_x64 21 | chmod a+x Server 22 | Compress-Archive * -DestinationPath ..\darwin_x64.zip 23 | Set-Location .. 24 | Set-Location .. 25 | -------------------------------------------------------------------------------- /ReStructuredText/Emphasis.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace Lextm.ReStructuredText 5 | { 6 | public class Emphasis : ITextArea 7 | { 8 | public IList TextAreas { get; } 9 | public Scope Scope { get; } 10 | 11 | public Emphasis(IList textAreas) 12 | { 13 | TextAreas = textAreas; 14 | Scope = new Scope 15 | { 16 | LineStart = TextAreas.First().Scope.LineStart, 17 | LineEnd = TextAreas.Last().Scope.LineEnd 18 | }; 19 | } 20 | 21 | public bool IsIndented => TextAreas[0].IsIndented; 22 | public Content Content => TextAreas[0].Content; 23 | public int Indentation 24 | { 25 | get => TextAreas[0].Indentation; 26 | set => TextAreas[0].Indentation = value; 27 | } 28 | 29 | public bool IsQuoted => TextAreas[0].IsQuoted; 30 | public ElementType TypeCode => ElementType.Emphasis; 31 | } 32 | } -------------------------------------------------------------------------------- /Tests/Tests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | netcoreapp3.1 4 | Exe 5 | Lextm.ReStructuredText.Tests 6 | 7 | 8 | 9 | 2.4.1 10 | 11 | 12 | 2.4.1 13 | runtime; build; native; contentfiles; analyzers; buildtransitive 14 | all 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | PreserveNewest 24 | 25 | 26 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2011 Bart Kiers 4 | Copyright (c) 2017 Lex Li 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 7 | 8 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 9 | 10 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 11 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | reStructuredText Grammar for ANTLR 4 2 | ==================================== 3 | 4 | [![Build Status](https://dev.azure.com/lextudio/vscode-restructuredtext/_apis/build/status/lextm.restructuredtext-antlr?branchName=master)](https://dev.azure.com/lextudio/vscode-restructuredtext/_build/latest?definitionId=3&branchName=master) 5 | 6 | This is the source code repo of reStructuredText grammar file for ANTLR 4. Visual Studio 2017/Rider is required to compile it. It should run cross platform. 7 | 8 | It is licensed under MIT license. 9 | 10 | History 11 | ------- 12 | This piece of work was started by Bart Kiers in 2011 as [a Stack Overflow answer](https://stackoverflow.com/questions/6178546/antlr-grammar-for-restructuredtext-rule-priorities) 13 | and Lex Li picked it up in 2017 to continue the momentum. 14 | 15 | Goals 16 | ----- 17 | * Compatibility to existing parsers, like Sphinx and [the JavaScript one](https://github.com/seikichi/restructured). 18 | * Linter and Language Server for Sphinx to empower [Visual Studio Code reStructuredText extension](https://github.com/vscode-restructuredtext/vscode-restructuredtext). 19 | * (Probably) DocFX fork to replace Sphinx completely. 20 | 21 | Others 22 | ------ 23 | Issues and questions can be created directly at GitHub. 24 | -------------------------------------------------------------------------------- /Server/Server.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp3.1 6 | win-x86;win-x64;linux-x64;osx-x64 7 | Lextm.ReStructuredText.LanguageServer 8 | true 9 | 10 | 11 | 12 | {a7e5ad0b-65f6-4c42-af05-b243ff5c4876} 13 | ReStructuredText 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /ReStructuredText/IParent.cs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2017 Lex Li 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this 4 | // software and associated documentation files (the "Software"), to deal in the Software 5 | // without restriction, including without limitation the rights to use, copy, modify, merge, 6 | // publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons 7 | // to whom the Software is furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in all copies or 10 | // substantial portions of the Software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 13 | // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 14 | // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE 15 | // FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 16 | // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 17 | // DEALINGS IN THE SOFTWARE. 18 | 19 | namespace Lextm.ReStructuredText 20 | { 21 | public interface IParent 22 | { 23 | IParent Add(IElement element, int level = 0); 24 | 25 | ElementType TypeCode { get; } 26 | 27 | IParent Parent { get; set; } 28 | } 29 | } -------------------------------------------------------------------------------- /ReStructuredText/Strong.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using System.Text; 4 | 5 | namespace Lextm.ReStructuredText 6 | { 7 | public class Strong : ITextArea 8 | { 9 | public IList TextAreas { get; } 10 | public Scope Scope { get; } 11 | 12 | public Strong(IList textTextAreas) 13 | { 14 | TextAreas = textTextAreas; 15 | Scope = new Scope 16 | { 17 | LineStart = TextAreas.First().Scope.LineStart, 18 | LineEnd = TextAreas.Last().Scope.LineEnd 19 | }; 20 | } 21 | 22 | public bool IsIndented => TextAreas[0].IsIndented; 23 | public Content Content => TextAreas[0].Content; 24 | public int Indentation 25 | { 26 | get => TextAreas[0].Indentation; 27 | set => TextAreas[0].Indentation = value; 28 | } 29 | 30 | public bool IsQuoted => TextAreas[0].IsQuoted; 31 | public ElementType TypeCode => ElementType.Strong; 32 | 33 | internal static ITextArea ParseStars(string stars, Scope scope) 34 | { 35 | var length = stars.Length; 36 | var builder = new StringBuilder(length - 4); 37 | for (int i = 0; i < length - 4; i++) 38 | { 39 | builder.Append("*"); 40 | } 41 | 42 | return new Strong(new ITextArea[] { new TextArea(builder.ToString(), scope) }); 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /azure-pipelines.yml: -------------------------------------------------------------------------------- 1 | # .NET Desktop 2 | # Build and run tests for .NET Desktop or Windows classic desktop solutions. 3 | # Add steps that publish symbols, save build artifacts, and more: 4 | # https://docs.microsoft.com/azure/devops/pipelines/apps/windows/dot-net 5 | 6 | jobs: 7 | - job: Linux 8 | 9 | pool: 10 | vmImage: 'ubuntu-latest' 11 | 12 | variables: 13 | solution: '**/*.sln' 14 | buildPlatform: 'Any CPU' 15 | buildConfiguration: 'Release' 16 | 17 | steps: 18 | - script: | 19 | set -e 20 | dotnet build ReStructuredText.sln --configuration $(buildConfiguration) 21 | dotnet test Tests/Tests.csproj --configuration $(buildConfiguration) --no-build 22 | 23 | - job: macOS 24 | 25 | pool: 26 | vmImage: 'macOS-latest' 27 | 28 | variables: 29 | solution: '**/*.sln' 30 | buildPlatform: 'Any CPU' 31 | buildConfiguration: 'Release' 32 | 33 | steps: 34 | - script: | 35 | set -e 36 | dotnet build ReStructuredText.sln --configuration $(buildConfiguration) 37 | dotnet test Tests/Tests.csproj --configuration $(buildConfiguration) --no-build 38 | 39 | - job: Windows 40 | 41 | pool: 42 | vmImage: 'windows-latest' 43 | 44 | variables: 45 | solution: '**/*.sln' 46 | buildPlatform: 'Any CPU' 47 | buildConfiguration: 'Release' 48 | 49 | steps: 50 | - script: | 51 | dotnet build ReStructuredText.sln --configuration $(buildConfiguration) 52 | dotnet test Tests/Tests.csproj --configuration $(buildConfiguration) --no-build 53 | -------------------------------------------------------------------------------- /ReStructuredText/IElement.cs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2017 Lex Li 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this 4 | // software and associated documentation files (the "Software"), to deal in the Software 5 | // without restriction, including without limitation the rights to use, copy, modify, merge, 6 | // publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons 7 | // to whom the Software is furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in all copies or 10 | // substantial portions of the Software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 13 | // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 14 | // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE 15 | // FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 16 | // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 17 | // DEALINGS IN THE SOFTWARE. 18 | 19 | using System.Collections.Generic; 20 | 21 | namespace Lextm.ReStructuredText 22 | { 23 | public interface IElement : IParent 24 | { 25 | 26 | IList TextAreas { get; } 27 | 28 | IElement Find(int line, int column); 29 | 30 | IParent Add(IElement element, int level = 0); 31 | 32 | int Indentation { get; } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /ReStructuredText/Attribution.cs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2017 Lex Li 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this 4 | // software and associated documentation files (the "Software"), to deal in the Software 5 | // without restriction, including without limitation the rights to use, copy, modify, merge, 6 | // publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons 7 | // to whom the Software is furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in all copies or 10 | // substantial portions of the Software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 13 | // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 14 | // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE 15 | // FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 16 | // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 17 | // DEALINGS IN THE SOFTWARE. 18 | 19 | using System.Collections.Generic; 20 | using System.Linq; 21 | 22 | namespace Lextm.ReStructuredText 23 | { 24 | public class Attribution 25 | { 26 | public Attribution(IList textAreas) 27 | { 28 | TextAreas = textAreas; 29 | TextAreas.First().Content.RemoveAttribution(); 30 | } 31 | 32 | public IList TextAreas { get; } 33 | } 34 | } -------------------------------------------------------------------------------- /ReStructuredText/Line.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace Lextm.ReStructuredText 5 | { 6 | public class Line : IElement 7 | { 8 | public Line(IList areas) 9 | { 10 | TextAreas = new List(); 11 | foreach (var area in areas) 12 | { 13 | if (area.TypeCode == ElementType.BackTickText) 14 | { 15 | ((BackTickText)area).Process(TextAreas); 16 | } 17 | else if (area.TypeCode == ElementType.StarText) 18 | { 19 | ((StarText)area).Process(TextAreas); 20 | } 21 | else 22 | { 23 | TextAreas.Add(area); 24 | } 25 | } 26 | 27 | TextAreas.Last().Content.RemoveEnd(); 28 | } 29 | 30 | public ElementType TypeCode => ElementType.Line; 31 | public IList TextAreas { get; } 32 | public IParent Parent { get; set; } 33 | 34 | public IElement Find(int line, int column) 35 | { 36 | var first = TextAreas.First(); 37 | var last = TextAreas.Last(); 38 | if (line < first.Scope.LineStart || line > last.Scope.LineEnd) 39 | { 40 | return null; 41 | } 42 | 43 | return this; 44 | } 45 | 46 | public IParent Add(IElement element, int level = 0) 47 | { 48 | return Parent.Add(element); 49 | } 50 | 51 | public int Indentation => TextAreas[0].Indentation; 52 | } 53 | } -------------------------------------------------------------------------------- /ReStructuredText/ReStructuredText.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | netstandard1.3 4 | true 5 | Lextm.ReStructuredText 6 | full 7 | 1.0.0 8 | Lex Li 9 | 10 | reStructuredText for .NET 11 | reStructuredText for .NET 12 | Lextm.ReStructuredText 13 | reStructuredText parser for .NET. 14 | restructuredtext rst parser 15 | https://github.com/lextm/restructuredtext-antlr 16 | https://github.com/lextm/restructuredtext-antlr 17 | en-us 18 | https://github.com/lextm/restructuredtext-antlr/releases 19 | Copyright (C) 2011 Bart Kiers. Copyright (C) 2017 Lex Li 20 | 1.0.0.0 21 | 1.0.0.0 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 4.6.6 30 | runtime; build; native; contentfiles; analyzers; buildtransitive 31 | all 32 | 33 | 34 | 4.6.6 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /Server/Services/WorkspaceService.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.IO; 3 | using System.Threading.Tasks; 4 | using JsonRpc.Contracts; 5 | using LanguageServer.VsCode.Contracts; 6 | namespace Lextm.ReStructuredText.LanguageServer.Services 7 | { 8 | [JsonRpcScope(MethodPrefix = "workspace/")] 9 | public class WorkspaceService : LanguageServiceBase 10 | { 11 | [JsonRpcMethod(IsNotification = true)] 12 | public async Task DidChangeConfiguration(SettingsRoot settings) 13 | { 14 | Session.Settings = settings.ReStructuredText; 15 | foreach (var doc in Session.DocumentStates.Values) 16 | { 17 | //Session.Project.RefreshDocument(doc.Document); 18 | // var diag = Session.DiagnosticProvider.LintDocument(doc.Document, Session.Settings.LanguageServer.MaxNumberOfProblems); 19 | // await Client.Document.PublishDiagnostics(doc.Document.Uri, diag); 20 | } 21 | } 22 | 23 | [JsonRpcMethod(IsNotification = true)] 24 | public async Task DidChangeWatchedFiles(ICollection changes) 25 | { 26 | foreach (var change in changes) 27 | { 28 | if (!change.Uri.IsFile) continue; 29 | var localPath = change.Uri.AbsolutePath; 30 | if (string.Equals(Path.GetExtension(localPath), ".rst") || string.Equals(Path.GetExtension(localPath), ".rest")) 31 | { 32 | // If the file has been removed, we will clear the lint result about it. 33 | // Note that pass null to PublishDiagnostics may mess up the client. 34 | if (change.Type == FileChangeType.Deleted) 35 | { 36 | await Session.Client.Document.PublishDiagnostics(change.Uri, new Diagnostic[0]); 37 | } 38 | } 39 | } 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /ReStructuredText/ElementType.cs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2017 Lex Li 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this 4 | // software and associated documentation files (the "Software"), to deal in the Software 5 | // without restriction, including without limitation the rights to use, copy, modify, merge, 6 | // publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons 7 | // to whom the Software is furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in all copies or 10 | // substantial portions of the Software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 13 | // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 14 | // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE 15 | // FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 16 | // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 17 | // DEALINGS IN THE SOFTWARE. 18 | 19 | namespace Lextm.ReStructuredText 20 | { 21 | public enum ElementType 22 | { 23 | Paragraph, 24 | Comment, 25 | BlockQuote, 26 | Section, 27 | BulletList, 28 | LineBlock, 29 | ListItem, 30 | LiteralBlock, 31 | EnumeratedList, 32 | Literal, 33 | Text, 34 | /// 35 | /// Reserved. Used only for parsing process. 36 | /// 37 | BackTickText, 38 | InterpretedText, 39 | Emphasis, 40 | Strong, 41 | /// 42 | /// Reserved. Used only for parsing process. 43 | /// 44 | StarText, 45 | Line, 46 | Document, 47 | DefinitionList, 48 | DefinitionListItem 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /ReStructuredText/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2017 Lex Li 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this 4 | // software and associated documentation files (the "Software"), to deal in the Software 5 | // without restriction, including without limitation the rights to use, copy, modify, merge, 6 | // publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons 7 | // to whom the Software is furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in all copies or 10 | // substantial portions of the Software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 13 | // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 14 | // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE 15 | // FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 16 | // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 17 | // DEALINGS IN THE SOFTWARE. 18 | 19 | using System; 20 | using System.Reflection; 21 | using System.Runtime.CompilerServices; 22 | using System.Runtime.InteropServices; 23 | 24 | // General Information about an assembly is controlled through the following 25 | // set of attributes. Change these attribute values to modify the information 26 | // associated with an assembly. 27 | [assembly: AssemblyTrademark("")] 28 | [assembly: AssemblyCulture("")] 29 | 30 | // Setting ComVisible to false makes the types in this assembly not visible 31 | // to COM components. If you need to access a type in this assembly from 32 | // COM, set the ComVisible attribute to true on that type. 33 | [assembly: ComVisible(false)] 34 | 35 | // The following GUID is for the ID of the typelib if this project is exposed to COM 36 | [assembly: Guid("a7e5ad0b-65f6-4c42-af05-b243ff5c4876")] 37 | 38 | [assembly: CLSCompliant(true)] 39 | -------------------------------------------------------------------------------- /Server/Services/InitializaionService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | using JsonRpc.Messages; 4 | using JsonRpc.Contracts; 5 | using JsonRpc.Server; 6 | using LanguageServer.VsCode.Contracts; 7 | using Newtonsoft.Json.Linq; 8 | 9 | namespace Lextm.ReStructuredText.LanguageServer.Services 10 | { 11 | public class InitializaionService : LanguageServiceBase 12 | { 13 | [JsonRpcMethod(AllowExtensionData = true)] 14 | public async Task Initialize(int processId, Uri rootUri, ClientCapabilities capabilities, 15 | JToken initializationOptions = null, string trace = null) 16 | { 17 | Session.Project.WorkspaceRoot = new Uri($"file://{rootUri.LocalPath}").LocalPath; 18 | // inform the language server client of server capabilities. 19 | return new InitializeResult(new ServerCapabilities 20 | { 21 | //HoverProvider = true, 22 | //SignatureHelpProvider = new SignatureHelpOptions(new[] {'(', ')'}), 23 | CompletionProvider = new CompletionOptions(true, new[]{'/'}), 24 | TextDocumentSync = new TextDocumentSyncOptions 25 | { 26 | OpenClose = true, 27 | WillSave = true, 28 | Change = TextDocumentSyncKind.Incremental 29 | } 30 | }); 31 | } 32 | 33 | [JsonRpcMethod(IsNotification = true)] 34 | public async Task Initialized() 35 | { 36 | //await Session.Client.Window.ShowMessage(MessageType.Info, "Hello from language server."); 37 | } 38 | 39 | [JsonRpcMethod] 40 | public void Shutdown() 41 | { 42 | 43 | } 44 | 45 | [JsonRpcMethod(IsNotification = true)] 46 | public void Exit() 47 | { 48 | Session.StopServer(); 49 | } 50 | 51 | [JsonRpcMethod("$/cancelRequest", IsNotification = true)] 52 | public void CancelRequest(MessageId id) 53 | { 54 | RequestContext.Features.Get()?.TryCancel(id); 55 | } 56 | } 57 | } -------------------------------------------------------------------------------- /ReStructuredText.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.27130.2010 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ReStructuredText", "ReStructuredText\ReStructuredText.csproj", "{A7E5AD0B-65F6-4C42-AF05-B243FF5C4876}" 7 | EndProject 8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tests", "Tests\Tests.csproj", "{5803E8F5-273D-4960-B8C9-2F71E8C344E3}" 9 | EndProject 10 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Server", "Server\Server.csproj", "{306136BD-480E-4E86-85E9-CF88542A55C5}" 11 | EndProject 12 | Global 13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 14 | Debug|Any CPU = Debug|Any CPU 15 | Release|Any CPU = Release|Any CPU 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {A7E5AD0B-65F6-4C42-AF05-B243FF5C4876}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 19 | {A7E5AD0B-65F6-4C42-AF05-B243FF5C4876}.Debug|Any CPU.Build.0 = Debug|Any CPU 20 | {A7E5AD0B-65F6-4C42-AF05-B243FF5C4876}.Release|Any CPU.ActiveCfg = Release|Any CPU 21 | {A7E5AD0B-65F6-4C42-AF05-B243FF5C4876}.Release|Any CPU.Build.0 = Release|Any CPU 22 | {5803E8F5-273D-4960-B8C9-2F71E8C344E3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 23 | {5803E8F5-273D-4960-B8C9-2F71E8C344E3}.Debug|Any CPU.Build.0 = Debug|Any CPU 24 | {5803E8F5-273D-4960-B8C9-2F71E8C344E3}.Release|Any CPU.ActiveCfg = Release|Any CPU 25 | {5803E8F5-273D-4960-B8C9-2F71E8C344E3}.Release|Any CPU.Build.0 = Release|Any CPU 26 | {306136BD-480E-4E86-85E9-CF88542A55C5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 27 | {306136BD-480E-4E86-85E9-CF88542A55C5}.Debug|Any CPU.Build.0 = Debug|Any CPU 28 | {306136BD-480E-4E86-85E9-CF88542A55C5}.Release|Any CPU.ActiveCfg = Release|Any CPU 29 | {306136BD-480E-4E86-85E9-CF88542A55C5}.Release|Any CPU.Build.0 = Release|Any CPU 30 | EndGlobalSection 31 | GlobalSection(SolutionProperties) = preSolution 32 | HideSolutionNode = FALSE 33 | EndGlobalSection 34 | GlobalSection(ExtensibilityGlobals) = postSolution 35 | SolutionGuid = {842C2225-C065-48A2-B3E1-A904CFADAFFF} 36 | EndGlobalSection 37 | EndGlobal 38 | -------------------------------------------------------------------------------- /Server/SphinxProject.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.IO; 3 | using System.Linq; 4 | using LanguageServer.VsCode.Contracts; 5 | using LanguageServer.VsCode.Server; 6 | 7 | namespace Lextm.ReStructuredText.LanguageServer 8 | { 9 | public class SphinxProject 10 | { 11 | public void RefreshDocument(TextDocument doc) 12 | { 13 | // var key = doc.Uri.ToString(); 14 | // if (!Files.ContainsKey(key)) 15 | // { 16 | // var path = key; 17 | // Files.Add(key, path); 18 | // } 19 | } 20 | 21 | public CompletionList GetCompletionList(DocumentState textDocument, Position position, CompletionContext context) 22 | { 23 | var document = textDocument.LintedDocument; 24 | if (context.TriggerKind != CompletionTriggerKind.TriggerCharacter 25 | || context.TriggerCharacter != '/' 26 | || !document.TriggerDocumentList(position.Line, position.Character)) 27 | { 28 | return new CompletionList(); 29 | } 30 | 31 | var Files = new Dictionary(); 32 | foreach (string file in Directory.EnumerateFiles( 33 | WorkspaceRoot, "*.rst", SearchOption.AllDirectories)) 34 | { 35 | Files.Add(GetPath(file), file); 36 | } 37 | 38 | foreach (string file in Directory.EnumerateFiles( 39 | WorkspaceRoot, "*.rest", SearchOption.AllDirectories)) 40 | { 41 | Files.Add(GetPath(file), file); 42 | } 43 | 44 | bool incomplete = Files.Count > 50; 45 | return new CompletionList(Files.Select(_ => 46 | new CompletionItem(_.Key, CompletionItemKind.File, _.Value, null)).Take(50), incomplete); 47 | } 48 | 49 | private string GetPath(string file) 50 | { 51 | var part = file.Substring(WorkspaceRoot.Length); 52 | return part.TrimStart('\\', '/').Replace('\\', '/').Replace(".rst", null).Replace(".rest", null); 53 | } 54 | 55 | public string WorkspaceRoot { get; set; } 56 | } 57 | } -------------------------------------------------------------------------------- /Tests/LineBlockTest.cs: -------------------------------------------------------------------------------- 1 | using Xunit; 2 | 3 | namespace Lextm.ReStructuredText.Tests 4 | { 5 | public class LineBlockTest 6 | { 7 | [Fact] 8 | public void Simple() 9 | { 10 | var document = TestUtils.Test("lineblock_simple"); 11 | Assert.Equal(1, document.Elements.Count); 12 | var block = (LineBlock) document.Elements[0]; 13 | Assert.Equal("This is a line block.", block.TextAreas[0].Content.Text); 14 | } 15 | 16 | [Fact] 17 | public void Multiple() 18 | { 19 | var document = TestUtils.Test("lineblock_multiple"); 20 | Assert.Equal(3, document.Elements.Count); 21 | var block = (LineBlock) document.Elements[0]; 22 | Assert.Equal("This is a line block.", block.TextAreas[0].Content.Text); 23 | var line = (Line) block.Elements[1]; 24 | Assert.Equal("Line breaks are ", line.TextAreas[0].Content.Text); 25 | Assert.Equal("preserved", line.TextAreas[1].Content.Text); 26 | Assert.Equal(".", line.TextAreas[2].Content.Text); 27 | 28 | Assert.Equal("This is a second line block.", document.Elements[1].TextAreas[0].Content.Text); 29 | Assert.Equal("This is a third.", document.Elements[2].TextAreas[0].Content.Text); 30 | } 31 | 32 | [Fact] 33 | public void InitialIndentation() 34 | { 35 | var document = TestUtils.Test("lineblock_indentation"); 36 | 37 | Assert.Equal(1, document.Elements.Count); 38 | var block = (LineBlock) document.Elements[0]; 39 | var block1 = (Line) block.Elements[0]; 40 | Assert.Equal("In line blocks,", block1.TextAreas[0].Content.Text); 41 | var child = (LineBlock) block.Elements[1]; 42 | Assert.Equal(ElementType.Text, child.TextAreas[0].TypeCode); 43 | Assert.Equal("Initial indentation is ", child.TextAreas[0].Content.Text); 44 | Assert.Equal(ElementType.Emphasis, child.TextAreas[1].TypeCode); 45 | Assert.Equal("also", child.TextAreas[1].Content.Text); 46 | Assert.Equal(ElementType.Text, child.TextAreas[2].TypeCode); 47 | Assert.Equal(" preserved.", child.TextAreas[2].Content.Text); 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /Tests/RealTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using Xunit; 4 | 5 | namespace Lextm.ReStructuredText.Tests 6 | { 7 | public class RealTest 8 | { 9 | [Fact] 10 | public void TestDockPanelSuite() 11 | { 12 | var path = "/Users/lextm/dockpanelsuite_docs"; 13 | if (Directory.Exists(path)) 14 | { 15 | foreach (string file in Directory.EnumerateFiles( 16 | path, "*.rst", SearchOption.AllDirectories)) 17 | { 18 | try 19 | { 20 | var result = ReStructuredTextParser.ParseDocument(file); 21 | } 22 | catch (Exception ex) 23 | { 24 | Assert.Equal(path, file); 25 | } 26 | } 27 | } 28 | } 29 | 30 | [Fact] 31 | public void TestJexus() 32 | { 33 | var path = "/Users/lextm/jexus_docs"; 34 | if (Directory.Exists(path)) 35 | { 36 | foreach (string file in Directory.EnumerateFiles( 37 | path, "*.rst", SearchOption.AllDirectories)) 38 | { 39 | try 40 | { 41 | var result = ReStructuredTextParser.ParseDocument(file); 42 | } 43 | catch (Exception ex) 44 | { 45 | Assert.Equal(path, file); 46 | } 47 | } 48 | } 49 | } 50 | 51 | [Fact] 52 | public void TestObfuscar() 53 | { 54 | var path = "/Users/lextm/obfuscar_docs"; 55 | if (Directory.Exists(path)) 56 | { 57 | foreach (string file in Directory.EnumerateFiles( 58 | path, "*.rst", SearchOption.AllDirectories)) 59 | { 60 | try 61 | { 62 | var result = ReStructuredTextParser.ParseDocument(file); 63 | } 64 | catch (Exception ex) 65 | { 66 | Assert.Equal(path, file); 67 | } 68 | } 69 | } 70 | } 71 | } 72 | } -------------------------------------------------------------------------------- /Server/DiagnosticProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using LanguageServer.VsCode.Contracts; 4 | using LanguageServer.VsCode.Server; 5 | using Range = LanguageServer.VsCode.Contracts.Range; 6 | 7 | namespace Lextm.ReStructuredText.LanguageServer 8 | { 9 | public class DiagnosticProvider 10 | { 11 | private static readonly string[] Keywords = 12 | {".NET Framework", ".NET Core", ".NET Standard", ".NET Compact", ".NET"}; 13 | 14 | public ICollection LintDocument(TextDocument document, int maxNumberOfProblems) 15 | { 16 | var diag = new List(); 17 | var content = document.Content; 18 | if (string.IsNullOrWhiteSpace(content)) 19 | { 20 | diag.Add(new Diagnostic(DiagnosticSeverity.Hint, 21 | new Range(new Position(0, 0), document.PositionAt(content?.Length ?? 0)), 22 | "DLS", "DLS0001", "Empty document. Try typing something, such as \".net core\".")); 23 | return diag; 24 | } 25 | foreach (var kw in Keywords) 26 | { 27 | int pos = 0; 28 | while (pos < content.Length) 29 | { 30 | pos = content.IndexOf(kw, pos, StringComparison.CurrentCultureIgnoreCase); 31 | if (pos < 0) break; 32 | var separatorPos = pos + kw.Length; 33 | if (separatorPos < content.Length && char.IsLetterOrDigit(content, separatorPos)) 34 | continue; 35 | var inputKw = content.Substring(pos, kw.Length); 36 | if (inputKw != kw) 37 | { 38 | diag.Add(new Diagnostic(DiagnosticSeverity.Warning, 39 | new Range(document.PositionAt(pos), document.PositionAt(separatorPos)), "DLS", "DLS1001", $"\"{inputKw}\" should be \"{kw}\".")); 40 | if (diag.Count >= maxNumberOfProblems) 41 | { 42 | diag.Add(new Diagnostic(DiagnosticSeverity.Information, 43 | new Range(document.PositionAt(pos), document.PositionAt(separatorPos)), "DLS", "DLS2001", "Too many messages, exiting…")); 44 | return diag; 45 | } 46 | } 47 | pos++; 48 | } 49 | } 50 | return diag; 51 | } 52 | } 53 | } -------------------------------------------------------------------------------- /ReStructuredText/DefinitionList.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace Lextm.ReStructuredText 5 | { 6 | public class DefinitionList : IElement 7 | { 8 | public DefinitionList(IList definitionListItems) 9 | { 10 | foreach (var item in definitionListItems) 11 | { 12 | Items.Add(item); 13 | item.Parent = this; 14 | } 15 | } 16 | 17 | public IList Items { get; } = new List(); 18 | 19 | public IParent Add(IElement element, int level = 0) 20 | { 21 | if (element is DefinitionListItem listItem) 22 | { 23 | Add(listItem); 24 | return listItem; 25 | } 26 | 27 | return Parent.Add(element); 28 | } 29 | 30 | public ElementType TypeCode => ElementType.DefinitionList; 31 | public IList TextAreas => Items[0].Term.TextAreas; 32 | 33 | public IParent Parent { get; set; } 34 | 35 | public int Indentation => Items[0].Term.TextAreas[0].Indentation; 36 | 37 | public IElement Find(int line, int column) 38 | { 39 | foreach (var item in Items) 40 | { 41 | var result = item.Find(line, column); 42 | if (result != null) 43 | { 44 | return result; 45 | } 46 | } 47 | 48 | return null; 49 | } 50 | 51 | public void Add(DefinitionListItem definitionListItem) 52 | { 53 | if (definitionListItem.Indentation == Indentation) 54 | { 55 | Items.Add(definitionListItem); 56 | definitionListItem.Parent = this; 57 | } 58 | else if (definitionListItem.Indentation > Indentation) 59 | { 60 | if (!(Items.Last().Definition.Elements.Last() is DefinitionList sublist)) 61 | { 62 | sublist = new DefinitionList(new List {definitionListItem}); 63 | sublist.Parent = this; 64 | Items.Last().Definition.Elements.Add(sublist); 65 | } 66 | else 67 | { 68 | sublist.Add(definitionListItem); 69 | } 70 | } 71 | else 72 | { 73 | Parent.Add(definitionListItem); 74 | } 75 | } 76 | } 77 | } -------------------------------------------------------------------------------- /ReStructuredText/Comment.cs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2017 Lex Li 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this 4 | // software and associated documentation files (the "Software"), to deal in the Software 5 | // without restriction, including without limitation the rights to use, copy, modify, merge, 6 | // publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons 7 | // to whom the Software is furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in all copies or 10 | // substantial portions of the Software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 13 | // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 14 | // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE 15 | // FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 16 | // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 17 | // DEALINGS IN THE SOFTWARE. 18 | 19 | using System.Collections.Generic; 20 | using System.Linq; 21 | 22 | namespace Lextm.ReStructuredText 23 | { 24 | public class Comment : IElement 25 | { 26 | public IList TextAreas { get; } 27 | 28 | public Comment(IList lines) 29 | { 30 | TextAreas = new List(); 31 | bool skip = true; 32 | foreach (var line in lines) 33 | { 34 | if (string.IsNullOrWhiteSpace(line.Content.Text)) 35 | { 36 | if (skip) 37 | { 38 | continue; 39 | } 40 | } 41 | 42 | skip = false; 43 | TextAreas.Add(line); 44 | } 45 | } 46 | 47 | public ElementType TypeCode => ElementType.Comment; 48 | 49 | public IParent Parent { get; set; } 50 | 51 | public IElement Find(int line, int column) 52 | { 53 | var first = TextAreas.First(); 54 | var last = TextAreas.Last(); 55 | if (line < first.Scope.LineStart || line > last.Scope.LineEnd) 56 | { 57 | return null; 58 | } 59 | 60 | return this; 61 | } 62 | 63 | public IParent Add(IElement element, int level = 0) 64 | { 65 | return Parent.Add(element); 66 | } 67 | 68 | public int Indentation { get; set; } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /ReStructuredText/BulletList.cs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2017 Lex Li 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this 4 | // software and associated documentation files (the "Software"), to deal in the Software 5 | // without restriction, including without limitation the rights to use, copy, modify, merge, 6 | // publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons 7 | // to whom the Software is furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in all copies or 10 | // substantial portions of the Software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 13 | // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 14 | // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE 15 | // FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 16 | // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 17 | // DEALINGS IN THE SOFTWARE. 18 | 19 | using System.Collections.Generic; 20 | using System.Linq; 21 | 22 | namespace Lextm.ReStructuredText 23 | { 24 | public class BulletList : IElement 25 | { 26 | public IList Items { get; } 27 | 28 | public BulletList(ListItem listItem) 29 | { 30 | Items = new List {listItem}; 31 | Start = listItem.Start; 32 | listItem.Parent = this; 33 | } 34 | 35 | public ElementType TypeCode => ElementType.BulletList; 36 | public IList TextAreas { get; } 37 | public IParent Parent { get; set; } 38 | public char Start { get; } 39 | 40 | public IParent Add(IElement current, int level = 0) 41 | { 42 | if (current is ListItem item) 43 | { 44 | if (item.Start == Start) 45 | { 46 | Items.Add(item); 47 | item.Parent = this; 48 | return item; 49 | } 50 | } 51 | 52 | return Parent.Add(current); 53 | } 54 | 55 | public int Indentation => Items[0].Indentation; 56 | 57 | public IElement Find(int line, int column) 58 | { 59 | foreach (var item in Items) 60 | { 61 | var result = item.Find(line, column); 62 | if (result != null) 63 | { 64 | return result; 65 | } 66 | } 67 | 68 | return null; 69 | } 70 | } 71 | } -------------------------------------------------------------------------------- /ReStructuredText/LineBlock.cs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2017 Lex Li 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this 4 | // software and associated documentation files (the "Software"), to deal in the Software 5 | // without restriction, including without limitation the rights to use, copy, modify, merge, 6 | // publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons 7 | // to whom the Software is furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in all copies or 10 | // substantial portions of the Software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 13 | // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 14 | // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE 15 | // FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 16 | // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 17 | // DEALINGS IN THE SOFTWARE. 18 | 19 | using System.Collections.Generic; 20 | 21 | namespace Lextm.ReStructuredText 22 | { 23 | public class LineBlock : IElement 24 | { 25 | public ElementType TypeCode => ElementType.LineBlock; 26 | public IList TextAreas => Elements[0].TextAreas; 27 | public IParent Parent { get; set; } 28 | public IList Elements { get; } 29 | 30 | public LineBlock(IList lines) 31 | { 32 | Elements = new List(); 33 | // TODO: improve indentation parsing. 34 | foreach (var line in lines) 35 | { 36 | if (line.TextAreas[0].IsIndented) 37 | { 38 | line.TextAreas[0].Indentation = 0; 39 | Elements.Add(new LineBlock(new[] {line})); 40 | continue; 41 | } 42 | 43 | Elements.Add(line); 44 | } 45 | } 46 | 47 | public IElement Find(int line, int column) 48 | { 49 | foreach (var item in Elements) 50 | { 51 | var result = item.Find(line, column); 52 | if (result != null) 53 | { 54 | return result; 55 | } 56 | } 57 | 58 | return null; 59 | } 60 | 61 | public IParent Add(IElement element, int level = 0) 62 | { 63 | return Parent.Add(element); 64 | } 65 | 66 | public int Indentation => Elements[0].Indentation; 67 | } 68 | } -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | /Tests/Input/* text eol=lf 6 | 7 | ############################################################################### 8 | # Set default behavior for command prompt diff. 9 | # 10 | # This is need for earlier builds of msysgit that does not have it on by 11 | # default for csharp files. 12 | # Note: This is only used by command line 13 | ############################################################################### 14 | #*.cs diff=csharp 15 | 16 | ############################################################################### 17 | # Set the merge driver for project and solution files 18 | # 19 | # Merging from the command prompt will add diff markers to the files if there 20 | # are conflicts (Merging from VS is not affected by the settings below, in VS 21 | # the diff markers are never inserted). Diff markers may cause the following 22 | # file extensions to fail to load in VS. An alternative would be to treat 23 | # these files as binary and thus will always conflict and require user 24 | # intervention with every merge. To do so, just uncomment the entries below 25 | ############################################################################### 26 | #*.sln merge=binary 27 | #*.csproj merge=binary 28 | #*.vbproj merge=binary 29 | #*.vcxproj merge=binary 30 | #*.vcproj merge=binary 31 | #*.dbproj merge=binary 32 | #*.fsproj merge=binary 33 | #*.lsproj merge=binary 34 | #*.wixproj merge=binary 35 | #*.modelproj merge=binary 36 | #*.sqlproj merge=binary 37 | #*.wwaproj merge=binary 38 | 39 | ############################################################################### 40 | # behavior for image files 41 | # 42 | # image files are treated as binary by default. 43 | ############################################################################### 44 | #*.jpg binary 45 | #*.png binary 46 | #*.gif binary 47 | 48 | ############################################################################### 49 | # diff behavior for common document formats 50 | # 51 | # Convert binary document formats to text before diffing them. This feature 52 | # is only available from the command line. Turn it on by uncommenting the 53 | # entries below. 54 | ############################################################################### 55 | #*.doc diff=astextplain 56 | #*.DOC diff=astextplain 57 | #*.docx diff=astextplain 58 | #*.DOCX diff=astextplain 59 | #*.dot diff=astextplain 60 | #*.DOT diff=astextplain 61 | #*.pdf diff=astextplain 62 | #*.PDF diff=astextplain 63 | #*.rtf diff=astextplain 64 | #*.RTF diff=astextplain 65 | -------------------------------------------------------------------------------- /Tests/InlineMarkupInterpretedTextTest.cs: -------------------------------------------------------------------------------- 1 | using Xunit; 2 | 3 | namespace Lextm.ReStructuredText.Tests 4 | { 5 | public class InlineMarkupInterpretedTextTest 6 | { 7 | [Fact] 8 | public void Simple() 9 | { 10 | var document = TestUtils.Test("inlinemarkupinterpretedtext_simple"); 11 | Assert.Equal(1, document.Elements.Count); 12 | Assert.Equal(ElementType.Paragraph, document.Elements[0].TypeCode); 13 | 14 | var paragraph = (Paragraph) document.Elements[0]; 15 | Assert.Equal(2, paragraph.TextAreas.Count); 16 | Assert.Equal(ElementType.InterpretedText, paragraph.TextAreas[0].TypeCode); 17 | Assert.Equal("interpreted", paragraph.TextAreas[0].Content.Text); 18 | } 19 | 20 | [Fact] 21 | public void Titled() 22 | { 23 | var document = TestUtils.Test("inlinemarkupinterpretedtext_titled"); 24 | Assert.Equal(1, document.Elements.Count); 25 | Assert.Equal(ElementType.Paragraph, document.Elements[0].TypeCode); 26 | 27 | var paragraph = (Paragraph) document.Elements[0]; 28 | Assert.Equal(2, paragraph.TextAreas.Count); 29 | Assert.Equal(ElementType.InterpretedText, paragraph.TextAreas[0].TypeCode); 30 | var interpreted = (InterpretedText) paragraph.TextAreas[0]; 31 | Assert.Equal("title", interpreted.RoleName); 32 | Assert.Equal("interpreted", paragraph.TextAreas[0].Content.Text); 33 | } 34 | 35 | [Fact] 36 | public void Multiple() 37 | { 38 | var document = TestUtils.Test("inlinemarkupinterpretedtext_multiple"); 39 | Assert.Equal(1, document.Elements.Count); 40 | Assert.Equal(ElementType.Paragraph, document.Elements[0].TypeCode); 41 | 42 | var paragraph = (Paragraph) document.Elements[0]; 43 | Assert.Equal(4, paragraph.TextAreas.Count); 44 | Assert.Equal(ElementType.InterpretedText, paragraph.TextAreas[0].TypeCode); 45 | var foo = (InterpretedText) paragraph.TextAreas[0]; 46 | Assert.Equal("foo", paragraph.TextAreas[0].Content.Text); 47 | 48 | Assert.Equal(ElementType.Text, paragraph.TextAreas[1].TypeCode); 49 | Assert.Equal(" ", paragraph.TextAreas[1].Content.Text); 50 | 51 | Assert.Equal(ElementType.InterpretedText, paragraph.TextAreas[2].TypeCode); 52 | var bar = (InterpretedText) paragraph.TextAreas[2]; 53 | Assert.Equal("x", bar.RoleName); 54 | Assert.Equal("bar", paragraph.TextAreas[2].Content.Text); 55 | 56 | Assert.Equal(ElementType.Text, paragraph.TextAreas[3].TypeCode); 57 | Assert.Equal(" :x:y\n", paragraph.TextAreas[3].Content.Text); 58 | } 59 | } 60 | } -------------------------------------------------------------------------------- /ReStructuredText/LiteralBlock.cs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2017 Lex Li 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this 4 | // software and associated documentation files (the "Software"), to deal in the Software 5 | // without restriction, including without limitation the rights to use, copy, modify, merge, 6 | // publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons 7 | // to whom the Software is furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in all copies or 10 | // substantial portions of the Software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 13 | // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 14 | // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE 15 | // FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 16 | // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 17 | // DEALINGS IN THE SOFTWARE. 18 | 19 | using System.Collections.Generic; 20 | using System.Linq; 21 | 22 | namespace Lextm.ReStructuredText 23 | { 24 | public class LiteralBlock : IElement 25 | { 26 | public LiteralBlock(IList lines) 27 | { 28 | TextAreas = lines; 29 | var minimal = lines[0].Indentation; 30 | foreach (var line in TextAreas) 31 | { 32 | line.Content.RemoveEnd(); 33 | if (line.Indentation < minimal) 34 | { 35 | minimal = line.Indentation; 36 | } 37 | } 38 | 39 | foreach (var line in TextAreas) 40 | { 41 | if (line.Indentation > minimal) 42 | { 43 | line.Content.Append(line.Indentation - minimal); 44 | line.Indentation = minimal; 45 | } 46 | } 47 | } 48 | 49 | public ElementType TypeCode => ElementType.LiteralBlock; 50 | public IList TextAreas { get; } 51 | public IParent Parent { get; set; } 52 | 53 | public IElement Find(int line, int column) 54 | { 55 | var first = TextAreas.First(); 56 | var last = TextAreas.Last(); 57 | if (line < first.Scope.LineStart || line > last.Scope.LineEnd) 58 | { 59 | return null; 60 | } 61 | 62 | return this; 63 | } 64 | 65 | public IParent Add(IElement element, int level = 0) 66 | { 67 | return Parent.Add(element); 68 | } 69 | 70 | public int Indentation => TextAreas[0].Indentation; 71 | } 72 | } -------------------------------------------------------------------------------- /Server/Services/TextDocumentService.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading; 3 | using System.Threading.Tasks; 4 | using JsonRpc.Contracts; 5 | using LanguageServer.VsCode; 6 | using LanguageServer.VsCode.Contracts; 7 | 8 | namespace Lextm.ReStructuredText.LanguageServer.Services 9 | { 10 | [JsonRpcScope(MethodPrefix = "textDocument/")] 11 | public class TextDocumentService : LanguageServiceBase 12 | { 13 | [JsonRpcMethod] 14 | public async Task Hover(TextDocumentIdentifier textDocument, Position position, CancellationToken ct) 15 | { 16 | // Note that Hover is cancellable. 17 | await Task.Delay(1000, ct); 18 | return new Hover {Contents = "Test _hover_ @" + position + "\n\n" + textDocument}; 19 | } 20 | 21 | [JsonRpcMethod] 22 | public SignatureHelp SignatureHelp(TextDocumentIdentifier textDocument, Position position) 23 | { 24 | return new SignatureHelp(new List 25 | { 26 | new SignatureInformation("**Function1**", "Documentation1"), 27 | new SignatureInformation("**Function2** test", "Documentation2"), 28 | }); 29 | } 30 | 31 | [JsonRpcMethod(IsNotification = true)] 32 | public void DidOpen(TextDocumentItem textDocument) 33 | { 34 | var doc = Session.AddOrUpdateDocument(textDocument); 35 | doc.RequestAnalysis(); 36 | } 37 | 38 | [JsonRpcMethod(IsNotification = true)] 39 | public void DidChange(TextDocumentIdentifier textDocument, 40 | ICollection contentChanges) 41 | { 42 | Session.DocumentStates[textDocument.Uri].NotifyChanges(contentChanges); 43 | } 44 | 45 | [JsonRpcMethod(IsNotification = true)] 46 | public void WillSave(TextDocumentIdentifier textDocument, TextDocumentSaveReason reason) 47 | { 48 | } 49 | 50 | [JsonRpcMethod(IsNotification = true)] 51 | public async Task DidClose(TextDocumentIdentifier textDocument) 52 | { 53 | Session.RemoveDocument(textDocument.Uri); 54 | if (textDocument.Uri.IsUntitled()) 55 | { 56 | await Session.Client.Document.PublishDiagnostics(textDocument.Uri, new Diagnostic[0]); 57 | } 58 | } 59 | 60 | 61 | [JsonRpcMethod] 62 | public CompletionList Completion(TextDocumentIdentifier textDocument, Position position, CompletionContext context) 63 | { 64 | var doc = Session.DocumentStates[textDocument.Uri]; 65 | doc.AnalyzeAsync(); 66 | return 67 | Session.Project.GetCompletionList(doc, position, context); //position, Session.PageInfoStore)); 68 | } 69 | } 70 | } -------------------------------------------------------------------------------- /ReStructuredText/EnumeratedList.cs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2017 Lex Li 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this 4 | // software and associated documentation files (the "Software"), to deal in the Software 5 | // without restriction, including without limitation the rights to use, copy, modify, merge, 6 | // publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons 7 | // to whom the Software is furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in all copies or 10 | // substantial portions of the Software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 13 | // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 14 | // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE 15 | // FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 16 | // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 17 | // DEALINGS IN THE SOFTWARE. 18 | 19 | using System.Collections.Generic; 20 | using System.Linq; 21 | 22 | namespace Lextm.ReStructuredText 23 | { 24 | public class EnumeratedList : IElement 25 | { 26 | public IList Items { get; } 27 | 28 | public EnumeratedList(ListItem item) 29 | { 30 | Items = new List{item}; 31 | item.Parent = this; 32 | } 33 | 34 | public ElementType TypeCode => ElementType.EnumeratedList; 35 | public IList TextAreas => Items[0].TextAreas; 36 | public IParent Parent { get; set; } 37 | 38 | public IParent Add(IElement current, int level = 0) 39 | { 40 | if (current is ListItem item) 41 | { 42 | if (item.Index == Items.Last().Index + 1) 43 | { 44 | Items.Add(item); 45 | item.Parent = this; 46 | return item; 47 | } 48 | 49 | if (item.CreateNewList) 50 | { 51 | var list = new EnumeratedList(item); 52 | Parent.Add(list); 53 | return item; 54 | } 55 | 56 | // downgrade to paragraph. 57 | current = new Paragraph(item.TextAreas); 58 | } 59 | 60 | return Parent.Add(current); 61 | } 62 | 63 | public int Indentation => Items[0].Indentation; 64 | 65 | public IElement Find(int line, int column) 66 | { 67 | foreach (var item in Items) 68 | { 69 | var result = item.Find(line, column); 70 | if (result != null) 71 | { 72 | return result; 73 | } 74 | } 75 | 76 | return null; 77 | } 78 | } 79 | } -------------------------------------------------------------------------------- /ReStructuredText/TextArea.cs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2017 Lex Li 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this 4 | // software and associated documentation files (the "Software"), to deal in the Software 5 | // without restriction, including without limitation the rights to use, copy, modify, merge, 6 | // publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons 7 | // to whom the Software is furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in all copies or 10 | // substantial portions of the Software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 13 | // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 14 | // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE 15 | // FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 16 | // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 17 | // DEALINGS IN THE SOFTWARE. 18 | 19 | using System.Collections.Generic; 20 | 21 | namespace Lextm.ReStructuredText 22 | { 23 | public class TextArea : ITextArea 24 | { 25 | public Content Content { get; } 26 | 27 | public bool IsIndented => Indentation > 0; 28 | 29 | public int Indentation { get; set; } 30 | 31 | public bool IsSection 32 | { 33 | get { 34 | var clean = Content.Text.TrimEnd(); 35 | var start = clean[0]; 36 | for (int i = 1; i < clean.Length; i++) 37 | { 38 | if (clean[i] != start) 39 | { 40 | return false; 41 | } 42 | } 43 | 44 | return true; 45 | } 46 | } 47 | 48 | public bool IsQuoted => Content.Text.StartsWith("> "); 49 | public ElementType TypeCode => ElementType.Text; 50 | 51 | public Scope Scope { get; } 52 | 53 | public TextArea(string content, Scope scope) 54 | { 55 | Content = new Content(content); 56 | Scope = scope; 57 | } 58 | 59 | public override string ToString() 60 | { 61 | return Content.Text; 62 | } 63 | 64 | public static IList Parse(string part, Scope scope) 65 | { 66 | var result = new List(); 67 | var lines = part.TrimEnd('\n').Split('\n'); 68 | if (lines.Length == 1) 69 | { 70 | result.Add(new TextArea(part, scope)); 71 | } 72 | else 73 | { 74 | for (int j = 0; j < lines.Length; j++) 75 | { 76 | result.Add(j == lines.Length - 1 77 | ? new TextArea(lines[j], scope) 78 | : new TextArea(lines[j] + '\n', scope)); 79 | } 80 | } 81 | 82 | return result; 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /Tests/InlineMarkupStrongEmphasisTest.cs: -------------------------------------------------------------------------------- 1 | using Xunit; 2 | 3 | namespace Lextm.ReStructuredText.Tests 4 | { 5 | public class InlineMarkupStrongEmphasisTest 6 | { 7 | [Fact] 8 | public void Apostrophe() 9 | { 10 | var document = TestUtils.Test("inlinemarkupstrongemphasis_apostrophe"); 11 | Assert.Equal(1, document.Elements.Count); 12 | Assert.Equal(ElementType.Paragraph, document.Elements[0].TypeCode); 13 | var paragraph = (Paragraph) document.Elements[0]; 14 | Assert.Equal(5, paragraph.TextAreas.Count); 15 | Assert.Equal(ElementType.Strong, paragraph.TextAreas[1].TypeCode); 16 | var literal = (Strong) paragraph.TextAreas[1]; 17 | Assert.Equal("strong", literal.Content.Text); 18 | var text = paragraph.TextAreas[2]; 19 | Assert.Equal(" and l\u2019", text.Content.Text); 20 | } 21 | 22 | [Fact] 23 | public void Quoted() 24 | { 25 | var document = TestUtils.Test("inlinemarkupstrongemphasis_quoted"); 26 | var paragraph = (Paragraph) document.Elements[0]; 27 | Assert.Equal("quoted '", paragraph.TextAreas[0].Content.Text); 28 | Assert.Equal("', quoted \"", paragraph.TextAreas[2].Content.Text); 29 | Assert.Equal("\",\n", paragraph.TextAreas[4].Content.Text); 30 | Assert.Equal("quoted \u2018", paragraph.TextAreas[5].Content.Text); 31 | Assert.Equal("\u2019, quoted \u201c", paragraph.TextAreas[7].Content.Text); 32 | Assert.Equal("\u201d,\n", paragraph.TextAreas[9].Content.Text); 33 | Assert.Equal("quoted \xab", paragraph.TextAreas[10].Content.Text); 34 | Assert.Equal("\xbb\n", paragraph.TextAreas[12].Content.Text); 35 | Assert.Equal(13, paragraph.TextAreas.Count); 36 | } 37 | 38 | [Fact] 39 | public void NotStrong() 40 | { 41 | var document = TestUtils.Test("inlinemarkupstrongemphasis_notstrong"); 42 | var paragraph = (Paragraph) document.Elements[0]; 43 | Assert.Equal("(", paragraph.TextAreas[0].Content.Text); 44 | Assert.Equal(") but not (**) or '(** ' or x**2 or \\**kwargs or **\n", paragraph.TextAreas[2].Content.Text); 45 | Assert.Equal(3, paragraph.TextAreas.Count); 46 | } 47 | 48 | [Fact] 49 | public void Asterisk() 50 | { 51 | var document = TestUtils.Test("inlinemarkupstrongemphasis_asterisk"); 52 | var paragraph = (Paragraph) document.Elements[0]; 53 | Assert.Equal("Strong asterisk: ", paragraph.TextAreas[0].Content.Text); 54 | Assert.Equal("*", paragraph.TextAreas[1].Content.Text); 55 | Assert.Equal("\n", paragraph.TextAreas[2].Content.Text); 56 | Assert.Equal(3, paragraph.TextAreas.Count); 57 | 58 | var paragraph2 = (Paragraph) document.Elements[1]; 59 | Assert.Equal("Strong double asterisk: ", paragraph2.TextAreas[0].Content.Text); 60 | Assert.Equal("**", paragraph2.TextAreas[1].Content.Text); 61 | Assert.Equal("\n", paragraph2.TextAreas[2].Content.Text); 62 | Assert.Equal(3, paragraph.TextAreas.Count); 63 | 64 | Assert.Equal(2, document.Elements.Count); 65 | } 66 | } 67 | } -------------------------------------------------------------------------------- /Tests/ParagraphTest.cs: -------------------------------------------------------------------------------- 1 | using Xunit; 2 | 3 | namespace Lextm.ReStructuredText.Tests 4 | { 5 | public class ParagraphTest 6 | { 7 | [Fact] 8 | public void Empty() 9 | { 10 | var document = TestUtils.Test("paragraph_empty"); 11 | Assert.Equal(0, document.Elements.Count); 12 | } 13 | 14 | [Fact] 15 | public void SingleLine() 16 | { 17 | var document = TestUtils.Test("paragraph_single"); 18 | Assert.Equal(1, document.Elements.Count); 19 | Assert.Equal("A paragraph.\n", document.Elements[0].TextAreas[0].Content.Text); 20 | } 21 | 22 | [Fact] 23 | public void SingleLineWithNewLine() 24 | { 25 | var document = TestUtils.Test("paragraph_single_newline"); 26 | Assert.Equal(1, document.Elements.Count); 27 | Assert.Equal("A paragraph.\n", document.Elements[0].TextAreas[0].Content.Text); 28 | } 29 | 30 | [Fact] 31 | public void MultipleLines() 32 | { 33 | var document = TestUtils.Test("paragraph_multiple"); 34 | Assert.Equal(1, document.Elements.Count); 35 | Assert.Equal("A paragraph.\n", document.Elements[0].TextAreas[0].Content.Text); 36 | } 37 | 38 | [Fact] 39 | public void MultipleSingleLines() 40 | { 41 | var document = TestUtils.Test("paragraph_multiplesinglelines"); 42 | Assert.Equal(2, document.Elements.Count); 43 | Assert.Equal("Paragraph 1.\n", document.Elements[0].TextAreas[0].Content.Text); 44 | Assert.Equal("Paragraph 2.\n", document.Elements[1].TextAreas[0].Content.Text); 45 | } 46 | 47 | [Fact] 48 | public void MultilineParagraph() 49 | { 50 | var document = TestUtils.Test("paragraph_multiline"); 51 | Assert.Equal(1, document.Elements.Count); 52 | Assert.Equal("Line 1.\n", document.Elements[0].TextAreas[0].Content.Text); 53 | Assert.Equal("Line 2.\n", document.Elements[0].TextAreas[1].Content.Text); 54 | Assert.Equal("Line 3.\n", document.Elements[0].TextAreas[2].Content.Text); 55 | } 56 | 57 | [Fact] 58 | public void MultilineParagraphs() 59 | { 60 | var document = TestUtils.Test("paragraph_multilines"); 61 | Assert.Equal(2, document.Elements.Count); 62 | Assert.Equal("Paragraph 1, Line 1.\n", document.Elements[0].TextAreas[0].Content.Text); 63 | Assert.Equal("Line 2.\n", document.Elements[0].TextAreas[1].Content.Text); 64 | Assert.Equal("Line 3.\n", document.Elements[0].TextAreas[2].Content.Text); 65 | Assert.Equal("Paragraph 2, Line 1.\n", document.Elements[1].TextAreas[0].Content.Text); 66 | Assert.Equal("Line 2.\n", document.Elements[1].TextAreas[1].Content.Text); 67 | Assert.Equal("Line 3.\n", document.Elements[1].TextAreas[2].Content.Text); 68 | } 69 | 70 | [Fact] 71 | public void SimpleParagraphs() 72 | { 73 | var document = TestUtils.Test("paragraph_simple"); 74 | Assert.Equal(1, document.Elements.Count); 75 | Assert.Equal("A. Einstein was a really\n", document.Elements[0].TextAreas[0].Content.Text); 76 | Assert.Equal("smart dude.\n", document.Elements[0].TextAreas[1].Content.Text); 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /ReStructuredText/BackTickText.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace Lextm.ReStructuredText 5 | { 6 | public class BackTickText : ITextArea 7 | { 8 | public string Title { get; set; } 9 | public Scope Scope { get; } 10 | 11 | private string _content; 12 | 13 | public BackTickText(string title, string content, Scope scope) 14 | { 15 | Title = title; 16 | Scope = scope; 17 | _content = content; 18 | } 19 | 20 | public bool IsIndented { get; } 21 | public Content Content { get; } 22 | public int Indentation 23 | { 24 | get; set; 25 | } 26 | 27 | public bool IsQuoted { get; } 28 | public ElementType TypeCode => ElementType.BackTickText; 29 | 30 | public void Process(IList list) 31 | { 32 | var content = _content; 33 | if (content.Length == 2) 34 | { 35 | list.Add(new InterpretedText(Title, new TextArea(string.Empty, Scope))); 36 | return; 37 | } 38 | 39 | int level = 0; 40 | var start = 0; 41 | var length = 0; 42 | var maxLevel = 0; 43 | for (int i = 0; i < content.Length; i++) 44 | { 45 | if (content[i] == '`') 46 | { 47 | if (length == 0) 48 | { 49 | // still in leading back ticks. 50 | level++; 51 | maxLevel = level; 52 | start = i; 53 | continue; 54 | } 55 | 56 | level--; 57 | if (level > 0) 58 | { 59 | // in ending back ticks. 60 | continue; 61 | } 62 | 63 | var part = content.Substring(start + 1, length); 64 | if (maxLevel == 2) 65 | { 66 | list.Add(new Literal(new TextArea(part, Scope))); 67 | } 68 | else if (maxLevel == 1) 69 | { 70 | var title = Title; 71 | if (title == null) 72 | { 73 | var last = list.LastOrDefault(); 74 | if (last is TextArea text) 75 | { 76 | title = text.Content.RemoveTitle(); 77 | } 78 | } 79 | else 80 | { 81 | // pick up title. 82 | Title = null; 83 | } 84 | 85 | list.Add(new InterpretedText(title, new TextArea(part, Scope))); 86 | } 87 | else if (maxLevel == 0) 88 | { 89 | list.Add(new TextArea(part, Scope)); 90 | } 91 | else 92 | { 93 | list.Add(new Literal(new TextArea($"`{part}`", Scope))); 94 | } 95 | 96 | maxLevel = 0; 97 | if (level < 0) 98 | { 99 | // restart 100 | maxLevel = level = 1; 101 | } 102 | 103 | length = 0; 104 | start = i; 105 | continue; 106 | } 107 | 108 | length++; 109 | } 110 | } 111 | } 112 | } -------------------------------------------------------------------------------- /ReStructuredText/ListItem.cs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2017 Lex Li 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this 4 | // software and associated documentation files (the "Software"), to deal in the Software 5 | // without restriction, including without limitation the rights to use, copy, modify, merge, 6 | // publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons 7 | // to whom the Software is furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in all copies or 10 | // substantial portions of the Software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 13 | // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 14 | // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE 15 | // FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 16 | // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 17 | // DEALINGS IN THE SOFTWARE. 18 | 19 | using System.Collections.Generic; 20 | 21 | namespace Lextm.ReStructuredText 22 | { 23 | public class ListItem : IElement 24 | { 25 | public IList Elements { get; } 26 | 27 | public ListItem(string start, string enumerator, IList elements) 28 | { 29 | Start = start?[0] ?? char.MinValue; 30 | Enumerator = enumerator; 31 | if (enumerator != null) 32 | { 33 | Index = int.Parse(Enumerator.TrimEnd('.', ' ')); 34 | } 35 | 36 | Elements = elements; 37 | foreach (var item in Elements) 38 | { 39 | item.Parent = this; 40 | } 41 | } 42 | 43 | public IParent Add(IElement element, int level = 0) 44 | { 45 | if (Enumerator == null) 46 | { 47 | if (element.Indentation == Indentation + 2) 48 | { 49 | Elements.Add(element); 50 | element.Parent = this; 51 | return element; 52 | } 53 | } 54 | else 55 | { 56 | if (element.Indentation == Indentation + 3) 57 | { 58 | Elements.Add(element); 59 | element.Parent = this; 60 | return element; 61 | } 62 | } 63 | 64 | return Parent.Add(element); 65 | } 66 | 67 | public int Indentation { get; set; } 68 | 69 | public char Start { get; } 70 | public string Enumerator { get; } 71 | public int Index { get; } 72 | 73 | public ElementType TypeCode => ElementType.ListItem; 74 | public IList TextAreas => Elements[0].TextAreas; 75 | 76 | public IElement Find(int line, int column) 77 | { 78 | foreach (var item in Elements) 79 | { 80 | var result = item.Find(line, column); 81 | if (result != null) 82 | { 83 | return result; 84 | } 85 | } 86 | 87 | return null; 88 | } 89 | 90 | public IParent Parent { get; set; } 91 | 92 | internal int LineNumber { get; set; } 93 | 94 | internal bool CreateNewList { get; set; } = true; 95 | 96 | public void Analyze(ListItem next) 97 | { 98 | if (next.LineNumber == LineNumber + 1) 99 | { 100 | if (next.Index < Index) 101 | { 102 | CreateNewList = false; 103 | } 104 | else if (next.Index == Index + 1) 105 | { 106 | } 107 | else 108 | { 109 | CreateNewList = false; 110 | } 111 | } 112 | } 113 | 114 | public void Add(IElement element) 115 | { 116 | Parent.Add(element); 117 | } 118 | } 119 | } -------------------------------------------------------------------------------- /ReStructuredText/Content.cs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2017 Lex Li 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this 4 | // software and associated documentation files (the "Software"), to deal in the Software 5 | // without restriction, including without limitation the rights to use, copy, modify, merge, 6 | // publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons 7 | // to whom the Software is furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in all copies or 10 | // substantial portions of the Software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 13 | // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 14 | // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE 15 | // FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 16 | // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 17 | // DEALINGS IN THE SOFTWARE. 18 | 19 | using System; 20 | using System.Globalization; 21 | using System.Text; 22 | using System.Text.RegularExpressions; 23 | 24 | namespace Lextm.ReStructuredText 25 | { 26 | public class Content 27 | { 28 | public Content(string text) 29 | { 30 | Text = text; 31 | Unescape(); 32 | } 33 | 34 | internal void RemoveAttribution() 35 | { 36 | if (Text.StartsWith("---")) 37 | { 38 | Text = Text.Substring("---".Length).TrimStart(); 39 | return; 40 | } 41 | 42 | if (Text.StartsWith("--")) 43 | { 44 | Text = Text.Substring("--".Length).TrimStart(); 45 | return; 46 | } 47 | 48 | if (Text.StartsWith("\u2014")) 49 | { 50 | Text = Text.Substring("\u2014".Length).TrimStart(); 51 | return; 52 | } 53 | } 54 | 55 | public string Text { get; private set; } 56 | public bool IsSection 57 | { 58 | get 59 | { 60 | var pure = Text.TrimEnd(); 61 | foreach (var item in pure) 62 | { 63 | if (item != Text[0]) 64 | { 65 | return false; 66 | } 67 | } 68 | 69 | return true; 70 | } 71 | } 72 | 73 | public void RemoveStart() 74 | { 75 | Text = Text.TrimStart(); 76 | } 77 | 78 | public void RemoveEnd() 79 | { 80 | Text = Text.TrimEnd(' ', '\r', '\n'); 81 | } 82 | 83 | public void RemoveLiteral() 84 | { 85 | Text = Text.TrimEnd().TrimEnd(':'); 86 | } 87 | 88 | public void Append(int indentation) 89 | { 90 | var builder = new StringBuilder(Text.Length + indentation); 91 | for (int i = 0; i < indentation; i++) 92 | { 93 | builder.Append(' '); 94 | } 95 | 96 | Text = builder.Append(Text).ToString(); 97 | } 98 | 99 | public void Append(string text) 100 | { 101 | Text = Text + text; 102 | } 103 | 104 | public void Unescape() 105 | { 106 | Regex regex = new Regex (@"\\[Ux]([0-9A-F]{2,4})", RegexOptions.IgnoreCase); 107 | Text = regex.Replace (Text, match => ((char)int.Parse (match.Groups[1].Value, 108 | NumberStyles.HexNumber)).ToString ()); 109 | } 110 | 111 | public string RemoveTitle() 112 | { 113 | var regex = new Regex(":(?.*):$"); 114 | var match = regex.Match(Text); 115 | if (!match.Success) 116 | { 117 | return null; 118 | } 119 | 120 | var title = match.Groups["title"].Value; 121 | Text = regex.Replace(Text, string.Empty); 122 | return title; 123 | } 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /Server/Program.cs: -------------------------------------------------------------------------------- 1 | //#define WAIT_FOR_DEBUGGER 2 | 3 | using System; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Reflection; 7 | using JsonRpc.Client; 8 | using JsonRpc.Contracts; 9 | using JsonRpc.Server; 10 | using JsonRpc.Streams; 11 | using LanguageServer.VsCode; 12 | using Microsoft.Extensions.Logging; 13 | 14 | namespace Lextm.ReStructuredText.LanguageServer 15 | { 16 | internal class Program 17 | { 18 | public static void Main(string[] args) 19 | { 20 | var debugMode = args.Any(a => a.Equals("--debug", StringComparison.OrdinalIgnoreCase)); 21 | #if WAIT_FOR_DEBUGGER 22 | while (!Debugger.IsAttached) Thread.Sleep(5000); 23 | Debugger.Break(); 24 | #endif 25 | StreamWriter logWriter = null; 26 | if (debugMode) 27 | { 28 | logWriter = File.CreateText("messages-" + DateTime.Now.ToString("yyyyMMddHHmmss") + ".log"); 29 | logWriter.AutoFlush = true; 30 | } 31 | 32 | using (logWriter) 33 | using (var cin = Console.OpenStandardInput()) 34 | using (var bcin = new BufferedStream(cin)) 35 | using (var cout = Console.OpenStandardOutput()) 36 | using (var reader = new PartwiseStreamMessageReader(bcin)) 37 | using (var writer = new PartwiseStreamMessageWriter(cout)) 38 | { 39 | var contractResolver = new JsonRpcContractResolver 40 | { 41 | NamingStrategy = new CamelCaseJsonRpcNamingStrategy(), 42 | ParameterValueConverter = new CamelCaseJsonValueConverter(), 43 | }; 44 | var clientHandler = new StreamRpcClientHandler(); 45 | var client = new JsonRpcClient(clientHandler); 46 | if (debugMode) 47 | { 48 | // We want to capture log all the LSP server-to-client calls as well 49 | clientHandler.MessageSending += (_, e) => 50 | { 51 | lock (logWriter) logWriter.WriteLine("<C{0}", e.Message); 52 | }; 53 | clientHandler.MessageReceiving += (_, e) => 54 | { 55 | lock (logWriter) logWriter.WriteLine(">C{0}", e.Message); 56 | }; 57 | } 58 | 59 | // Configure & build service host 60 | var session = new SessionState(client, contractResolver); 61 | var host = BuildServiceHost(logWriter, contractResolver, debugMode); 62 | var serverHandler = new StreamRpcServerHandler(host, 63 | StreamRpcServerHandlerOptions.ConsistentResponseSequence | 64 | StreamRpcServerHandlerOptions.SupportsRequestCancellation); 65 | serverHandler.DefaultFeatures.Set(session); 66 | // If we want server to stop, just stop the "source" 67 | using (serverHandler.Attach(reader, writer)) 68 | using (clientHandler.Attach(reader, writer)) 69 | { 70 | // Wait for the "stop" request. 71 | session.CancellationToken.WaitHandle.WaitOne(); 72 | } 73 | 74 | logWriter?.WriteLine("Exited"); 75 | } 76 | } 77 | 78 | private static IJsonRpcServiceHost BuildServiceHost(TextWriter logWriter, 79 | IJsonRpcContractResolver contractResolver, bool debugMode) 80 | { 81 | var loggerFactory = LoggerFactory.Create(builder => builder.AddDebug()); 82 | if (debugMode) 83 | { 84 | loggerFactory.AddFile("logs-" + DateTime.Now.ToString("yyyyMMddHHmmss") + ".log"); 85 | } 86 | 87 | var builder = new JsonRpcServiceHostBuilder 88 | { 89 | ContractResolver = contractResolver, 90 | LoggerFactory = loggerFactory 91 | }; 92 | builder.UseCancellationHandling(); 93 | builder.Register(typeof(Program).GetTypeInfo().Assembly); 94 | if (debugMode) 95 | { 96 | // Log all the client-to-server calls. 97 | builder.Intercept(async (context, next) => 98 | { 99 | lock (logWriter) logWriter.WriteLine("> {0}", context.Request); 100 | await next(); 101 | lock (logWriter) logWriter.WriteLine("< {0}", context.Response); 102 | }); 103 | } 104 | 105 | return builder.Build(); 106 | } 107 | 108 | } 109 | } -------------------------------------------------------------------------------- /ReStructuredText/Section.cs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2017 Lex Li 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this 4 | // software and associated documentation files (the "Software"), to deal in the Software 5 | // without restriction, including without limitation the rights to use, copy, modify, merge, 6 | // publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons 7 | // to whom the Software is furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in all copies or 10 | // substantial portions of the Software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 13 | // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 14 | // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE 15 | // FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 16 | // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 17 | // DEALINGS IN THE SOFTWARE. 18 | 19 | using System.Collections.Generic; 20 | using System.Linq; 21 | 22 | namespace Lextm.ReStructuredText 23 | { 24 | public class Section : IElement, IParent 25 | { 26 | public int Level { get; } 27 | public IList<IElement> Elements { get; } 28 | public IList<ITextArea> Title { get; set; } 29 | 30 | public bool Overline { get; } 31 | 32 | public Section(int level, IList<ITextArea> title, IList<IElement> content, bool overline) 33 | { 34 | Title = new List<ITextArea>(); 35 | foreach (var area in title) 36 | { 37 | if (area.TypeCode == ElementType.BackTickText) 38 | { 39 | ((BackTickText)area).Process(TextAreas); 40 | } 41 | else if (area.TypeCode == ElementType.StarText) 42 | { 43 | ((StarText)area).Process(Title); 44 | } 45 | else 46 | { 47 | Title.Add(area); 48 | } 49 | } 50 | 51 | Title.First().Content.RemoveStart(); 52 | Title.Last().Content.RemoveEnd(); 53 | if (Title.Last().Content.Text.Length == 0) 54 | { 55 | Title.Remove(Title.Last()); 56 | } 57 | 58 | Level = level; 59 | Elements = new List<IElement>(); 60 | Overline = overline; 61 | foreach (var item in content) 62 | { 63 | item.Parent = this; 64 | if (item.TextAreas.Count == 0) 65 | { 66 | continue; 67 | } 68 | 69 | Elements.Add(item); 70 | } 71 | } 72 | 73 | public ElementType TypeCode => ElementType.Section; 74 | 75 | public IList<ITextArea> TextAreas => Title; 76 | 77 | public IParent Parent { get; set; } 78 | 79 | public IParent Add(IElement current, int level = 0) 80 | { 81 | if (!(current is Section section) || section.Level == Level + 1) 82 | { 83 | Elements.Add(current); 84 | current.Parent = this; 85 | return current; 86 | } 87 | 88 | if (section.Level <= Level) 89 | { 90 | return Parent?.Add(current); 91 | } 92 | else 93 | { 94 | var child = Elements.LastOrDefault() as Section; 95 | return child?.Add(current); 96 | } 97 | } 98 | 99 | public int Indentation => Title[0].Indentation; 100 | 101 | public IElement Find(int line, int column) 102 | { 103 | var first = Title.First(); 104 | if (Overline && line == first.Scope.LineStart - 1) 105 | { 106 | return this; 107 | } 108 | 109 | if (line < first.Scope.LineStart) 110 | { 111 | return null; 112 | } 113 | 114 | foreach (var item in Elements) 115 | { 116 | if (line < item.TextAreas.First().Scope.LineStart) 117 | { 118 | return this; 119 | } 120 | 121 | var result = item.Find(line, column); 122 | if (result != null) 123 | { 124 | return result; 125 | } 126 | } 127 | 128 | return null; 129 | } 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /Tests/BulletListTest.cs: -------------------------------------------------------------------------------- 1 | using Xunit; 2 | 3 | namespace Lextm.ReStructuredText.Tests 4 | { 5 | public class BulletListTest 6 | { 7 | [Fact] 8 | public void Single() 9 | { 10 | var document = TestUtils.Test("bulletlist_single"); 11 | Assert.Equal(1, document.Elements.Count); 12 | 13 | var list = (BulletList) document.Elements[0]; 14 | Assert.Equal(1, list.Items.Count); 15 | Assert.Equal("item\n", list.Items[0].Elements[0].TextAreas[0].Content.Text); 16 | } 17 | 18 | [Fact] 19 | public void Multiple() 20 | { 21 | var document = TestUtils.Test("bulletlist_multiple"); 22 | Assert.Equal(1, document.Elements.Count); 23 | 24 | var list = (BulletList) document.Elements[0]; 25 | Assert.Equal(2, list.Items.Count); 26 | Assert.Equal('*', list.Start); 27 | Assert.Equal("item 1\n", list.Items[0].Elements[0].TextAreas[0].Content.Text); 28 | Assert.Equal("item 2\n", list.Items[1].Elements[0].TextAreas[0].Content.Text); 29 | } 30 | 31 | [Fact] 32 | public void MultipleNoBlankLine() 33 | { 34 | var document = TestUtils.Test("bulletlist_multiple_noblankline"); 35 | Assert.Equal(2, document.Elements.Count); 36 | Assert.Equal("No blank line between:\n", document.Elements[0].TextAreas[0].Content.Text); 37 | 38 | var list = (BulletList) document.Elements[1]; 39 | Assert.Equal(2, list.Items.Count); 40 | Assert.Equal('+', list.Start); 41 | Assert.Equal("item 1\n", list.Items[0].Elements[0].TextAreas[0].Content.Text); 42 | Assert.Equal("item 2\n", list.Items[1].Elements[0].TextAreas[0].Content.Text); 43 | } 44 | 45 | [Fact] 46 | public void MultiLineBody() 47 | { 48 | var document = TestUtils.Test("bulletlist_multilinebody"); 49 | Assert.Equal(1, document.Elements.Count); 50 | 51 | var list = (BulletList)document.Elements[0]; 52 | Assert.Equal(2, list.Items.Count); 53 | 54 | var item = list.Items[0]; 55 | Assert.Equal(2, item.Elements.Count); 56 | 57 | Assert.Equal("item 1, para 1.\n", item.Elements[0].TextAreas[0].Content.Text); 58 | Assert.Equal("item 1, para 2.\n", item.Elements[1].TextAreas[0].Content.Text); 59 | 60 | Assert.Equal("item 2\n", list.Items[1].Elements[0].TextAreas[0].Content.Text); 61 | } 62 | 63 | [Fact] 64 | public void MultiLineBodyWithNoBlankLine() 65 | { 66 | var document = TestUtils.Test("bulletlist_multilinebody_noblankline"); 67 | Assert.Equal(1, document.Elements.Count); 68 | 69 | var list = (BulletList)document.Elements[0]; 70 | Assert.Equal(2, list.Items.Count); 71 | 72 | var item = list.Items[0]; 73 | Assert.Equal(1, item.Elements.Count); 74 | 75 | Assert.Equal("item 1, para 1.\n", item.Elements[0].TextAreas[0].Content.Text); 76 | Assert.Equal("item 1, para 2.\n", item.Elements[0].TextAreas[1].Content.Text); 77 | 78 | Assert.Equal("item 2\n", list.Items[1].Elements[0].TextAreas[0].Content.Text); 79 | } 80 | 81 | [Fact] 82 | public void DifferentMarker() 83 | { 84 | var document = TestUtils.Test("bulletlist_differentmarker"); 85 | Assert.Equal(5, document.Elements.Count); 86 | 87 | Assert.Equal("item 1\n", ((BulletList)document.Elements[1]).Items[0].Elements[0].TextAreas[0].Content.Text); 88 | Assert.Equal("item 2\n", ((BulletList)document.Elements[2]).Items[0].Elements[0].TextAreas[0].Content.Text); 89 | Assert.Equal("item 3\n", ((BulletList)document.Elements[3]).Items[0].Elements[0].TextAreas[0].Content.Text); 90 | Assert.Equal("item 4\n", ((BulletList)document.Elements[4]).Items[0].Elements[0].TextAreas[0].Content.Text); 91 | } 92 | 93 | [Fact] 94 | public void EmptyItemAbove() 95 | { 96 | var document = TestUtils.Test("bulletlist_emptyitemabove"); 97 | // TODO: Read the spec to know if this is supported. 98 | Assert.Equal(2, document.Elements.Count); 99 | } 100 | 101 | [Fact] 102 | public void Unicode() 103 | { 104 | var document = TestUtils.Test("bulletlist_unicode"); 105 | // TODO: read the spec to confirm the characters. 106 | Assert.Equal(4, document.Elements.Count); 107 | } 108 | 109 | [Fact] 110 | public void BeginWithNewLine() 111 | { 112 | var document = TestUtils.Test("bulletlist_beginwithnewline"); 113 | // TODO: read the spec to confirm this is supported. 114 | Assert.Equal(1, document.Elements.Count); 115 | } 116 | } 117 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | bld/ 21 | [Bb]in/ 22 | [Oo]bj/ 23 | [Ll]og/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | project.fragment.lock.json 46 | artifacts/ 47 | 48 | *_i.c 49 | *_p.c 50 | *_i.h 51 | *.ilk 52 | *.meta 53 | *.obj 54 | *.pch 55 | *.pdb 56 | *.pgc 57 | *.pgd 58 | *.rsp 59 | *.sbr 60 | *.tlb 61 | *.tli 62 | *.tlh 63 | *.tmp 64 | *.tmp_proj 65 | *.log 66 | *.vspscc 67 | *.vssscc 68 | .builds 69 | *.pidb 70 | *.svclog 71 | *.scc 72 | 73 | # Chutzpah Test files 74 | _Chutzpah* 75 | 76 | # Visual C++ cache files 77 | ipch/ 78 | *.aps 79 | *.ncb 80 | *.opendb 81 | *.opensdf 82 | *.sdf 83 | *.cachefile 84 | *.VC.db 85 | *.VC.VC.opendb 86 | 87 | # Visual Studio profiler 88 | *.psess 89 | *.vsp 90 | *.vspx 91 | *.sap 92 | 93 | # TFS 2012 Local Workspace 94 | $tf/ 95 | 96 | # Guidance Automation Toolkit 97 | *.gpState 98 | 99 | # ReSharper is a .NET coding add-in 100 | _ReSharper*/ 101 | *.[Rr]e[Ss]harper 102 | *.DotSettings.user 103 | 104 | # JustCode is a .NET coding add-in 105 | .JustCode 106 | 107 | # TeamCity is a build add-in 108 | _TeamCity* 109 | 110 | # DotCover is a Code Coverage Tool 111 | *.dotCover 112 | 113 | # NCrunch 114 | _NCrunch_* 115 | .*crunch*.local.xml 116 | nCrunchTemp_* 117 | 118 | # MightyMoose 119 | *.mm.* 120 | AutoTest.Net/ 121 | 122 | # Web workbench (sass) 123 | .sass-cache/ 124 | 125 | # Installshield output folder 126 | [Ee]xpress/ 127 | 128 | # DocProject is a documentation generator add-in 129 | DocProject/buildhelp/ 130 | DocProject/Help/*.HxT 131 | DocProject/Help/*.HxC 132 | DocProject/Help/*.hhc 133 | DocProject/Help/*.hhk 134 | DocProject/Help/*.hhp 135 | DocProject/Help/Html2 136 | DocProject/Help/html 137 | 138 | # Click-Once directory 139 | publish/ 140 | 141 | # Publish Web Output 142 | *.[Pp]ublish.xml 143 | *.azurePubxml 144 | # TODO: Comment the next line if you want to checkin your web deploy settings 145 | # but database connection strings (with potential passwords) will be unencrypted 146 | #*.pubxml 147 | *.publishproj 148 | 149 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 150 | # checkin your Azure Web App publish settings, but sensitive information contained 151 | # in these scripts will be unencrypted 152 | PublishScripts/ 153 | 154 | # NuGet Packages 155 | *.nupkg 156 | # The packages folder can be ignored because of Package Restore 157 | **/packages/* 158 | # except build/, which is used as an MSBuild target. 159 | !**/packages/build/ 160 | # Uncomment if necessary however generally it will be regenerated when needed 161 | #!**/packages/repositories.config 162 | # NuGet v3's project.json files produces more ignoreable files 163 | *.nuget.props 164 | *.nuget.targets 165 | 166 | # Microsoft Azure Build Output 167 | csx/ 168 | *.build.csdef 169 | 170 | # Microsoft Azure Emulator 171 | ecf/ 172 | rcf/ 173 | 174 | # Windows Store app package directories and files 175 | AppPackages/ 176 | BundleArtifacts/ 177 | Package.StoreAssociation.xml 178 | _pkginfo.txt 179 | 180 | # Visual Studio cache files 181 | # files ending in .cache can be ignored 182 | *.[Cc]ache 183 | # but keep track of directories ending in .cache 184 | !*.[Cc]ache/ 185 | 186 | # Others 187 | ClientBin/ 188 | ~$* 189 | *~ 190 | *.dbmdl 191 | *.dbproj.schemaview 192 | *.jfm 193 | *.pfx 194 | *.publishsettings 195 | node_modules/ 196 | orleans.codegen.cs 197 | 198 | # Since there are multiple workflows, uncomment next line to ignore bower_components 199 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 200 | #bower_components/ 201 | 202 | # RIA/Silverlight projects 203 | Generated_Code/ 204 | 205 | # Backup & report files from converting an old project file 206 | # to a newer Visual Studio version. Backup files are not needed, 207 | # because we have git ;-) 208 | _UpgradeReport_Files/ 209 | Backup*/ 210 | UpgradeLog*.XML 211 | UpgradeLog*.htm 212 | 213 | # SQL Server files 214 | *.mdf 215 | *.ldf 216 | 217 | # Business Intelligence projects 218 | *.rdl.data 219 | *.bim.layout 220 | *.bim_*.settings 221 | 222 | # Microsoft Fakes 223 | FakesAssemblies/ 224 | 225 | # GhostDoc plugin setting file 226 | *.GhostDoc.xml 227 | 228 | # Node.js Tools for Visual Studio 229 | .ntvs_analysis.dat 230 | 231 | # Visual Studio 6 build log 232 | *.plg 233 | 234 | # Visual Studio 6 workspace options file 235 | *.opt 236 | 237 | # Visual Studio LightSwitch build output 238 | **/*.HTMLClient/GeneratedArtifacts 239 | **/*.DesktopClient/GeneratedArtifacts 240 | **/*.DesktopClient/ModelManifest.xml 241 | **/*.Server/GeneratedArtifacts 242 | **/*.Server/ModelManifest.xml 243 | _Pvt_Extensions 244 | 245 | # Paket dependency manager 246 | .paket/paket.exe 247 | paket-files/ 248 | 249 | # FAKE - F# Make 250 | .fake/ 251 | 252 | # JetBrains Rider 253 | .idea/ 254 | *.sln.iml 255 | 256 | # CodeRush 257 | .cr/ 258 | 259 | # Python Tools for Visual Studio (PTVS) 260 | __pycache__/ 261 | *.pyc 262 | /output 263 | -------------------------------------------------------------------------------- /Tests/FullTest.cs: -------------------------------------------------------------------------------- 1 | using Xunit; 2 | 3 | namespace Lextm.ReStructuredText.Tests 4 | { 5 | public class FullTest 6 | { 7 | [Fact] 8 | public void LineNumbers() 9 | { 10 | var document = TestUtils.Test("full_linenumbers"); 11 | 12 | Assert.Null(document.Find(1, 0)); 13 | Assert.False(document.TriggerDocumentList(0, 0)); 14 | 15 | Assert.Equal(ElementType.Section, document.Find(2, 0).TypeCode); 16 | Assert.False(document.TriggerDocumentList(1, 0)); 17 | Assert.Equal(ElementType.Section, document.Find(3, 0).TypeCode); 18 | Assert.False(document.TriggerDocumentList(2, 0)); 19 | Assert.Equal(ElementType.Section, document.Find(4, 0).TypeCode); 20 | Assert.False(document.TriggerDocumentList(3, 0)); 21 | Assert.Equal(ElementType.Section, document.Find(5, 0).TypeCode); 22 | Assert.False(document.TriggerDocumentList(4, 0)); 23 | Assert.Equal(ElementType.Paragraph, document.Find(6, 0).TypeCode); 24 | Assert.False(document.TriggerDocumentList(5, 0)); 25 | Assert.Equal(ElementType.Paragraph, document.Find(7, 0).TypeCode); 26 | Assert.False(document.TriggerDocumentList(6, 0)); 27 | Assert.Equal(ElementType.Section, document.Find(8, 0).TypeCode); 28 | Assert.False(document.TriggerDocumentList(7, 0)); 29 | IElement element9 = document.Find(9, 0); 30 | Assert.Equal(ElementType.Paragraph, element9.TypeCode); 31 | Assert.True(document.TriggerDocumentList(8, 0)); 32 | Assert.Equal(ElementType.ListItem, element9.Parent.TypeCode); 33 | IElement element10 = document.Find(10, 0); 34 | Assert.Equal(ElementType.Paragraph, element10.TypeCode); 35 | Assert.True(document.TriggerDocumentList(9, 0)); 36 | Assert.Equal(ElementType.ListItem, element10.Parent.TypeCode); 37 | 38 | Assert.Equal(ElementType.Section, document.Find(11, 0).TypeCode); 39 | Assert.False(document.TriggerDocumentList(10, 0)); 40 | 41 | Assert.Equal(ElementType.Paragraph, document.Find(12, 0).TypeCode); 42 | Assert.True(document.TriggerDocumentList(11, 0)); 43 | 44 | Assert.Null(document.Find(13, 0)); 45 | Assert.False(document.TriggerDocumentList(12, 0)); 46 | } 47 | 48 | [Fact] 49 | public void LineStart() 50 | { 51 | var document = TestUtils.Test("full_linestart"); 52 | 53 | IElement item1 = document.Find(1, 0); 54 | Assert.Equal(ElementType.Paragraph, item1.TypeCode); 55 | Assert.Equal(ElementType.ListItem, item1.Parent.TypeCode); 56 | Assert.StartsWith(":doc:", item1.TextAreas[0].Content.Text); 57 | Assert.True(document.TriggerDocumentList(0, 0)); 58 | 59 | IElement item2 = document.Find(2, 0); 60 | Assert.Equal(ElementType.Paragraph, item2.TypeCode); 61 | Assert.Equal(ElementType.ListItem, item2.Parent.TypeCode); 62 | Assert.StartsWith(":doc:", item2.TextAreas[0].Content.Text); 63 | Assert.True(document.TriggerDocumentList(1, 0)); 64 | 65 | IElement item3 = document.Find(3, 0); 66 | Assert.Equal(ElementType.Paragraph, item3.TypeCode); 67 | Assert.Equal(ElementType.ListItem, item3.Parent.TypeCode); 68 | Assert.StartsWith(":doc:", item3.TextAreas[0].Content.Text); 69 | Assert.True(document.TriggerDocumentList(2, 0)); 70 | 71 | IElement item4 = document.Find(4, 0); 72 | Assert.Equal(ElementType.Paragraph, item4.TypeCode); 73 | Assert.Equal(ElementType.ListItem, item4.Parent.TypeCode); 74 | Assert.StartsWith(":doc:", item4.TextAreas[0].Content.Text); 75 | Assert.True(document.TriggerDocumentList(3, 0)); 76 | 77 | IElement item5 = document.Find(5, 0); 78 | Assert.Equal(ElementType.Paragraph, item5.TypeCode); 79 | Assert.Equal(ElementType.ListItem, item5.Parent.TypeCode); 80 | Assert.StartsWith(":doc:", item5.TextAreas[0].Content.Text); 81 | Assert.True(document.TriggerDocumentList(4, 0)); 82 | 83 | IElement item6 = document.Find(6, 0); 84 | Assert.Equal(ElementType.Paragraph, item6.TypeCode); 85 | Assert.Equal(ElementType.ListItem, item6.Parent.TypeCode); 86 | Assert.StartsWith("doc", ((InterpretedText)item6.TextAreas[0]).RoleName); 87 | Assert.True(document.TriggerDocumentList(5, 0)); 88 | 89 | IElement item7 = document.Find(7, 0); 90 | Assert.Equal(ElementType.Paragraph, item7.TypeCode); 91 | Assert.Equal(ElementType.ListItem, item7.Parent.TypeCode); 92 | Assert.StartsWith("doc", ((InterpretedText)item7.TextAreas[0]).RoleName); 93 | Assert.True(document.TriggerDocumentList(6, 0)); 94 | 95 | IElement item8 = document.Find(8, 0); 96 | Assert.Equal(ElementType.Paragraph, item8.TypeCode); 97 | Assert.Equal(ElementType.ListItem, item8.Parent.TypeCode); 98 | Assert.StartsWith("doc", ((InterpretedText)item8.TextAreas[0]).RoleName); 99 | Assert.True(document.TriggerDocumentList(7, 0)); 100 | 101 | IElement item9 = document.Find(9, 0); 102 | Assert.Equal(ElementType.Paragraph, item9.TypeCode); 103 | Assert.Equal(ElementType.ListItem, item9.Parent.TypeCode); 104 | Assert.StartsWith("doc", ((InterpretedText)item9.TextAreas[0]).RoleName); 105 | Assert.True(document.TriggerDocumentList(8, 0)); 106 | } 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /Tests/EnumeratedListTest.cs: -------------------------------------------------------------------------------- 1 | using Xunit; 2 | 3 | namespace Lextm.ReStructuredText.Tests 4 | { 5 | public class EnumeratedListTest 6 | { 7 | [Fact] 8 | public void Simple() 9 | { 10 | var document = TestUtils.Test("enumeratedlist_simple"); 11 | Assert.Equal(1, document.Elements.Count); 12 | Assert.Equal(ElementType.EnumeratedList, document.Elements[0].TypeCode); 13 | 14 | var list = (EnumeratedList) document.Elements[0]; 15 | Assert.Equal(3, list.Items.Count); 16 | 17 | Assert.Equal("Item one.\n", list.Items[0].TextAreas[0].Content.Text); 18 | Assert.Equal("Item two.\n", list.Items[1].TextAreas[0].Content.Text); 19 | Assert.Equal("Item three.\n", list.Items[2].TextAreas[0].Content.Text); 20 | } 21 | 22 | [Fact] 23 | public void NoBlankLines() 24 | { 25 | var document = TestUtils.Test("enumeratedlist_noblanklines"); 26 | Assert.Equal(2, document.Elements.Count); 27 | Assert.Equal(ElementType.EnumeratedList, document.Elements[1].TypeCode); 28 | 29 | var list = (EnumeratedList) document.Elements[1]; 30 | Assert.Equal(3, list.Items.Count); 31 | 32 | Assert.Equal("Item one.\n", list.Items[0].TextAreas[0].Content.Text); 33 | Assert.Equal("Item two.\n", list.Items[1].TextAreas[0].Content.Text); 34 | Assert.Equal("Item three.\n", list.Items[2].TextAreas[0].Content.Text); 35 | } 36 | 37 | [Fact] 38 | public void Empty() 39 | { 40 | var document = TestUtils.Test("enumeratedlist_empty"); 41 | Assert.Equal(1, document.Elements.Count); 42 | Assert.Equal(ElementType.Paragraph, document.Elements[0].TypeCode); 43 | Assert.Equal("1.\n", document.Elements[0].TextAreas[0].Content.Text); 44 | Assert.Equal("empty item above, no blank line\n", document.Elements[0].TextAreas[1].Content.Text); 45 | } 46 | 47 | [Fact] 48 | public void Scrambled() 49 | { 50 | var document = TestUtils.Test("enumeratedlist_scrambled"); 51 | 52 | // TODO: 53 | Assert.Equal(7, document.Elements.Count); 54 | Assert.Equal(ElementType.Paragraph, document.Elements[0].TypeCode); 55 | Assert.Equal(ElementType.EnumeratedList, document.Elements[1].TypeCode); 56 | Assert.Equal(ElementType.EnumeratedList, document.Elements[2].TypeCode); 57 | Assert.Equal(ElementType.EnumeratedList, document.Elements[3].TypeCode); 58 | Assert.Equal(ElementType.Paragraph, document.Elements[4].TypeCode); 59 | 60 | var list = (EnumeratedList) document.Elements[1]; 61 | Assert.Equal(1, list.Items.Count); 62 | 63 | Assert.Equal("Item three.\n", list.Items[0].TextAreas[0].Content.Text); 64 | 65 | var list2 = (EnumeratedList) document.Elements[2]; 66 | Assert.Equal(1, list2.Items.Count); 67 | Assert.Equal("Item two.\n", list2.Items[0].TextAreas[0].Content.Text); 68 | 69 | var list3 = (EnumeratedList) document.Elements[3]; 70 | Assert.Equal(1, list3.Items.Count); 71 | Assert.Equal("Item one.\n", list3.Items[0].TextAreas[0].Content.Text); 72 | 73 | //TODO: test the rest. 74 | } 75 | 76 | [Fact] 77 | public void NonOrdinal() 78 | { 79 | var document = TestUtils.Test("enumeratedlist_nonordinal"); 80 | Assert.Equal(4, document.Elements.Count); 81 | Assert.Equal(ElementType.Paragraph, document.Elements[0].TypeCode); 82 | Assert.Equal(ElementType.EnumeratedList, document.Elements[1].TypeCode); 83 | Assert.Equal(ElementType.Paragraph, document.Elements[2].TypeCode); 84 | Assert.Equal(ElementType.EnumeratedList, document.Elements[3].TypeCode); 85 | 86 | var list = (EnumeratedList) document.Elements[1]; 87 | Assert.Equal(4, list.Items.Count); 88 | 89 | Assert.Equal("Item zero.\n", list.Items[0].TextAreas[0].Content.Text); 90 | 91 | var list2 = (EnumeratedList) document.Elements[3]; 92 | Assert.Equal(2, list2.Items.Count); 93 | Assert.Equal("Item two.\n", list2.Items[0].TextAreas[0].Content.Text); 94 | } 95 | 96 | [Fact] 97 | public void MultipleBody() 98 | { 99 | var document = TestUtils.Test("enumeratedlist_multiplebody"); 100 | Assert.Equal(1, document.Elements.Count); 101 | Assert.Equal(ElementType.EnumeratedList, document.Elements[0].TypeCode); 102 | 103 | var list = (EnumeratedList) document.Elements[0]; 104 | Assert.Equal(3, list.Items.Count); 105 | 106 | Assert.Equal("Item one: line 1,\n", list.Items[0].TextAreas[0].Content.Text); 107 | Assert.Equal("line 2.\n", list.Items[0].TextAreas[1].Content.Text); 108 | 109 | Assert.Equal("Item two: line 1,\n", list.Items[1].TextAreas[0].Content.Text); 110 | Assert.Equal("line 2.\n", list.Items[1].TextAreas[1].Content.Text); 111 | 112 | var item = list.Items[2]; 113 | Assert.Equal(2, item.Elements.Count); 114 | 115 | Assert.Equal("Paragraph 2.\n", item.Elements[1].TextAreas[0].Content.Text); 116 | } 117 | 118 | [Fact] 119 | public void Different() 120 | { 121 | var document = TestUtils.Test("enumeratedlist_different"); 122 | // TODO: 123 | Assert.Equal(6, document.Elements.Count); 124 | } 125 | 126 | // TODO: roman calculation. 127 | } 128 | } -------------------------------------------------------------------------------- /ReStructuredText/BlockQuote.cs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2017 Lex Li 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this 4 | // software and associated documentation files (the "Software"), to deal in the Software 5 | // without restriction, including without limitation the rights to use, copy, modify, merge, 6 | // publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons 7 | // to whom the Software is furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in all copies or 10 | // substantial portions of the Software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 13 | // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 14 | // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE 15 | // FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 16 | // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 17 | // DEALINGS IN THE SOFTWARE. 18 | 19 | using System.Collections.Generic; 20 | using System.Linq; 21 | 22 | namespace Lextm.ReStructuredText 23 | { 24 | public class BlockQuote : IElement 25 | { 26 | private readonly int _unit; 27 | 28 | public BlockQuote(int indentation, int unit, params IElement[] content) 29 | { 30 | _unit = unit; 31 | Indentation = indentation; 32 | Elements = new List<IElement>(content); 33 | foreach (var item in Elements) 34 | { 35 | item.Parent = this; 36 | } 37 | } 38 | 39 | public Attribution Attribution { get; private set; } 40 | 41 | public int Indentation { get; } 42 | 43 | public IList<IElement> Elements { get; private set; } 44 | 45 | public ElementType TypeCode => ElementType.BlockQuote; 46 | 47 | // TODO: 48 | public IList<ITextArea> TextAreas => Elements[0].TextAreas; 49 | 50 | public IParent Parent { get; set; } 51 | 52 | public int Level => Indentation / _unit; 53 | 54 | public IParent Add(IElement current, int level = 0) 55 | { 56 | if (current is BlockQuote block) 57 | { 58 | var quoteLevel = block.Level; 59 | if (quoteLevel == Level) 60 | { 61 | foreach (var item in block.Elements) 62 | { 63 | Elements.Add(item); 64 | item.Parent = this; 65 | } 66 | 67 | return this; 68 | } 69 | 70 | if (quoteLevel < Level) 71 | { 72 | return Parent.Add(current, quoteLevel); 73 | } 74 | 75 | Elements.Add(block); 76 | block.Parent = this; 77 | return this; 78 | } 79 | 80 | if (current.Indentation >= Indentation) 81 | { 82 | Elements.Add(current); 83 | return this; 84 | } 85 | 86 | FillAttribution(); 87 | return Parent.Add(current); 88 | } 89 | 90 | public IElement Find(int line, int column) 91 | { 92 | foreach (var item in Elements) 93 | { 94 | var result = item.Find(line, column); 95 | if (result != null) 96 | { 97 | return result; 98 | } 99 | } 100 | 101 | return null; 102 | } 103 | 104 | internal void FillAttribution() 105 | { 106 | for (var index = 1; index < Elements.Count; index++) 107 | { 108 | var item = Elements[index]; 109 | if (item is Paragraph last) 110 | { 111 | var text = last.TextAreas[0].Content.Text; 112 | if (text.StartsWith("--") || text.StartsWith("\u2014")) 113 | { 114 | int line = 0; 115 | int? indent = null; 116 | bool isAttribution = true; 117 | for (var i = 0; i < last.TextAreas.Count; i++) 118 | { 119 | var info = last.TextAreas[i]; 120 | if (info.Content.Text.Last() == '\n') 121 | { 122 | if (line > 0) 123 | { 124 | var next = i + 1; 125 | if (next == last.TextAreas.Count) 126 | { 127 | continue; 128 | } 129 | 130 | var indentation = last.TextAreas[next].Indentation; 131 | if (indent == null) 132 | { 133 | indent = indentation; 134 | } 135 | else 136 | { 137 | if (indentation != indent) 138 | { 139 | isAttribution = false; 140 | break; 141 | } 142 | } 143 | } 144 | 145 | line++; 146 | } 147 | } 148 | 149 | if (isAttribution) 150 | { 151 | Attribution = new Attribution(last.TextAreas); 152 | if (index < Elements.Count - 1) 153 | { 154 | var newItem = new BlockQuote(Indentation, _unit, Elements.Skip(index + 1).ToArray()); 155 | newItem.FillAttribution(); 156 | Parent.Add(newItem); 157 | Elements = Elements.Take(index + 1).ToList(); 158 | } 159 | 160 | Elements.Remove(last); 161 | } 162 | } 163 | } 164 | } 165 | } 166 | } 167 | } 168 | -------------------------------------------------------------------------------- /ReStructuredText/Paragraph.cs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2017 Lex Li 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this 4 | // software and associated documentation files (the "Software"), to deal in the Software 5 | // without restriction, including without limitation the rights to use, copy, modify, merge, 6 | // publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons 7 | // to whom the Software is furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in all copies or 10 | // substantial portions of the Software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 13 | // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 14 | // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE 15 | // FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 16 | // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 17 | // DEALINGS IN THE SOFTWARE. 18 | 19 | using System; 20 | using System.Collections.Generic; 21 | using System.Linq; 22 | 23 | namespace Lextm.ReStructuredText 24 | { 25 | public class Paragraph : IElement 26 | { 27 | public IList<ITextArea> TextAreas { get; } 28 | 29 | public int Unit { get; set; } 30 | 31 | public Paragraph(IEnumerable<ITextArea> textAreas) 32 | { 33 | TextAreas = new List<ITextArea>(); 34 | foreach (var area in textAreas) 35 | { 36 | if (area.TypeCode == ElementType.BackTickText) 37 | { 38 | ((BackTickText)area).Process(TextAreas); 39 | } 40 | else if (area.TypeCode == ElementType.StarText) 41 | { 42 | ((StarText)area).Process(TextAreas); 43 | } 44 | else 45 | { 46 | TextAreas.Add(area); 47 | } 48 | } 49 | 50 | StarText.Deemphasize(TextAreas); 51 | } 52 | 53 | public bool IsBlockQuote => TextAreas.Count > 0 && TextAreas[0].IsIndented; 54 | 55 | public ElementType TypeCode => ElementType.Paragraph; 56 | 57 | public IParent Parent { get; set; } 58 | 59 | public override string ToString() 60 | { 61 | return TextAreas[0].Content.Text; 62 | } 63 | 64 | public IElement Find(int line, int column) 65 | { 66 | var first = TextAreas.First(); 67 | var last = TextAreas.Last(); 68 | if (line < first.Scope.LineStart || line > last.Scope.LineEnd) 69 | { 70 | return null; 71 | } 72 | 73 | return this; 74 | } 75 | 76 | public IParent Add(IElement element, int level = 0) 77 | { 78 | return Parent.Add(element); 79 | } 80 | 81 | public int Indentation => TextAreas[0].Indentation; 82 | 83 | public bool IsAttribution() 84 | { 85 | var text = TextAreas[0].Content.Text; 86 | if (!text.StartsWith("--") && !text.StartsWith("\u2014")) 87 | { 88 | return false; 89 | } 90 | 91 | int? indent = null; 92 | for (var i = 0; i < TextAreas.Count; i++) 93 | { 94 | var info = TextAreas[i]; 95 | if (info.Content.Text.Last() == '\n') 96 | { 97 | var next = i + 1; 98 | if (next == TextAreas.Count) 99 | { 100 | continue; 101 | } 102 | 103 | var indentation = TextAreas[next].Indentation; 104 | if (indent == null) 105 | { 106 | indent = indentation; 107 | } 108 | else 109 | { 110 | if (indentation != indent) 111 | { 112 | return false; 113 | } 114 | } 115 | } 116 | } 117 | 118 | return true; 119 | } 120 | 121 | public Tuple<bool, IElement> Parse(int parentIndentation, int unit, IParent last) 122 | { 123 | var definitionListItems = DefinitionListItem.Parse(this, last); 124 | if (definitionListItems.Count > 0) 125 | { 126 | var definitionList = last.Parent as DefinitionList; 127 | if (last.Parent is DefinitionListItem) 128 | { 129 | definitionList = (DefinitionList) last.Parent.Parent; 130 | } 131 | 132 | if (definitionList != null) 133 | { 134 | foreach (var item in definitionListItems) 135 | { 136 | definitionList.Add(item); 137 | } 138 | 139 | return new Tuple<bool, IElement>(true, definitionListItems.Last()); 140 | } 141 | 142 | definitionList = new DefinitionList(definitionListItems); 143 | definitionList.Parent = last; 144 | last.Add(definitionList); 145 | var listItem = definitionListItems.Last(); 146 | return new Tuple<bool, IElement>(true, listItem); 147 | } 148 | 149 | IElement newElement = this; 150 | if (Indentation > parentIndentation || TextAreas[0].IsQuoted) 151 | { 152 | var lastElement = last as IElement; 153 | var lastText = lastElement?.TextAreas?.LastOrDefault()?.Content.Text.TrimEnd(); 154 | if (lastText != null && lastText.EndsWith("::")) 155 | { 156 | newElement = new LiteralBlock(TextAreas); 157 | lastElement?.TextAreas.Last().Content.RemoveLiteral(); 158 | } 159 | else 160 | { 161 | var level = newElement.TextAreas[0].Indentation / unit; 162 | while (level > 0) 163 | { 164 | newElement = new BlockQuote(level * unit, unit, newElement); 165 | level--; 166 | } 167 | } 168 | } 169 | 170 | return new Tuple<bool, IElement>(false, newElement); 171 | } 172 | } 173 | } 174 | -------------------------------------------------------------------------------- /Tests/LiteralBlockTest.cs: -------------------------------------------------------------------------------- 1 | using Xunit; 2 | 3 | namespace Lextm.ReStructuredText.Tests 4 | { 5 | public class LiteralBlockTest 6 | { 7 | [Fact] 8 | public void Minimized() 9 | { 10 | var document = TestUtils.Test("literalblock_minimized"); 11 | Assert.Equal(2, document.Elements.Count); 12 | Assert.Equal("A paragraph", document.Elements[0].TextAreas[0].Content.Text); 13 | 14 | Assert.Equal(ElementType.LiteralBlock, document.Elements[1].TypeCode); 15 | Assert.Equal("A literal block.", document.Elements[1].TextAreas[0].Content.Text); 16 | } 17 | 18 | [Fact] 19 | public void MinimizedAndSpace() 20 | { 21 | var document = TestUtils.Test("literalblock_minimized_space"); 22 | Assert.Equal(2, document.Elements.Count); 23 | Assert.Equal("A paragraph with a space after the colons", document.Elements[0].TextAreas[0].Content.Text); 24 | 25 | Assert.Equal(ElementType.LiteralBlock, document.Elements[1].TypeCode); 26 | Assert.Equal("A literal block.", document.Elements[1].TextAreas[0].Content.Text); 27 | } 28 | 29 | [Fact] 30 | public void Two() 31 | { 32 | var document = TestUtils.Test("literalblock_two"); 33 | Assert.Equal(5, document.Elements.Count); 34 | Assert.Equal("A paragraph", document.Elements[0].TextAreas[0].Content.Text); 35 | 36 | Assert.Equal(ElementType.LiteralBlock, document.Elements[1].TypeCode); 37 | Assert.Equal("A literal block.", document.Elements[1].TextAreas[0].Content.Text); 38 | 39 | Assert.Equal("Another paragraph", document.Elements[2].TextAreas[0].Content.Text); 40 | 41 | Assert.Equal(ElementType.LiteralBlock, document.Elements[3].TypeCode); 42 | Assert.Equal("Another literal block.", document.Elements[3].TextAreas[0].Content.Text); 43 | Assert.Equal("With two blank lines following.", document.Elements[3].TextAreas[1].Content.Text); 44 | 45 | Assert.Equal("A final paragraph.\n", document.Elements[4].TextAreas[0].Content.Text); 46 | } 47 | 48 | [Fact] 49 | public void Multiline() 50 | { 51 | var document = TestUtils.Test("literalblock_multiline"); 52 | Assert.Equal(2, document.Elements.Count); 53 | Assert.Equal("A paragraph\n", document.Elements[0].TextAreas[0].Content.Text); 54 | Assert.Equal("on more than\n", document.Elements[0].TextAreas[1].Content.Text); 55 | Assert.Equal("one line", document.Elements[0].TextAreas[2].Content.Text); 56 | 57 | Assert.Equal(ElementType.LiteralBlock, document.Elements[1].TypeCode); 58 | Assert.Equal("A literal block.", document.Elements[1].TextAreas[0].Content.Text); 59 | } 60 | 61 | [Fact] 62 | public void Partial() 63 | { 64 | var document = TestUtils.Test("literalblock_partial"); 65 | Assert.Equal(2, document.Elements.Count); 66 | Assert.Equal("A paragraph: ", document.Elements[0].TextAreas[0].Content.Text); 67 | 68 | Assert.Equal(ElementType.LiteralBlock, document.Elements[1].TypeCode); 69 | Assert.Equal("A literal block.", document.Elements[1].TextAreas[0].Content.Text); 70 | } 71 | 72 | [Fact] 73 | public void Expanded() 74 | { 75 | var document = TestUtils.Test("literalblock_expanded"); 76 | Assert.Equal(2, document.Elements.Count); 77 | // TODO: should end with \n 78 | // Assert.Equal("A paragraph:\n", document.Elements[0].TextAreas[0].Text.Content); 79 | Assert.Equal("A paragraph:\n\n", document.Elements[0].TextAreas[0].Content.Text); 80 | 81 | Assert.Equal(ElementType.LiteralBlock, document.Elements[1].TypeCode); 82 | Assert.Equal("A literal block.", document.Elements[1].TextAreas[0].Content.Text); 83 | } 84 | 85 | [Fact] 86 | public void Wonky() 87 | { 88 | var document = TestUtils.Test("literalblock_wonky"); 89 | Assert.Equal(2, document.Elements.Count); 90 | // TODO: should end with \n 91 | // Assert.Equal("A paragraph:\n", document.Elements[0].TextAreas[0].Text.Content); 92 | Assert.Equal("A paragraph", document.Elements[0].TextAreas[0].Content.Text); 93 | 94 | Assert.Equal(ElementType.LiteralBlock, document.Elements[1].TypeCode); 95 | Assert.Equal(" A wonky literal block.", document.Elements[1].TextAreas[0].Content.Text); 96 | Assert.Equal("Literal line 2.", document.Elements[1].TextAreas[1].Content.Text); 97 | Assert.Equal(" Literal line 3.", document.Elements[1].TextAreas[2].Content.Text); 98 | } 99 | 100 | [Fact] 101 | public void Quoted() 102 | { 103 | var document = TestUtils.Test("literalblock_quoted"); 104 | Assert.Equal(2, document.Elements.Count); 105 | Assert.Equal("A paragraph", document.Elements[0].TextAreas[0].Content.Text); 106 | 107 | Assert.Equal(ElementType.LiteralBlock, document.Elements[1].TypeCode); 108 | Assert.Equal("> A literal block.", document.Elements[1].TextAreas[0].Content.Text); 109 | } 110 | 111 | [Fact] 112 | public void QuotedTwoBlankLine() 113 | { 114 | var document = TestUtils.Test("literalblock_quoted_twoblanklines"); 115 | Assert.Equal(2, document.Elements.Count); 116 | Assert.Equal("A paragraph", document.Elements[0].TextAreas[0].Content.Text); 117 | 118 | Assert.Equal(ElementType.LiteralBlock, document.Elements[1].TypeCode); 119 | Assert.Equal("> A literal block.", document.Elements[1].TextAreas[0].Content.Text); 120 | } 121 | 122 | [Fact] 123 | public void QuotedMultiline() 124 | { 125 | var document = TestUtils.Test("literalblock_quoted_multiline"); 126 | Assert.Equal(2, document.Elements.Count); 127 | Assert.Equal("A paragraph", document.Elements[0].TextAreas[0].Content.Text); 128 | 129 | Assert.Equal(ElementType.LiteralBlock, document.Elements[1].TypeCode); 130 | Assert.Equal("> A literal block.", document.Elements[1].TextAreas[0].Content.Text); 131 | Assert.Equal("> Line 2.", document.Elements[1].TextAreas[1].Content.Text); 132 | } 133 | } 134 | } -------------------------------------------------------------------------------- /ReStructuredText/DefinitionListItem.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | namespace Lextm.ReStructuredText 6 | { 7 | public class DefinitionListItem : IElement 8 | { 9 | private DefinitionListItem(IList<ITextArea> take, IEnumerable<ITextArea> skip, int unit, IParent parent) 10 | { 11 | var term = new List<ITextArea>(); 12 | var rest = new List<ITextArea>(); 13 | foreach (var item in take) 14 | { 15 | if (item.TypeCode == ElementType.Text) 16 | { 17 | if (string.IsNullOrWhiteSpace(item.Content.Text)) 18 | { 19 | continue; 20 | } 21 | 22 | var content = item.Content.Text; 23 | int index; 24 | while ((index = content.IndexOf(" : ", StringComparison.Ordinal)) > -1) 25 | { 26 | var text = new TextArea(content.Substring(0, index), item.Scope); 27 | if (Term == null) 28 | { 29 | term.Add(text); 30 | Term = new Term(term); 31 | } 32 | else 33 | { 34 | var list = new List<ITextArea>(); 35 | if (rest.Count > 0) 36 | { 37 | list.AddRange(rest); 38 | rest.Clear(); 39 | } 40 | 41 | list.Add(text); 42 | Classifiers.Add(new Classifier(list)); 43 | } 44 | 45 | content = content.Substring(index + " : ".Length); 46 | } 47 | 48 | if (string.IsNullOrWhiteSpace(content)) 49 | { 50 | continue; 51 | } 52 | 53 | var last = new TextArea(content, item.Scope); 54 | if (Term == null) 55 | { 56 | term.Add(last); 57 | } 58 | else 59 | { 60 | rest.Add(last); 61 | } 62 | 63 | continue; 64 | } 65 | 66 | if (Term == null) 67 | { 68 | term.Add(item); 69 | } 70 | else 71 | { 72 | rest.Add(item); 73 | } 74 | } 75 | 76 | if (Term == null) 77 | { 78 | Term = new Term(term); 79 | } 80 | 81 | Term.TextAreas.First().Indentation = take.First().Indentation; 82 | if (rest.Count > 0) 83 | { 84 | Classifiers.Add(new Classifier(rest)); 85 | } 86 | 87 | var paragraph = new Paragraph(skip) { Unit = unit }; 88 | Definition = new Definition {Indentation = paragraph.Indentation}; 89 | Definition.Add(paragraph.Parse(paragraph.Indentation, paragraph.Unit, this).Item2); 90 | } 91 | 92 | public IList<Classifier> Classifiers { get; } = new List<Classifier>(); 93 | 94 | public Definition Definition { get; } 95 | 96 | public Term Term { get; } 97 | 98 | public ElementType TypeCode => ElementType.DefinitionListItem; 99 | public IList<ITextArea> TextAreas { get; } 100 | public IParent Parent { get; set; } 101 | 102 | public IElement Find(int line, int column) 103 | { 104 | return null; 105 | } 106 | 107 | public static IList<DefinitionListItem> Parse(Paragraph paragraph, IParent last) 108 | { 109 | if (paragraph.TextAreas.Count < 2) 110 | { 111 | return Array.Empty<DefinitionListItem>(); 112 | } 113 | 114 | var result = new List<DefinitionListItem>(); 115 | IEnumerable<ITextArea> term = null; 116 | IList<ITextArea> rest = paragraph.TextAreas.ToList(); 117 | var firstIndentation = paragraph.TextAreas[0].Indentation; 118 | while (rest.Count > 0) 119 | { 120 | for (var index = 0; index < rest.Count; index++) 121 | { 122 | var item = rest[index]; 123 | if (item.Content.Text.Last() != '\n') 124 | { 125 | continue; 126 | } 127 | 128 | var next = index + 1; 129 | if (index + 1 == rest.Count) 130 | { 131 | if (term == null) 132 | { 133 | return Array.Empty<DefinitionListItem>(); 134 | } 135 | 136 | result.Add(new DefinitionListItem(term.ToList(), rest, paragraph.Unit, last)); 137 | return result; 138 | } 139 | 140 | var indentation = rest[next].Indentation; 141 | if (term == null) 142 | { 143 | if (indentation > firstIndentation) 144 | { 145 | term = rest.Take(next); 146 | rest = rest.Skip(next).ToList(); 147 | break; 148 | } 149 | } 150 | else if (indentation == firstIndentation) 151 | { 152 | // another term starts. 153 | var body = rest.Take(next); 154 | rest = rest.Skip(next).ToList(); 155 | result.Add(new DefinitionListItem(term.ToList(), body, paragraph.Unit, last)); 156 | term = null; 157 | break; 158 | } 159 | } 160 | } 161 | 162 | return Array.Empty<DefinitionListItem>(); 163 | } 164 | 165 | public IParent Add(IElement element, int level = 0) 166 | { 167 | if (element.Indentation == Definition.Indentation) 168 | { 169 | element.Parent = this; 170 | return Definition.Add(element); 171 | } 172 | 173 | return Parent.Add(element); 174 | } 175 | 176 | public int Indentation => Term.TextAreas[0].Indentation; 177 | } 178 | } -------------------------------------------------------------------------------- /ReStructuredText/Document.cs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2017 Lex Li 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this 4 | // software and associated documentation files (the "Software"), to deal in the Software 5 | // without restriction, including without limitation the rights to use, copy, modify, merge, 6 | // publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons 7 | // to whom the Software is furnished to do so, subject to the following conditions: 8 | // 9 | // The above copyright notice and this permission notice shall be included in all copies or 10 | // substantial portions of the Software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 13 | // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 14 | // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE 15 | // FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 16 | // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 17 | // DEALINGS IN THE SOFTWARE. 18 | 19 | using System; 20 | using System.Collections.Generic; 21 | using System.Linq; 22 | 23 | namespace Lextm.ReStructuredText 24 | { 25 | public class Document : IParent 26 | { 27 | public Document() 28 | { 29 | Elements = new List<IElement>(); 30 | } 31 | 32 | public IElement Find(int line, int column) 33 | { 34 | line += 1; // IMPORTNANT: when parsing we add a \n at top. 35 | foreach (var item in Elements) 36 | { 37 | var result = item.Find(line, column); 38 | if (result != null) 39 | { 40 | return result; 41 | } 42 | } 43 | 44 | return null; 45 | } 46 | 47 | public IList<IElement> Elements { get; set; } 48 | 49 | public ElementType TypeCode => ElementType.Document; 50 | 51 | public IParent Parent { get; set; } 52 | 53 | public int Unit { get; set; } 54 | 55 | public void Add(IList<ListItem> items) 56 | { 57 | foreach (var item in items) 58 | { 59 | Add(item); 60 | } 61 | } 62 | 63 | private IParent Add(ListItem item) 64 | { 65 | if (item.Enumerator == null) 66 | { 67 | if (!(Elements.LastOrDefault() is BulletList list) || list.Start != item.Start) 68 | { 69 | list = new BulletList(item); 70 | Add(list); 71 | return item; 72 | } 73 | 74 | return list.Add(item); 75 | } 76 | else 77 | { 78 | if (!(Elements.LastOrDefault() is EnumeratedList list)) 79 | { 80 | list = new EnumeratedList(item); 81 | Add(list); 82 | return item; 83 | } 84 | 85 | return list.Add(item); 86 | } 87 | } 88 | 89 | public IParent Add(IElement element, int level = 0) 90 | { 91 | if (element is ListItem listItem) 92 | { 93 | return Add(listItem); 94 | } 95 | 96 | Elements.Add(element); 97 | element.Parent = this; 98 | return element; 99 | } 100 | 101 | internal void Eat(List<IElement> raw, ITracked tracked) 102 | { 103 | Unit = tracked.IndentationTracker.Minimum; 104 | 105 | IParent last = this; 106 | int parentIndentation = 0; 107 | // IMPORTANT: block quote processing 108 | for (int i = 0; i < raw.Count; i++) 109 | { 110 | var current = raw[i]; 111 | if (current.TypeCode == ElementType.ListItem) 112 | { 113 | if (current is ListItem item && item.Enumerator != null) 114 | { 115 | if (i < raw.Count - 1) 116 | { 117 | if (raw[i + 1] is ListItem next) 118 | { 119 | item.Analyze(next); 120 | } 121 | } 122 | } 123 | 124 | last = last.Add(current); 125 | continue; 126 | } 127 | 128 | if (current.TypeCode == ElementType.Comment || current.TypeCode == ElementType.Section) 129 | { 130 | last = last.Add(current); 131 | parentIndentation = current.Indentation; 132 | continue; 133 | } 134 | 135 | if (current is Paragraph paragraph) 136 | { 137 | paragraph.Unit = Unit; 138 | if (last.TypeCode == ElementType.ListItem || last.Parent?.TypeCode == ElementType.ListItem) 139 | { 140 | last = last.Add(current); 141 | continue; 142 | } 143 | 144 | if (last.TypeCode == ElementType.BlockQuote) 145 | { 146 | if (paragraph.IsAttribution()) 147 | { 148 | last = last.Add(paragraph); 149 | continue; 150 | } 151 | } 152 | 153 | var tuple = paragraph.Parse(parentIndentation, Unit, last); 154 | if (tuple.Item1) 155 | { 156 | last = tuple.Item2; 157 | continue; 158 | } 159 | 160 | current = tuple.Item2; 161 | } 162 | 163 | last = last.Add(current); 164 | parentIndentation = current.Indentation; 165 | } 166 | 167 | if (Elements.LastOrDefault() is BlockQuote end) 168 | { 169 | end.FillAttribution(); 170 | } 171 | } 172 | 173 | public bool TriggerDocumentList(int line, int character) 174 | { 175 | var element = Find(line + 1, character); 176 | if (element == null || element.TypeCode != ElementType.Paragraph) 177 | { 178 | return false; 179 | } 180 | 181 | if (element.Parent == null) 182 | { 183 | return false; 184 | } 185 | 186 | if (element.Parent.TypeCode == ElementType.ListItem) 187 | { 188 | var text = element.TextAreas[0]; 189 | if (text is InterpretedText interpreted) 190 | { 191 | if (interpreted.RoleName != "doc") 192 | { 193 | return false; 194 | } 195 | } 196 | else if (!text.Content.Text.StartsWith(":doc:", StringComparison.Ordinal)) 197 | { 198 | return false; 199 | } 200 | 201 | return true; 202 | } 203 | 204 | if (element.Parent.TypeCode == ElementType.Section && element.TextAreas.Count >= 3) 205 | { 206 | var last = element.TextAreas.Last(); 207 | var previous = element.TextAreas[element.TextAreas.Count - 2]; 208 | var text = element.TextAreas[element.TextAreas.Count - 3]; 209 | if (last.Content.Text == "/\n" && previous.Content.Text == "`" && text.Content.Text.EndsWith(":doc:")) 210 | { 211 | return true; 212 | } 213 | } 214 | 215 | return false; 216 | } 217 | } 218 | } 219 | -------------------------------------------------------------------------------- /Tests/InlineMarkupLiteralTest.cs: -------------------------------------------------------------------------------- 1 | using Xunit; 2 | 3 | namespace Lextm.ReStructuredText.Tests 4 | { 5 | public class InlineMarkupLiteralTest 6 | { 7 | [Fact] 8 | public void Simple() 9 | { 10 | var document = TestUtils.Test("inlinemarkupliteral_simple"); 11 | Assert.Equal(1, document.Elements.Count); 12 | Assert.Equal(ElementType.Paragraph, document.Elements[0].TypeCode); 13 | var paragraph = (Paragraph) document.Elements[0]; 14 | Assert.Equal(2, paragraph.TextAreas.Count); 15 | Assert.Equal(ElementType.Literal, paragraph.TextAreas[0].TypeCode); 16 | var literal = (Literal) paragraph.TextAreas[0]; 17 | Assert.Equal("literal", literal.Content.Text); 18 | var text = paragraph.TextAreas[1]; 19 | Assert.Equal("\n", text.Content.Text); 20 | } 21 | 22 | [Fact] 23 | public void BackSlash() 24 | { 25 | var document = TestUtils.Test("inlinemarkupliteral_backslash"); 26 | Assert.Equal(1, document.Elements.Count); 27 | Assert.Equal(ElementType.Paragraph, document.Elements[0].TypeCode); 28 | var paragraph = (Paragraph) document.Elements[0]; 29 | Assert.Equal(2, paragraph.TextAreas.Count); 30 | Assert.Equal(ElementType.Literal, paragraph.TextAreas[0].TypeCode); 31 | var literal = (Literal) paragraph.TextAreas[0]; 32 | Assert.Equal("\\\\literal", literal.Content.Text); 33 | var text = paragraph.TextAreas[1]; 34 | Assert.Equal("\n", text.Content.Text); 35 | } 36 | 37 | [Fact] 38 | public void BackSlashInside() 39 | { 40 | var document = TestUtils.Test("inlinemarkupliteral_backslash_inside"); 41 | Assert.Equal(1, document.Elements.Count); 42 | Assert.Equal(ElementType.Paragraph, document.Elements[0].TypeCode); 43 | var paragraph = (Paragraph) document.Elements[0]; 44 | Assert.Equal(2, paragraph.TextAreas.Count); 45 | Assert.Equal(ElementType.Literal, paragraph.TextAreas[0].TypeCode); 46 | var literal = (Literal) paragraph.TextAreas[0]; 47 | Assert.Equal("lite\\\\ral", literal.Content.Text); 48 | var text = paragraph.TextAreas[1]; 49 | Assert.Equal("\n", text.Content.Text); 50 | } 51 | 52 | [Fact] 53 | public void BackSlashEnd() 54 | { 55 | var document = TestUtils.Test("inlinemarkupliteral_backslash_end"); 56 | Assert.Equal(1, document.Elements.Count); 57 | Assert.Equal(ElementType.Paragraph, document.Elements[0].TypeCode); 58 | var paragraph = (Paragraph) document.Elements[0]; 59 | Assert.Equal(2, paragraph.TextAreas.Count); 60 | Assert.Equal(ElementType.Literal, paragraph.TextAreas[0].TypeCode); 61 | var literal = (Literal) paragraph.TextAreas[0]; 62 | Assert.Equal("literal\\\\", literal.Content.Text); 63 | var text = paragraph.TextAreas[1]; 64 | Assert.Equal("\n", text.Content.Text); 65 | } 66 | 67 | [Fact] 68 | public void Apostrophe() 69 | { 70 | var document = TestUtils.Test("inlinemarkupliteral_apostrophe"); 71 | Assert.Equal(1, document.Elements.Count); 72 | Assert.Equal(ElementType.Paragraph, document.Elements[0].TypeCode); 73 | var paragraph = (Paragraph) document.Elements[0]; 74 | Assert.Equal(5, paragraph.TextAreas.Count); 75 | Assert.Equal(ElementType.Literal, paragraph.TextAreas[1].TypeCode); 76 | var literal = (Literal) paragraph.TextAreas[1]; 77 | Assert.Equal("literal", literal.Content.Text); 78 | var text = paragraph.TextAreas[2]; 79 | Assert.Equal(" and l\u2019", text.Content.Text); 80 | } 81 | 82 | [Fact] 83 | public void Quoted() 84 | { 85 | var document = TestUtils.Test("inlinemarkupliteral_quoted"); 86 | Assert.Equal(1, document.Elements.Count); 87 | Assert.Equal(ElementType.Paragraph, document.Elements[0].TypeCode); 88 | var paragraph = (Paragraph) document.Elements[0]; 89 | Assert.Equal(13, paragraph.TextAreas.Count); 90 | Assert.Equal(ElementType.Text, paragraph.TextAreas[0].TypeCode); 91 | var text = (TextArea) paragraph.TextAreas[0]; 92 | Assert.Equal("quoted '", text.Content.Text); 93 | 94 | Assert.Equal(ElementType.Literal, paragraph.TextAreas[1].TypeCode); 95 | var literal = (Literal) paragraph.TextAreas[1]; 96 | Assert.Equal("literal", literal.Content.Text); 97 | 98 | Assert.Equal("', quoted \"", paragraph.TextAreas[2].Content.Text); 99 | Assert.Equal("\"\n", paragraph.TextAreas[4].Content.Text); 100 | Assert.Equal("quoted \u2018", paragraph.TextAreas[5].Content.Text); 101 | Assert.Equal("\u2019, quoted \u201c", paragraph.TextAreas[7].Content.Text); 102 | Assert.Equal("\u201d,\n", paragraph.TextAreas[9].Content.Text); 103 | Assert.Equal("quoted \xab", paragraph.TextAreas[10].Content.Text); 104 | Assert.Equal("\xbb\n", paragraph.TextAreas[12].Content.Text); 105 | } 106 | 107 | [Fact] 108 | public void Quote() 109 | { 110 | var document = TestUtils.Test("inlinemarkupliteral_quote"); 111 | Assert.Equal(1, document.Elements.Count); 112 | Assert.Equal(ElementType.Paragraph, document.Elements[0].TypeCode); 113 | var paragraph = (Paragraph) document.Elements[0]; 114 | Assert.Equal(10, paragraph.TextAreas.Count); 115 | Assert.Equal(ElementType.Literal, paragraph.TextAreas[0].TypeCode); 116 | var text = (Literal) paragraph.TextAreas[0]; 117 | Assert.Equal("'literal'", text.Content.Text); 118 | 119 | Assert.Equal(ElementType.Text, paragraph.TextAreas[1].TypeCode); 120 | var literal = (TextArea) paragraph.TextAreas[1]; 121 | Assert.Equal(" with quotes, ", literal.Content.Text); 122 | 123 | Assert.Equal("\"literal\"", paragraph.TextAreas[2].Content.Text); 124 | Assert.Equal(" with quotes,\n", paragraph.TextAreas[3].Content.Text); 125 | Assert.Equal("\u2018literal\u2019", paragraph.TextAreas[4].Content.Text); 126 | Assert.Equal("\u201cliteral\u201d", paragraph.TextAreas[6].Content.Text); 127 | Assert.Equal("\xabliteral\xbb", paragraph.TextAreas[8].Content.Text); 128 | } 129 | 130 | [Fact] 131 | public void InterpretedText() 132 | { 133 | var document = TestUtils.Test("inlinemarkupliteral_interpretedtext"); 134 | Assert.Equal(1, document.Elements.Count); 135 | Assert.Equal(ElementType.Paragraph, document.Elements[0].TypeCode); 136 | var paragraph = (Paragraph) document.Elements[0]; 137 | Assert.Equal(3, paragraph.TextAreas.Count); 138 | Assert.Equal(ElementType.Literal, paragraph.TextAreas[1].TypeCode); 139 | var text = (Literal) paragraph.TextAreas[1]; 140 | Assert.Equal("`interpreted text`", text.Content.Text); 141 | } 142 | 143 | [Fact] 144 | public void EndsWithBackslash() 145 | { 146 | var document = TestUtils.Test("inlinemarkupliteral_endswithbackslash"); 147 | Assert.Equal(1, document.Elements.Count); 148 | Assert.Equal(ElementType.Paragraph, document.Elements[0].TypeCode); 149 | var paragraph = (Paragraph) document.Elements[0]; 150 | Assert.Equal(3, paragraph.TextAreas.Count); 151 | Assert.Equal(ElementType.Literal, paragraph.TextAreas[1].TypeCode); 152 | var text = (Literal) paragraph.TextAreas[1]; 153 | Assert.Equal("list", text.Content.Text); 154 | 155 | Assert.Equal("\\s use square bracket syntax.\n", paragraph.TextAreas[2].Content.Text); 156 | } 157 | } 158 | } -------------------------------------------------------------------------------- /ReStructuredText/ReStructuredText.g4: -------------------------------------------------------------------------------- 1 | grammar ReStructuredText; 2 | 3 | // Copyright (C) 2011 Bart Kiers 4 | // Copyright (C) 2017 Lex Li 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this 7 | // software and associated documentation files (the "Software"), to deal in the Software 8 | // without restriction, including without limitation the rights to use, copy, modify, merge, 9 | // publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons 10 | // to whom the Software is furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all copies or 13 | // substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 16 | // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 17 | // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE 18 | // FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 19 | // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | // DEALINGS IN THE SOFTWARE. 21 | 22 | options { 23 | language=CSharp; 24 | } 25 | 26 | @parser::namespace { Lextm.ReStructuredText } 27 | @lexer::namespace { Lextm.ReStructuredText } 28 | 29 | parse 30 | 31 | : (element | empty_line)+? EOF 32 | ; 33 | 34 | element 35 | : section | sectionElement 36 | ; 37 | 38 | sectionElement 39 | : listItemBullet | listItemEnumerated | paragraph | lineBlock | comment 40 | ; 41 | 42 | comment 43 | : LineBreak indentation? Comment Space* (commentLineNoBreak commentParagraphs?)? 44 | ; 45 | 46 | commentParagraphs 47 | : main=commentParagraph commentRest 48 | ; 49 | 50 | commentRest 51 | : (empty_line commentParagraph)* 52 | ; 53 | 54 | commentParagraph 55 | : commentLine+ 56 | ; 57 | 58 | commentLineNoBreak 59 | : commentLineAtoms 60 | ; 61 | 62 | commentLine 63 | : LineBreak Space Space Space commentLineNoBreak 64 | ; 65 | 66 | commentLineAtoms 67 | : ~(LineBreak)+ 68 | ; 69 | 70 | paragraph 71 | : lines 72 | ; 73 | 74 | section 75 | : (LineBreak overline=SectionSeparator)? title LineBreak? SectionSeparator (LineBreak)* sectionElement* 76 | ; 77 | 78 | title 79 | : LineBreak textStart 80 | | LineBreak lineSpecial Space+ (paragraphNoBreak)? 81 | | lineNormal 82 | | lineStar 83 | ; 84 | 85 | lineBlock 86 | : LineBreak lineBlockLine LineBreak? lineBlockLine* 87 | ; 88 | 89 | lineBlockLine 90 | : Block Space indentation? span*? starText 91 | | Block Space indentation? span+ 92 | ; 93 | 94 | listItemBullet 95 | : bulletCrossLine 96 | | bulletSimple 97 | | LineBreak indentation? special=(Minus | Plus) 98 | ; 99 | 100 | bulletCrossLine 101 | : LineBreak indentation? bullet Space* (paragraph+)? 102 | ; 103 | 104 | bulletSimple 105 | : LineBreak indentation? bullet Space+ paragraphNoBreak paragraph* 106 | ; 107 | 108 | bullet 109 | : Star 110 | | Minus 111 | | Plus 112 | ; 113 | 114 | listItemEnumerated 115 | : LineBreak enumerated=lineSpecial Space+ (paragraphNoBreak paragraph*)? 116 | ; 117 | 118 | paragraphNoBreak 119 | : lineNoBreak lines* 120 | ; 121 | 122 | lineNoBreak 123 | : indentation? spanLineStartNoStar span*? 124 | ; 125 | 126 | lines 127 | : linesStar 128 | | linesNormal 129 | ; 130 | 131 | linesNormal 132 | : lineNormal (linesStar | linesNormal?) 133 | ; 134 | 135 | linesStar 136 | : lineStar 137 | | lineStar lineNoBreak linesNormal?? 138 | | lineStar lineNoBreak linesStar 139 | ; 140 | 141 | lineNormal 142 | : LineBreak indentation? spanLineStartNoStar+? (span*? spanNoStar+?)? 143 | | lineSpecial 144 | ; 145 | 146 | lineStar 147 | : LineBreak indentation? spanLineStartNoStar*? starText 148 | | LineBreak indentation? text_fragment+ starText 149 | ; 150 | 151 | lineSpecial 152 | : Numbers Dot 153 | | LineBreak indentation? Numbers 154 | | LineBreak indentation? SectionSeparator (Space+ SectionSeparator) Space* // for table. 155 | //| Alphabet Dot 156 | ; 157 | 158 | empty_line 159 | : LineBreak Space* 160 | ; 161 | 162 | indentation 163 | : Space+ 164 | ; 165 | 166 | spanLineStartNoStar 167 | : reference 168 | | referenceIn 169 | | hyperlinkTarget 170 | | hyperlink 171 | // | hyperlinkDoc 172 | | backTickText 173 | | quotedLiteral 174 | | textLineStart 175 | ; 176 | 177 | textLineStart 178 | : lineStart_fragment+ text_fragment* 179 | ; 180 | 181 | lineStart_fragment 182 | : (Minus ~(Space | LineBreak | Star)) 183 | | (Plus ~(Space | Star)) 184 | | (Numbers Dot ~(Space | LineBreak | Star)) 185 | | (Numbers ~(Dot | LineBreak | Star)) 186 | //| (Alphabet Dot ~(Space | LineBreak | Star)) 187 | | (Alphabet Dot) 188 | | (Block ~(Space | Star)) 189 | | (UnderScore ~(Space | Star)) 190 | | (Alphabet ~(Dot | LineBreak | Star)) 191 | | Alphabet 192 | | separator separator 193 | | TimeStar 194 | | SquareLeft 195 | | SquareRight 196 | | RoundLeft 197 | | RoundRight 198 | | SemiColon 199 | | Colon 200 | | QuotationDouble 201 | | QuotationSingle 202 | | Dot 203 | | UnderScore 204 | | AngleLeft 205 | | AngleRight 206 | | Any 207 | | SectionSeparator 208 | ; 209 | 210 | text 211 | : textStart+ text_fragment* 212 | | textSpecial 213 | ; 214 | 215 | textSpecial 216 | : BackTick 217 | ; 218 | 219 | textStart 220 | : forcedText 221 | | lineStart_fragment 222 | | text_fragment_start text_fragment_start+ 223 | | Space 224 | ; 225 | 226 | forcedText 227 | : RoundLeft Star RoundRight 228 | | SquareLeft Star SquareRight 229 | | QuotationSingle Star QuotationSingle 230 | | QuotationSingle QuotationDouble Star QuotationDouble QuotationSingle 231 | ; 232 | 233 | spanNoStar 234 | : reference 235 | | referenceIn 236 | | hyperlinkTarget 237 | | hyperlink 238 | // | hyperlinkDoc 239 | | backTickText 240 | | quotedLiteral 241 | | text 242 | ; 243 | 244 | span 245 | : starText 246 | | spanNoStar 247 | ; 248 | 249 | quotedLiteral 250 | : AngleRight Space lineNoBreak 251 | ; 252 | 253 | text_fragment_start 254 | : SemiColon 255 | | Numbers 256 | | Alphabet 257 | | Space 258 | | SquareLeft 259 | | SquareRight 260 | | RoundLeft 261 | | RoundRight 262 | | Colon 263 | | separator 264 | | AngleLeft 265 | | AngleRight 266 | | QuotationDouble 267 | | QuotationSingle 268 | | Dot 269 | | Star Space 270 | | Any 271 | ; 272 | 273 | text_fragment 274 | : text_fragment_start 275 | | forcedText 276 | | Block 277 | | Literal 278 | | Comment 279 | | Dot 280 | | Quote 281 | ; 282 | 283 | starText 284 | : Star+ LineBreak 285 | | Star+ starNoSpace starAtoms (LineBreak Star* starNoSpace starAtoms)* Star* LineBreak 286 | | Star+ starNoSpace starAtoms Star* LineBreak 287 | | Star+ Space+ starAtoms Star+ LineBreak 288 | ; 289 | 290 | starAtoms 291 | : starAtom* (Star* starAtom)* 292 | ; 293 | 294 | starNoSpace 295 | : ~(Star | LineBreak | Space | SectionSeparator) 296 | ; 297 | 298 | starAtom 299 | : ~(Star | LineBreak) 300 | ; 301 | 302 | backTickText 303 | : (Colon titled=Alphabet Colon)? body UnderScore? 304 | ; 305 | 306 | body 307 | : BackTick BackTick* backTickAtoms BackTick+ 308 | | BackTick backTickNoSpace backTickAtoms BackTick+ 309 | | BackTick BackTick 310 | ; 311 | 312 | backTickAtoms 313 | : backTickAtom+ 314 | ; 315 | 316 | backTickNoSpace 317 | : ~(BackTick | LineBreak | Space) 318 | ; 319 | 320 | backTickAtom 321 | : ~(BackTick | LineBreak) 322 | | BackTick ~(BackTick | LineBreak) 323 | ; 324 | 325 | reference 326 | : Any+ UnderScore 327 | ; 328 | 329 | referenceIn 330 | : UnderScore hyperlinkAtom+ Colon Space url 331 | ; 332 | 333 | hyperlinkTarget 334 | : UnderScore Any+ 335 | ; 336 | 337 | hyperlink 338 | : BackTick hyperlinkAtom+ Space AngleLeft url AngleRight BackTick UnderScore? Space 339 | ; 340 | 341 | //hyperlinkDoc 342 | // : ':doc:' BackTick hyperlinkAtom+ Space AngleLeft url AngleRight BackTick 343 | // | ':doc:' BackTick url BackTick 344 | // ; 345 | 346 | url 347 | : urlAtom+ 348 | ; 349 | 350 | urlAtom 351 | : ~( LineBreak | BackTick ) 352 | ; 353 | 354 | hyperlinkAtom 355 | : ~( LineBreak | AngleLeft | AngleRight | BackTick | Star ) 356 | ; 357 | 358 | separator 359 | : (Minus | Equal | Plus | Hat) 360 | ; 361 | 362 | SectionSeparator 363 | : (Minus | Equal | Plus | Hat) (Minus | Equal | Plus | Hat) (Minus | Equal | Plus | Hat)+ 364 | ; 365 | 366 | Literal 367 | : Colon LineBreak LineBreak* Colon Colon 368 | ; 369 | 370 | TimeStar 371 | : Numbers Star 372 | | 'x' Star 373 | ; 374 | 375 | Alphabet 376 | : [A-Za-z]+ 377 | ; 378 | 379 | Numbers 380 | : [0-9]+ 381 | ; 382 | 383 | Quote 384 | : Colon Colon 385 | ; 386 | 387 | SquareLeft 388 | : '[' 389 | ; 390 | 391 | SquareRight 392 | : ']' 393 | ; 394 | 395 | RoundLeft 396 | : '(' 397 | ; 398 | 399 | RoundRight 400 | : ')' 401 | ; 402 | 403 | AngleLeft 404 | : '<' 405 | ; 406 | 407 | AngleRight 408 | : '>' 409 | ; 410 | 411 | Hat 412 | : '^' 413 | ; 414 | 415 | QuotationDouble 416 | : '"' 417 | ; 418 | 419 | QuotationSingle 420 | : '\'' 421 | ; 422 | 423 | Dot 424 | : '.' 425 | ; 426 | 427 | SemiColon 428 | : ';' 429 | ; 430 | 431 | Colon 432 | : ':' 433 | ; 434 | 435 | Equal 436 | : '=' 437 | ; 438 | 439 | Plus 440 | : '+' 441 | ; 442 | 443 | Minus 444 | : '-' 445 | ; 446 | 447 | Block 448 | : '|' 449 | ; 450 | 451 | Comment 452 | : ('.. ' LineBreak?) 453 | | ('..' LineBreak) 454 | ; 455 | 456 | UnderScore 457 | : '_' 458 | ; 459 | 460 | BackTick 461 | : '`' 462 | ; 463 | 464 | Star 465 | : '*' 466 | ; 467 | 468 | Space 469 | : ' ' 470 | | '\t' 471 | ; 472 | 473 | LineBreak 474 | : '\r'? '\n' 475 | ; 476 | 477 | Any 478 | : . 479 | ; -------------------------------------------------------------------------------- /Tests/InlineMarkupEmphasisTest.cs: -------------------------------------------------------------------------------- 1 | using Xunit; 2 | 3 | namespace Lextm.ReStructuredText.Tests 4 | { 5 | public class InlineMarkupEmphasisTest 6 | { 7 | [Fact] 8 | public void Simple() 9 | { 10 | var document = TestUtils.Test("inlinemarkupemphasis_simple"); 11 | Assert.Equal(1, document.Elements.Count); 12 | var paragraph = (Paragraph) document.Elements[0]; 13 | Assert.Equal(2, paragraph.TextAreas.Count); 14 | 15 | Assert.Equal(ElementType.Emphasis, paragraph.TextAreas[0].TypeCode); 16 | Assert.Equal("emphasis", paragraph.TextAreas[0].Content.Text); 17 | 18 | Assert.Equal(ElementType.Text, paragraph.TextAreas[1].TypeCode); 19 | Assert.Equal("\n", paragraph.TextAreas[1].Content.Text); 20 | } 21 | 22 | [Fact] 23 | public void Multiple() 24 | { 25 | var document = TestUtils.Test("inlinemarkupemphasis_multiple"); 26 | Assert.Equal(1, document.Elements.Count); 27 | var paragraph = (Paragraph) document.Elements[0]; 28 | //Assert.Equal(10, paragraph.TextAreas.Count); 29 | 30 | Assert.Equal(ElementType.Text, paragraph.TextAreas[0].TypeCode); 31 | Assert.Equal("l'", paragraph.TextAreas[0].Content.Text); 32 | 33 | Assert.Equal(ElementType.Emphasis, paragraph.TextAreas[1].TypeCode); 34 | Assert.Equal("emphasis", paragraph.TextAreas[1].Content.Text); 35 | 36 | Assert.Equal(ElementType.Text, paragraph.TextAreas[2].TypeCode); 37 | Assert.Equal(" with the ", paragraph.TextAreas[2].Content.Text); 38 | 39 | Assert.Equal(ElementType.Emphasis, paragraph.TextAreas[3].TypeCode); 40 | Assert.Equal("emphasis", paragraph.TextAreas[3].Content.Text); 41 | 42 | Assert.Equal(ElementType.Text, paragraph.TextAreas[4].TypeCode); 43 | Assert.Equal("' apostrophe.\n", paragraph.TextAreas[4].Content.Text); 44 | 45 | Assert.Equal(ElementType.Text, paragraph.TextAreas[5].TypeCode); 46 | Assert.Equal("l\u2019", paragraph.TextAreas[5].Content.Text); 47 | 48 | Assert.Equal(ElementType.Emphasis, paragraph.TextAreas[6].TypeCode); 49 | Assert.Equal("emphasis", paragraph.TextAreas[6].Content.Text); 50 | 51 | Assert.Equal(ElementType.Text, paragraph.TextAreas[7].TypeCode); 52 | Assert.Equal(" with the ", paragraph.TextAreas[7].Content.Text); 53 | 54 | Assert.Equal(ElementType.Emphasis, paragraph.TextAreas[8].TypeCode); 55 | Assert.Equal("emphasis", paragraph.TextAreas[8].Content.Text); 56 | 57 | Assert.Equal(ElementType.Text, paragraph.TextAreas[9].TypeCode); 58 | Assert.Equal("\u2019 apostrophe.\n", paragraph.TextAreas[9].Content.Text); 59 | } 60 | 61 | [Fact] 62 | public void CrossLine() 63 | { 64 | var document = TestUtils.Test("inlinemarkupemphasis_crossline"); 65 | 66 | Assert.Equal(1, document.Elements.Count); 67 | var paragraph = (Paragraph) document.Elements[0]; 68 | Assert.Equal(2, paragraph.TextAreas.Count); 69 | 70 | Assert.Equal(ElementType.Emphasis, paragraph.TextAreas[0].TypeCode); 71 | var emphasis = (Emphasis) paragraph.TextAreas[0]; 72 | Assert.Equal("emphasized sentence\n", emphasis.TextAreas[0].Content.Text); 73 | Assert.Equal("across lines", emphasis.TextAreas[1].Content.Text); 74 | 75 | Assert.Equal(ElementType.Text, paragraph.TextAreas[1].TypeCode); 76 | Assert.Equal("\n", paragraph.TextAreas[1].Content.Text); 77 | } 78 | 79 | [Fact] 80 | public void Punctuation() 81 | { 82 | var document = TestUtils.Test("inlinemarkupemphasis_punctuation"); 83 | 84 | var paragraph = (Paragraph) document.Elements[0]; 85 | Assert.Equal("some punctuation is allowed around inline markup, e.g.\n", paragraph.TextAreas[0].Content.Text); 86 | Assert.Equal("/", paragraph.TextAreas[1].Content.Text); 87 | 88 | Assert.Equal(ElementType.Emphasis, paragraph.TextAreas[2].TypeCode); 89 | Assert.Equal("emphasis", ((Emphasis)paragraph.TextAreas[2]).TextAreas[0].Content.Text); 90 | 91 | Assert.Equal("/, -", paragraph.TextAreas[3].Content.Text); 92 | 93 | Assert.Equal(ElementType.Emphasis, paragraph.TextAreas[4].TypeCode); 94 | Assert.Equal("emphasis", ((Emphasis)paragraph.TextAreas[4]).TextAreas[0].Content.Text); 95 | 96 | Assert.Equal("-, and :", paragraph.TextAreas[5].Content.Text); 97 | 98 | Assert.Equal(ElementType.Emphasis, paragraph.TextAreas[6].TypeCode); 99 | Assert.Equal("emphasis", ((Emphasis)paragraph.TextAreas[6]).TextAreas[0].Content.Text); 100 | 101 | Assert.Equal(": (delimiters),\n", paragraph.TextAreas[7].Content.Text); 102 | Assert.Equal("(", paragraph.TextAreas[8].Content.Text); 103 | 104 | Assert.Equal(ElementType.Emphasis, paragraph.TextAreas[9].TypeCode); 105 | Assert.Equal("emphasis", ((Emphasis)paragraph.TextAreas[9]).TextAreas[0].Content.Text); 106 | 107 | Assert.Equal("), [", paragraph.TextAreas[10].Content.Text); 108 | 109 | Assert.Equal(ElementType.Emphasis, paragraph.TextAreas[11].TypeCode); 110 | Assert.Equal("emphasis", ((Emphasis)paragraph.TextAreas[11]).TextAreas[0].Content.Text); 111 | 112 | Assert.Equal("], <", paragraph.TextAreas[12].Content.Text); 113 | 114 | Assert.Equal(ElementType.Emphasis, paragraph.TextAreas[13].TypeCode); 115 | Assert.Equal("emphasis", ((Emphasis)paragraph.TextAreas[13]).TextAreas[0].Content.Text); 116 | 117 | Assert.Equal(">, {", paragraph.TextAreas[14].Content.Text); 118 | 119 | Assert.Equal(ElementType.Emphasis, paragraph.TextAreas[15].TypeCode); 120 | Assert.Equal("emphasis", ((Emphasis)paragraph.TextAreas[15]).TextAreas[0].Content.Text); 121 | 122 | Assert.Equal("} (open/close pairs)\n", paragraph.TextAreas[16].Content.Text); 123 | 124 | Assert.Equal(ElementType.Emphasis, paragraph.TextAreas[17].TypeCode); 125 | Assert.Equal("emphasis", ((Emphasis)paragraph.TextAreas[17]).TextAreas[0].Content.Text); 126 | 127 | Assert.Equal("., ", paragraph.TextAreas[18].Content.Text); 128 | 129 | Assert.Equal(ElementType.Emphasis, paragraph.TextAreas[19].TypeCode); 130 | Assert.Equal("emphasis", ((Emphasis)paragraph.TextAreas[19]).TextAreas[0].Content.Text); 131 | 132 | Assert.Equal(",, ", paragraph.TextAreas[20].Content.Text); 133 | 134 | Assert.Equal(ElementType.Emphasis, paragraph.TextAreas[21].TypeCode); 135 | Assert.Equal("emphasis", ((Emphasis)paragraph.TextAreas[21]).TextAreas[0].Content.Text); 136 | 137 | Assert.Equal("!, and ", paragraph.TextAreas[22].Content.Text); 138 | 139 | Assert.Equal(ElementType.Emphasis, paragraph.TextAreas[23].TypeCode); 140 | Assert.Equal("emphasis", ((Emphasis)paragraph.TextAreas[23]).TextAreas[0].Content.Text); 141 | 142 | Assert.Equal(" (closing delimiters),\n", paragraph.TextAreas[24].Content.Text); 143 | Assert.Equal(25, paragraph.TextAreas.Count); 144 | 145 | var paragraph2 = (Paragraph) document.Elements[1]; 146 | Assert.Equal("but not\n", paragraph2.TextAreas[0].Content.Text); 147 | Assert.Equal(")*emphasis*(, ]*emphasis*[, >*emphasis*>, }*emphasis*{ (close/open pairs),\n", paragraph2.TextAreas[1].Content.Text); 148 | Assert.Equal("(*), [*], '*' or '\"*\"' (\"quoted\" star-string),\n", paragraph2.TextAreas[2].Content.Text); 149 | Assert.Equal("x*2* or 2*x* (alphanumeric char before),\n", paragraph2.TextAreas[3].Content.Text); 150 | Assert.Equal("\\*args or * (escaped, whitespace behind start-string),\n", paragraph2.TextAreas[4].Content.Text); 151 | 152 | Assert.Equal("or ", paragraph2.TextAreas[5].Content.Text); 153 | Assert.Equal(ElementType.Emphasis, paragraph2.TextAreas[6].TypeCode); 154 | Assert.Equal("the\\* *stars\\* *inside", paragraph2.TextAreas[6].Content.Text); 155 | Assert.Equal(" (escaped, whitespace before end-string).\n", paragraph2.TextAreas[7].Content.Text); 156 | Assert.Equal(8, paragraph2.TextAreas.Count); 157 | 158 | var paragraph3 = (Paragraph) document.Elements[2]; 159 | 160 | Assert.Equal("what about ", paragraph3.TextAreas[0].Content.Text); 161 | Assert.Equal(ElementType.Emphasis, paragraph3.TextAreas[1].TypeCode); 162 | Assert.Equal("this*", paragraph3.TextAreas[1].Content.Text); 163 | Assert.Equal("?\n", paragraph3.TextAreas[2].Content.Text); 164 | Assert.Equal(3, paragraph3.TextAreas.Count); 165 | 166 | Assert.Equal(3, document.Elements.Count); 167 | } 168 | 169 | [Fact] 170 | public void Quotes() 171 | { 172 | var document = TestUtils.Test("inlinemarkupemphasis_quotes"); 173 | 174 | Assert.Equal(2, document.Elements.Count); 175 | var paragraph = (Paragraph) document.Elements[0]; 176 | Assert.Equal(1, paragraph.TextAreas.Count); 177 | Assert.Equal("Quotes around inline markup:\n", paragraph.TextAreas[0].Content.Text); 178 | 179 | var paragraph2 = (Paragraph) document.Elements[1]; 180 | Assert.Equal(5, paragraph2.TextAreas.Count); 181 | Assert.Equal(ElementType.Text, paragraph2.TextAreas[0].TypeCode); 182 | Assert.Equal("'", paragraph2.TextAreas[0].Content.Text); 183 | Assert.Equal(ElementType.Text, paragraph2.TextAreas[2].TypeCode); 184 | Assert.Equal("' \"", paragraph2.TextAreas[2].Content.Text); 185 | Assert.Equal(ElementType.Text, paragraph2.TextAreas[4].TypeCode); 186 | Assert.Equal("\" Straight,\n", paragraph2.TextAreas[4].Content.Text); 187 | } 188 | 189 | [Fact] 190 | public void Asterisk() 191 | { 192 | var document = TestUtils.Test("inlinemarkupemphasis_asterisk"); 193 | 194 | Assert.Equal(2, document.Elements.Count); 195 | var paragraph = (Paragraph) document.Elements[0]; 196 | Assert.Equal(3, paragraph.TextAreas.Count); 197 | Assert.Equal("Emphasized asterisk: ", paragraph.TextAreas[0].Content.Text); 198 | Assert.Equal("\\*", paragraph.TextAreas[1].Content.Text); 199 | Assert.Equal("\n", paragraph.TextAreas[2].Content.Text); 200 | 201 | var paragraph2 = (Paragraph) document.Elements[1]; 202 | Assert.Equal(3, paragraph2.TextAreas.Count); 203 | Assert.Equal("Emphasized double asterisk: ", paragraph2.TextAreas[0].Content.Text); 204 | Assert.Equal("\\**", paragraph2.TextAreas[1].Content.Text); 205 | Assert.Equal("\n", paragraph2.TextAreas[2].Content.Text); 206 | } 207 | } 208 | } --------------------------------------------------------------------------------