diff --git a/gap/DocumentationTree.gi b/gap/DocumentationTree.gi index b54f43b2..d190dd38 100644 --- a/gap/DocumentationTree.gi +++ b/gap/DocumentationTree.gi @@ -251,7 +251,8 @@ InstallMethod( DocumentationChunk, [ IsTreeForDocumentation, IsString ], if IsBound( tree!.chunks.( name ) ) then return tree!.chunks.( name ); fi; - node := rec( content := [ ] ); + node := rec( content := [ ], + content_source_positions := [ ] ); ObjectifyWithAttributes( node, TheTypeOfDocumentationTreeChunkNodes, Label, name ); node!.is_defined := false; @@ -266,9 +267,12 @@ InstallMethod( DocumentationManItem, [ ], local node; node := rec( description := [ ], - return_value := [ ] ); + description_source_positions := [ ], + return_value := [ ], + return_value_source_positions := [ ] ); ObjectifyWithAttributes( node, TheTypeOfDocumentationTreeNodesForManItem ); node!.content := node!.description; + node!.content_source_field := "description_source_positions"; return node; end ); @@ -280,7 +284,8 @@ InstallMethod( DocumentationGroup, [ IsTreeForDocumentation, IsString ], if IsBound( tree!.cached_nodes_by_label.( name ) ) then return tree!.cached_nodes_by_label.( name ); fi; - group := rec( content := [ ] ); + group := rec( content := [ ], + content_source_positions := [ ] ); ObjectifyWithAttributes( group, TheTypeOfDocumentationTreeNodesForGroup, Label, name ); tree!.cached_nodes_by_label.( name ) := group; @@ -414,11 +419,13 @@ end ); ############################################# BindGlobal( "AUTODOC_ConvertHeadingToGAPDocXML", - function( heading ) + function( heading, source_position ) local converted_heading; - converted_heading := - AUTODOC_ConvertMarkdownToGAPDocXML( [ NormalizedWhitespace( heading ) ] ); + converted_heading := AUTODOC_ConvertMarkdownToGAPDocXML( + [ NormalizedWhitespace( heading ) ], + [ source_position ] + ); if not ForAll( converted_heading, IsString ) then Error( "headings must convert to inline GAPDoc XML" ); fi; @@ -429,7 +436,7 @@ end ); BindGlobal( "AUTODOC_WriteStructuralNode", function( node, element_name, stream ) - local heading; + local heading, title_source_position; if ForAll( node!.content, IsEmptyNode ) then return false; @@ -437,10 +444,12 @@ BindGlobal( "AUTODOC_WriteStructuralNode", if IsBound( node!.title_string ) then heading := NormalizedWhitespace( node!.title_string ); + title_source_position := node!.title_string_source_position; else heading := ReplacedString( node!.name, "_", " " ); + title_source_position := fail; fi; - heading := AUTODOC_ConvertHeadingToGAPDocXML( heading ); + heading := AUTODOC_ConvertHeadingToGAPDocXML( heading, title_source_position ); AppendTo( stream, "<", element_name, " Label=\"", Label( node ), "\">\n" ); AppendTo( stream, "", heading, "\n\n" ); @@ -491,7 +500,11 @@ BindGlobal( "WriteChunks", fi; AppendTo( chunks_stream, "<#GAPDoc Label=\"", current_chunk_name, "\">\n" ); if IsBound( current_chunk!.content ) then - WriteDocumentation( current_chunk!.content, chunks_stream ); + AUTODOC_WriteDocumentationListWithSource( + current_chunk!.content, + current_chunk!.content_source_positions, + chunks_stream + ); fi; AppendTo( chunks_stream, "\n<#/GAPDoc>\n" ); od; @@ -566,29 +579,14 @@ InstallMethod( WriteDocumentation, [ IsList, IsStream ], local current_string_list, i, FlushConvertedStrings; FlushConvertedStrings := function() - local converted_string_list, in_cdata, item; if current_string_list = [ ] then return; fi; - converted_string_list := AUTODOC_ConvertMarkdownToGAPDocXML( current_string_list ); - in_cdata := false; - for item in converted_string_list do - if not IsString( item ) then - WriteDocumentation( item, filestream ); - continue; - fi; - if AUTODOC_LineStartsCDATA( item ) then - in_cdata := true; - fi; - if in_cdata = true then - AppendTo( filestream, Chomp( item ), "\n" ); - else - WriteDocumentation( item, filestream ); - fi; - if AUTODOC_LineEndsCDATA( item ) then - in_cdata := false; - fi; - od; + AUTODOC_WriteStringListWithSource( + current_string_list, + fail, + filestream + ); current_string_list := [ ]; end; diff --git a/gap/Markdown.gi b/gap/Markdown.gi index 843b195b..8dfe6d1e 100644 --- a/gap/Markdown.gi +++ b/gap/Markdown.gi @@ -47,7 +47,7 @@ end ); ## BindGlobal( "AUTODOC_ConvertInlineBackticksInLine", - function( string, keyword_set ) + function( string, keyword_set, source_position ) local opening_pos, closing_pos, inline_content, tag_name, search_string; while PositionSublist( string, "`" ) <> fail do @@ -55,7 +55,16 @@ BindGlobal( "AUTODOC_ConvertInlineBackticksInLine", search_string := string{ [ opening_pos + 1 .. Length( string ) ] }; closing_pos := PositionSublist( search_string, "`" ); if closing_pos = fail then - Error( "did you forget some `" ); + if source_position = fail then + Error( "did you forget some `" ); + fi; + Error( + "did you forget some `,\n", + "at ", + source_position.filename, + ":", + source_position.line + ); fi; closing_pos := opening_pos + closing_pos; @@ -94,12 +103,21 @@ end ); ## BindGlobal( "AUTODOC_ConvertFencedMarkdownBlocks", - function( string_list ) - local i, converted_string_list, skipped, trimmed_line, + function( arg ) + local converted_source_positions, converted_string_list, i, skipped, + string_list, trimmed_line, fence_char, fence_length, info_string, fence_element, code_block, - fence_content; + fence_content, source_positions; + + string_list := arg[ 1 ]; + if Length( arg ) > 1 then + source_positions := arg[ 2 ]; + else + source_positions := ListWithIdenticalEntries( Length( string_list ), fail ); + fi; converted_string_list := [ ]; + converted_source_positions := [ ]; i := 1; skipped := false; while i <= Length( string_list ) do @@ -108,6 +126,7 @@ BindGlobal( "AUTODOC_ConvertFencedMarkdownBlocks", fi; if skipped = true then Add( converted_string_list, string_list[ i ] ); + Add( converted_source_positions, source_positions[ i ] ); if AUTODOC_LineEndsCDATA( string_list[ i ] ) then skipped := false; fi; @@ -146,6 +165,7 @@ BindGlobal( "AUTODOC_ConvertFencedMarkdownBlocks", od; Add( converted_string_list, DocumentationVerbatim( fence_element, rec( ), fence_content ) ); + Add( converted_source_positions, source_positions[ i - Length( fence_content ) - 1 ] ); if code_block = true then i := i + 1; continue; @@ -154,10 +174,14 @@ BindGlobal( "AUTODOC_ConvertFencedMarkdownBlocks", fi; fi; Add( converted_string_list, string_list[ i ] ); + Add( converted_source_positions, source_positions[ i ] ); i := i + 1; od; - return converted_string_list; + return rec( + items := converted_string_list, + source_positions := converted_source_positions + ); end ); ## @@ -181,10 +205,11 @@ end ); ## BindGlobal( "AUTODOC_ConvertMarkdownStringsToGAPDocXML", - function( string_list ) + function( string_list, source_positions ) local i, current_list, current_string, max_line_length, current_position, already_in_list, command_list_with_translation, beginning, - commands, position_of_command, insert, beginning_whitespaces, temp, string_list_temp, skipped, + commands, opening_source_position, position_of_command, insert, + beginning_whitespaces, temp, string_list_temp, skipped, already_inserted_paragraph, in_list, in_item, converted_string_list, keyword_set; @@ -193,7 +218,11 @@ BindGlobal( "AUTODOC_ConvertMarkdownStringsToGAPDocXML", keyword_set := Set( ALL_KEYWORDS() ); AUTODOC_ForEachNonCDATALine( string_list, function( i ) string_list[ i ] := - AUTODOC_ConvertInlineBackticksInLine( string_list[ i ], keyword_set ); + AUTODOC_ConvertInlineBackticksInLine( + string_list[ i ], + keyword_set, + source_positions[ i ] + ); end ); ## Check for paragraphs by turning an empty string into

@@ -245,13 +274,17 @@ BindGlobal( "AUTODOC_ConvertMarkdownStringsToGAPDocXML", fi; if already_in_list = false then Add( string_list, "", i ); + Add( source_positions, fail, i ); Add( string_list, "", i ); + Add( source_positions, fail, i ); i := i + 2; string_list[ i ] := string_list[ i ]{[ current_position + 2 .. Length( string_list[ i ] ) ]}; already_in_list := true; else Add( string_list, "", i ); + Add( source_positions, fail, i ); Add( string_list, "", i ); + Add( source_positions, fail, i ); i := i + 2; string_list[ i ] := string_list[ i ]{[ current_position + 2 .. Length( string_list[ i ] ) ]}; fi; @@ -270,14 +303,18 @@ BindGlobal( "AUTODOC_ConvertMarkdownStringsToGAPDocXML", elif already_in_list = true and PositionSublist( string_list[ i ], " " ) > current_position then already_in_list := false; Add( string_list, "", i ); + Add( source_positions, fail, i ); Add( string_list, "", i ); + Add( source_positions, fail, i ); i := i + 2; fi; i := i + 1; od; if already_in_list = true then Add( string_list, "" ); + Add( source_positions, fail ); Add( string_list, "" ); + Add( source_positions, fail ); fi; current_position := current_position + 1; od; @@ -320,13 +357,16 @@ BindGlobal( "AUTODOC_ConvertMarkdownStringsToGAPDocXML", for commands in command_list_with_translation do beginning := true; + opening_source_position := fail; AUTODOC_ForEachNonCDATALine( string_list, function( i ) while PositionSublist( string_list[ i ], commands[ 1 ] ) <> fail do position_of_command := PositionSublist( string_list[ i ], commands[ 1 ] ); if beginning = true then insert := Concatenation( "<", commands[ 2 ], ">" ); + opening_source_position := source_positions[ i ]; else insert := Concatenation( "" ); + opening_source_position := fail; fi; string_list[ i ] := INSERT_IN_STRING_WITH_REPLACE( string_list[ i ], insert, position_of_command, Length( commands[ 1 ] ) ); beginning := not beginning; @@ -334,7 +374,18 @@ BindGlobal( "AUTODOC_ConvertMarkdownStringsToGAPDocXML", end ); if beginning = false then - Error( "did you forget some ", commands[ 1 ] ); + if opening_source_position = fail then + Error( "did you forget some ", commands[ 1 ] ); + fi; + Error( + "did you forget some ", + commands[ 1 ], + ",\n", + "at ", + opening_source_position.filename, + ":", + opening_source_position.line + ); fi; od; @@ -343,27 +394,42 @@ end ); ## InstallGlobalFunction( AUTODOC_ConvertMarkdownToGAPDocXML, - function( string_list ) - local converted_items, current_string_list, item, FlushStringList; + function( string_list, source_positions ) + local converted_blocks, converted_items, current_source_positions, + current_string_list, i, FlushStringList; + + if source_positions = fail then + source_positions := ListWithIdenticalEntries( Length( string_list ), fail ); + fi; converted_items := [ ]; current_string_list := [ ]; + current_source_positions := [ ]; FlushStringList := function() if current_string_list = [ ] then return; fi; Append( converted_items, - AUTODOC_ConvertMarkdownStringsToGAPDocXML( current_string_list ) ); + AUTODOC_ConvertMarkdownStringsToGAPDocXML( + current_string_list, + current_source_positions + ) ); current_string_list := [ ]; + current_source_positions := [ ]; end; - for item in AUTODOC_ConvertFencedMarkdownBlocks( string_list ) do - if IsString( item ) then - Add( current_string_list, item ); + converted_blocks := AUTODOC_ConvertFencedMarkdownBlocks( + string_list, + source_positions + ); + for i in [ 1 .. Length( converted_blocks.items ) ] do + if IsString( converted_blocks.items[ i ] ) then + Add( current_string_list, converted_blocks.items[ i ] ); + Add( current_source_positions, converted_blocks.source_positions[ i ] ); else FlushStringList(); - Add( converted_items, item ); + Add( converted_items, converted_blocks.items[ i ] ); fi; od; FlushStringList(); diff --git a/gap/Parser.gi b/gap/Parser.gi index 6a110c28..21b269c2 100644 --- a/gap/Parser.gi +++ b/gap/Parser.gi @@ -287,13 +287,14 @@ end ); InstallGlobalFunction( AutoDoc_Parser_ReadFiles, function( filename_list, tree, default_chapter_data ) local ApplyFilterInfoToCurrentItem, CreateTitleItemFunction, CurrentItem, - CurrentOrNewManItem, DeclarationDelimiterPosition, ErrorWithPos, + CurrentOrNewManItem, CurrentSourcePosition, + DeclarationDelimiterPosition, ErrorWithPos, FinishCurrentManItem, HasCurrentItem, IsMatchingMarkdownFence, MarkdownFenceFromLine, NormalizeInputLine, NormalizeItemType, NormalizedReadLine, ReadBracketedFilterString, ReadCode, ReadExample, ReadInstallMethodArguments, ReadInstallMethodFilterString, ReadLineWithLineCount, - ReadSessionExample, Reset, ScanDeclarePart, ScanForDeclarationPart, + ReadSessionExample, RecordStringSourcePosition, Reset, ScanDeclarePart, ScanForDeclarationPart, ScanInstallMethodPart, SetCurrentItem, # active_title_item_is_multiline, active_title_item_name, @@ -331,6 +332,26 @@ InstallGlobalFunction( AutoDoc_Parser_ReadFiles, list := Concatenation(arg, [ ",\n", "at ", filename, ":", line_number]); CallFuncList(Error, list); end; + CurrentSourcePosition := function() + return rec( filename := filename, line := line_number ); + end; + RecordStringSourcePosition := function( item ) + local source_field; + if not ( IsRecord( item ) or IsTreeForDocumentationNode( item ) ) then + return; + fi; + if IsBound( item!.content_source_field ) then + source_field := item!.content_source_field; + elif IsBound( item!.content_source_positions ) then + source_field := "content_source_positions"; + else + return; + fi; + if not IsBound( item!.( source_field ) ) then + item!.( source_field ) := [ ]; + fi; + Add( item!.( source_field ), CurrentSourcePosition() ); + end; HasCurrentItem := function( ) return Length( context_stack ) > 0; end; @@ -828,6 +849,7 @@ InstallGlobalFunction( AutoDoc_Parser_ReadFiles, fi; scope_chapter := ChapterInTree( tree, chapter_info[ 1 ] ); scope_chapter!.title_string := current_command[ 2 ]; + scope_chapter!.title_string_source_position := CurrentSourcePosition(); end, @Section := function() @@ -856,6 +878,7 @@ InstallGlobalFunction( AutoDoc_Parser_ReadFiles, fi; scope_section := SectionInTree( tree, chapter_info[ 1 ], chapter_info[ 2 ] ); scope_section!.title_string := current_command[ 2 ]; + scope_section!.title_string_source_position := CurrentSourcePosition(); end, @Subsection := function() @@ -883,6 +906,7 @@ InstallGlobalFunction( AutoDoc_Parser_ReadFiles, fi; scope_subsection := SubsectionInTree( tree, chapter_info[ 1 ], chapter_info[ 2 ], chapter_info[ 3 ] ); scope_subsection!.title_string := current_command[ 2 ]; + scope_subsection!.title_string_source_position := CurrentSourcePosition(); end, @BeginGroup := function() @@ -899,25 +923,30 @@ InstallGlobalFunction( AutoDoc_Parser_ReadFiles, @Description := function() CurrentOrNewManItem(); CurrentItem()!.content := CurrentItem()!.description; + CurrentItem()!.content_source_field := "description_source_positions"; NormalizeWhitespace( current_command[ 2 ] ); if current_command[ 2 ] <> "" then Add( CurrentItem(), current_command[ 2 ] ); + RecordStringSourcePosition( CurrentItem() ); fi; end, @Returns := function() CurrentOrNewManItem(); CurrentItem()!.content := CurrentItem()!.return_value; + CurrentItem()!.content_source_field := "return_value_source_positions"; if IsBound( CurrentItem()!.item_type ) and CurrentItem()!.item_type = "Var" then CurrentItem()!.item_type := "Func"; if not IsBound( CurrentItem()!.arguments ) or CurrentItem()!.arguments = fail then CurrentItem()!.arguments := "arg"; fi; CurrentItem()!.return_value := [ ]; + CurrentItem()!.return_value_source_positions := [ ]; elif not IsBound( CurrentItem()!.item_type ) then CurrentItem()!.declaration_is_function := true; fi; if current_command[ 2 ] <> "" then Add( CurrentItem(), current_command[ 2 ] ); + RecordStringSourcePosition( CurrentItem() ); fi; end, @Arguments := function() @@ -964,6 +993,7 @@ InstallGlobalFunction( AutoDoc_Parser_ReadFiles, fi; group_obj := DocumentationGroup( tree, group_name, chap_info ); group_obj!.title_string := current_command[ 2 ]; + group_obj!.title_string_source_position := CurrentSourcePosition(); end, @ChapterInfo := function() local current_chapter_info; @@ -1097,6 +1127,7 @@ InstallGlobalFunction( AutoDoc_Parser_ReadFiles, return; fi; Add( CurrentItem(), current_command[ 2 ] ); + RecordStringSourcePosition( CurrentItem() ); end, @BeginLatexOnly := function() local alt_node; diff --git a/gap/ToolFunctions.gd b/gap/ToolFunctions.gd index f191e341..224cca59 100644 --- a/gap/ToolFunctions.gd +++ b/gap/ToolFunctions.gd @@ -12,6 +12,8 @@ DeclareGlobalFunction( "AUTODOC_LineEndsCDATA" ); DeclareGlobalFunction( "AUTODOC_EscapeCDATAContent" ); DeclareGlobalFunction( "AUTODOC_OutputTextFile" ); +DeclareGlobalFunction( "AUTODOC_WriteDocumentationListWithSource" ); +DeclareGlobalFunction( "AUTODOC_WriteStringListWithSource" ); DeclareGlobalFunction( "AutoDoc_WriteDocEntry" ); DeclareGlobalFunction( "AUTODOC_Diff" ); diff --git a/gap/ToolFunctions.gi b/gap/ToolFunctions.gi index c5fcc17e..e3c41b39 100644 --- a/gap/ToolFunctions.gi +++ b/gap/ToolFunctions.gi @@ -94,7 +94,8 @@ end ); ## InstallGlobalFunction( AutoDoc_WriteDocEntry, function( filestream, list_of_records, heading ) - local return_value, description, current_description, labels, i, + local return_value, return_value_sources, description, + description_sources, current_description, labels, i, item_type_info; # look for a good return value (it should be the same everywhere) @@ -102,9 +103,11 @@ InstallGlobalFunction( AutoDoc_WriteDocEntry, if IsBound( i!.return_value ) then if IsList( i!.return_value ) and Length( i!.return_value ) > 0 then return_value := i!.return_value; + return_value_sources := i!.return_value_source_positions; break; elif IsBool( i!.return_value ) then return_value := i!.return_value; + return_value_sources := [ ]; break; fi; fi; @@ -112,6 +115,7 @@ InstallGlobalFunction( AutoDoc_WriteDocEntry, if not IsBound( return_value ) then return_value := false; + return_value_sources := [ ]; fi; if IsList( return_value ) and ( not IsString( return_value ) ) and return_value <> "" then @@ -120,12 +124,14 @@ InstallGlobalFunction( AutoDoc_WriteDocEntry, # collect description (for readability not in the loop above) description := [ ]; + description_sources := [ ]; for i in list_of_records do current_description := i!.description; if IsString( current_description ) then current_description := [ current_description ]; fi; - description := Concatenation( description, current_description ); + Append( description, current_description ); + Append( description_sources, i!.description_source_positions ); od; labels := [ ]; @@ -178,17 +184,88 @@ InstallGlobalFunction( AutoDoc_WriteDocEntry, return_value := [ return_value ]; fi; AppendTo( filestream, " " ); - WriteDocumentation( return_value, filestream ); + AUTODOC_WriteDocumentationListWithSource( + return_value, + return_value_sources, + filestream + ); AppendTo( filestream, "\n" ); fi; AppendTo( filestream, " \n" ); - WriteDocumentation( description, filestream ); + AUTODOC_WriteDocumentationListWithSource( + description, + description_sources, + filestream + ); AppendTo( filestream, " \n" ); AppendTo( filestream, "\n\n" ); end ); +InstallGlobalFunction( AUTODOC_WriteDocumentationListWithSource, + function( node_list, source_positions, filestream ) + local current_source_positions, current_string_list, i, next_source_index, + FlushConvertedStrings; + + FlushConvertedStrings := function() + AUTODOC_WriteStringListWithSource( + current_string_list, + current_source_positions, + filestream + ); + current_string_list := [ ]; + current_source_positions := [ ]; + end; + + current_string_list := [ ]; + current_source_positions := [ ]; + next_source_index := 1; + for i in [ 1 .. Length( node_list ) ] do + if IsString( node_list[ i ] ) then + Add( current_string_list, ShallowCopy( node_list[ i ] ) ); + if source_positions = fail or next_source_index > Length( source_positions ) then + Add( current_source_positions, fail ); + else + Add( current_source_positions, source_positions[ next_source_index ] ); + fi; + next_source_index := next_source_index + 1; + else + FlushConvertedStrings(); + WriteDocumentation( node_list[ i ], filestream ); + fi; + od; + FlushConvertedStrings(); +end ); + +InstallGlobalFunction( AUTODOC_WriteStringListWithSource, + function( string_list, source_positions, filestream ) + local converted_string_list, in_cdata, item; + + if string_list = [ ] then + return; + fi; + converted_string_list := AUTODOC_ConvertMarkdownToGAPDocXML( string_list, source_positions ); + in_cdata := false; + for item in converted_string_list do + if not IsString( item ) then + WriteDocumentation( item, filestream ); + continue; + fi; + if AUTODOC_LineStartsCDATA( item ) then + in_cdata := true; + fi; + if in_cdata = true then + AppendTo( filestream, Chomp( item ), "\n" ); + else + WriteDocumentation( item, filestream ); + fi; + if AUTODOC_LineEndsCDATA( item ) then + in_cdata := false; + fi; + od; +end ); + InstallGlobalFunction( AUTODOC_Diff, function(args...) local diff; diff --git a/tst/errorwithpos.tst b/tst/errorwithpos.tst index 07cf9e2a..179b818a 100644 --- a/tst/errorwithpos.tst +++ b/tst/errorwithpos.tst @@ -11,6 +11,22 @@ gap> ParseFixture := function( arg ) > AutoDoc_Parser_ReadFiles( [ arg[ 1 ] ], tree, default_chapter_data ); > return tree; > end;; +gap> RenderFixtureDescription := function( file, item_name ) +> local tree, section, item, rendered, stream; +> tree := ParseFixture( file ); +> section := SectionInTree( tree, "Parser", "Markdown_errors" ); +> item := First( section!.content, +> x -> IsBound( x!.name ) and x!.name = item_name ); +> rendered := ""; +> stream := OutputTextString( rendered, true ); +> SetPrintFormattingStatus( stream, false ); +> AUTODOC_WriteStringListWithSource( +> item!.description, +> item!.description_source_positions, +> stream ); +> CloseStream( stream ); +> return rendered; +> end;; # # control: valid parser input still works @@ -120,3 +136,17 @@ at tst/errorwithpos/break.g:1 gap> ParseFixture( "tst/errorwithpos/unknown-command.g" ); Error, unknown AutoDoc command @NotACommand, at tst/errorwithpos/unknown-command.g:1 + +# +# markdown syntax errors should also report file and line +# +gap> RenderFixtureDescription( +> "tst/errorwithpos/markdown-backtick-unbalanced.g", +> "BacktickOp" ); +Error, did you forget some `, +at tst/errorwithpos/markdown-backtick-unbalanced.g:3 +gap> RenderFixtureDescription( +> "tst/errorwithpos/markdown-emph-unbalanced.g", +> "EmphOp" ); +Error, did you forget some **, +at tst/errorwithpos/markdown-emph-unbalanced.g:3 diff --git a/tst/errorwithpos/markdown-backtick-unbalanced.g b/tst/errorwithpos/markdown-backtick-unbalanced.g new file mode 100644 index 00000000..259d8065 --- /dev/null +++ b/tst/errorwithpos/markdown-backtick-unbalanced.g @@ -0,0 +1,4 @@ +#! @Chapter Parser +#! @Section Markdown errors +#! @Description Text with `unterminated code span +DeclareGlobalFunction( "BacktickOp" ); diff --git a/tst/errorwithpos/markdown-emph-unbalanced.g b/tst/errorwithpos/markdown-emph-unbalanced.g new file mode 100644 index 00000000..752e306c --- /dev/null +++ b/tst/errorwithpos/markdown-emph-unbalanced.g @@ -0,0 +1,4 @@ +#! @Chapter Parser +#! @Section Markdown errors +#! @Description Text with **unterminated emphasis +DeclareGlobalFunction( "EmphOp" ); diff --git a/tst/markdown.tst b/tst/markdown.tst index 075d305a..2e5e6b8c 100644 --- a/tst/markdown.tst +++ b/tst/markdown.tst @@ -26,7 +26,7 @@ gap> markdown_verbatim := AUTODOC_ConvertMarkdownToGAPDocXML([ > "gap> 1 + 1;", > "2", > "```" -> ]);; +> ], fail);; gap> Length(markdown_verbatim); 1 gap> IsTreeForDocumentationNode(markdown_verbatim[1]); @@ -43,7 +43,7 @@ gap> markdown_verbatim := AUTODOC_ConvertMarkdownToGAPDocXML([ > "fi;", > "```", > "After" -> ]);; +> ], fail);; gap> markdown_verbatim[1]; "Before" gap> IsTreeForDocumentationNode(markdown_verbatim[2]); @@ -58,7 +58,7 @@ gap> markdown_verbatim := AUTODOC_ConvertMarkdownToGAPDocXML([ > "~~~", > "gap> [[2]]>[[1]];", > "~~~" -> ]);; +> ], fail);; gap> markdown_verbatim[1]!.content; [ "gap> [[2]]>[[1]];" ] gap> markdown_verbatim := AUTODOC_ConvertMarkdownToGAPDocXML([ @@ -66,14 +66,14 @@ gap> markdown_verbatim := AUTODOC_ConvertMarkdownToGAPDocXML([ > "gap> 1 + 1;", > "2", > "```" -> ]);; +> ], fail);; gap> markdown_verbatim[1]!.element_name; "Example" gap> markdown_verbatim := AUTODOC_ConvertMarkdownToGAPDocXML([ > "```@log", > "#I some log message", > "```" -> ]);; +> ], fail);; gap> markdown_verbatim[1]!.element_name; "Log" gap> markdown_verbatim := AUTODOC_ConvertMarkdownToGAPDocXML([ @@ -85,13 +85,13 @@ gap> markdown_verbatim := AUTODOC_ConvertMarkdownToGAPDocXML([ > "#! @InsertCode Increment", > "## Code is inserted here.", > "```" -> ]);; +> ], fail);; gap> markdown_verbatim[1]!.content; [ "#! @BeginCode Increment", "i := i + 1;", "#! @EndCode", "", "#! @InsertCode Increment", "## Code is inserted here." ] gap> AUTODOC_ConvertMarkdownToGAPDocXML([ > "` & more`" -> ]) = [ +> ], fail) = [ > "<Log attr="x"> & more" > ]; true