redsnow 0.1.6 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (101) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +2 -0
  3. data/ext/snowcrash/Makefile +1 -1
  4. data/ext/snowcrash/bin/snowcrash +0 -0
  5. data/ext/snowcrash/configure +9 -9
  6. data/ext/snowcrash/ext/markdown-parser/Makefile +87 -0
  7. data/ext/snowcrash/{sundown → ext/markdown-parser/ext/sundown}/CONTRIBUTING.md +0 -0
  8. data/ext/snowcrash/{sundown → ext/markdown-parser/ext/sundown}/Makefile +2 -1
  9. data/ext/snowcrash/{sundown → ext/markdown-parser/ext/sundown}/Makefile.win +0 -0
  10. data/ext/snowcrash/{sundown → ext/markdown-parser/ext/sundown}/examples/smartypants.c +0 -0
  11. data/ext/snowcrash/{sundown → ext/markdown-parser/ext/sundown}/examples/sundown.c +0 -0
  12. data/ext/snowcrash/{sundown → ext/markdown-parser/ext/sundown}/html/houdini.h +0 -0
  13. data/ext/snowcrash/{sundown → ext/markdown-parser/ext/sundown}/html/houdini_href_e.c +0 -0
  14. data/ext/snowcrash/{sundown → ext/markdown-parser/ext/sundown}/html/houdini_html_e.c +0 -0
  15. data/ext/snowcrash/{sundown → ext/markdown-parser/ext/sundown}/html/html.c +0 -0
  16. data/ext/snowcrash/{sundown → ext/markdown-parser/ext/sundown}/html/html.h +0 -0
  17. data/ext/snowcrash/{sundown → ext/markdown-parser/ext/sundown}/html/html_smartypants.c +0 -0
  18. data/ext/snowcrash/{sundown → ext/markdown-parser/ext/sundown}/html_block_names.txt +0 -0
  19. data/ext/snowcrash/{sundown → ext/markdown-parser/ext/sundown}/src/autolink.c +0 -0
  20. data/ext/snowcrash/{sundown → ext/markdown-parser/ext/sundown}/src/autolink.h +0 -0
  21. data/ext/snowcrash/{sundown → ext/markdown-parser/ext/sundown}/src/buffer.c +0 -0
  22. data/ext/snowcrash/{sundown → ext/markdown-parser/ext/sundown}/src/buffer.h +1 -1
  23. data/ext/snowcrash/{sundown → ext/markdown-parser/ext/sundown}/src/html_blocks.h +0 -0
  24. data/ext/snowcrash/{sundown → ext/markdown-parser/ext/sundown}/src/markdown.c +9 -3
  25. data/ext/snowcrash/{sundown → ext/markdown-parser/ext/sundown}/src/markdown.h +0 -0
  26. data/ext/snowcrash/{sundown → ext/markdown-parser/ext/sundown}/src/src_map.c +11 -7
  27. data/ext/snowcrash/{sundown → ext/markdown-parser/ext/sundown}/src/src_map.h +1 -1
  28. data/ext/snowcrash/{sundown → ext/markdown-parser/ext/sundown}/src/stack.c +0 -0
  29. data/ext/snowcrash/{sundown → ext/markdown-parser/ext/sundown}/src/stack.h +0 -0
  30. data/ext/snowcrash/{sundown → ext/markdown-parser/ext/sundown}/sundown.def +0 -0
  31. data/ext/snowcrash/ext/markdown-parser/msvc/markdown/markdown.vcproj +188 -0
  32. data/ext/snowcrash/ext/markdown-parser/msvc/msvc.sln +38 -0
  33. data/ext/snowcrash/ext/markdown-parser/msvc/sundown/sundown.vcproj +206 -0
  34. data/ext/snowcrash/ext/markdown-parser/src/ByteBuffer.cc +92 -0
  35. data/ext/snowcrash/ext/markdown-parser/src/ByteBuffer.h +82 -0
  36. data/ext/snowcrash/ext/markdown-parser/src/MarkdownNode.cc +152 -0
  37. data/ext/snowcrash/ext/markdown-parser/src/MarkdownNode.h +103 -0
  38. data/ext/snowcrash/ext/markdown-parser/src/MarkdownParser.cc +388 -0
  39. data/ext/snowcrash/{src → ext/markdown-parser/src}/MarkdownParser.h +43 -33
  40. data/ext/snowcrash/snowcrash.gyp +114 -63
  41. data/ext/snowcrash/src/ActionParser.h +334 -398
  42. data/ext/snowcrash/src/AssetParser.h +82 -171
  43. data/ext/snowcrash/src/Blueprint.h +7 -2
  44. data/ext/snowcrash/src/BlueprintParser.h +212 -286
  45. data/ext/snowcrash/src/BlueprintUtility.h +2 -2
  46. data/ext/snowcrash/src/CBlueprint.h +1 -1
  47. data/ext/snowcrash/src/CSourceAnnotation.cc +11 -11
  48. data/ext/snowcrash/src/CSourceAnnotation.h +9 -9
  49. data/ext/snowcrash/src/CodeBlockUtility.h +199 -149
  50. data/ext/snowcrash/src/HeadersParser.h +197 -0
  51. data/ext/snowcrash/src/ParameterParser.h +429 -0
  52. data/ext/snowcrash/src/ParametersParser.h +136 -211
  53. data/ext/snowcrash/src/PayloadParser.h +458 -562
  54. data/ext/snowcrash/src/Platform.h +0 -3
  55. data/ext/snowcrash/src/ResourceGroupParser.h +183 -164
  56. data/ext/snowcrash/src/ResourceParser.h +325 -493
  57. data/ext/snowcrash/src/Section.cc +42 -0
  58. data/ext/snowcrash/src/Section.h +47 -0
  59. data/ext/snowcrash/src/SectionParser.h +229 -0
  60. data/ext/snowcrash/src/SectionParserData.h +81 -0
  61. data/ext/snowcrash/src/SectionProcessor.h +211 -0
  62. data/ext/snowcrash/src/Signature.cc +74 -0
  63. data/ext/snowcrash/src/Signature.h +32 -0
  64. data/ext/snowcrash/src/SourceAnnotation.h +7 -20
  65. data/ext/snowcrash/src/StringUtility.h +30 -10
  66. data/ext/snowcrash/src/SymbolTable.h +7 -7
  67. data/ext/snowcrash/src/UriTemplateParser.cc +10 -10
  68. data/ext/snowcrash/src/UriTemplateParser.h +11 -14
  69. data/ext/snowcrash/src/ValuesParser.h +122 -0
  70. data/ext/snowcrash/src/Version.h +2 -2
  71. data/ext/snowcrash/src/csnowcrash.cc +5 -5
  72. data/ext/snowcrash/src/csnowcrash.h +3 -3
  73. data/ext/snowcrash/src/snowcrash.cc +74 -4
  74. data/ext/snowcrash/src/snowcrash.h +9 -4
  75. data/ext/snowcrash/src/snowcrash/snowcrash.cc +16 -16
  76. data/ext/snowcrash/tools/homebrew/snowcrash.rb +3 -2
  77. data/ext/snowcrash/vcbuild.bat +13 -4
  78. data/lib/redsnow.rb +5 -5
  79. data/lib/redsnow/binding.rb +1 -1
  80. data/lib/redsnow/blueprint.rb +33 -2
  81. data/lib/redsnow/parseresult.rb +7 -4
  82. data/lib/redsnow/version.rb +1 -1
  83. data/test/redsnow_binding_test.rb +6 -6
  84. data/test/redsnow_parseresult_test.rb +1 -1
  85. metadata +62 -42
  86. data/ext/snowcrash/src/BlockUtility.h +0 -186
  87. data/ext/snowcrash/src/BlueprintParserCore.h +0 -190
  88. data/ext/snowcrash/src/BlueprintSection.h +0 -140
  89. data/ext/snowcrash/src/DescriptionSectionUtility.h +0 -156
  90. data/ext/snowcrash/src/HeaderParser.h +0 -289
  91. data/ext/snowcrash/src/ListBlockUtility.h +0 -273
  92. data/ext/snowcrash/src/ListUtility.h +0 -95
  93. data/ext/snowcrash/src/MarkdownBlock.cc +0 -176
  94. data/ext/snowcrash/src/MarkdownBlock.h +0 -93
  95. data/ext/snowcrash/src/MarkdownParser.cc +0 -266
  96. data/ext/snowcrash/src/ParameterDefinitonParser.h +0 -645
  97. data/ext/snowcrash/src/Parser.cc +0 -71
  98. data/ext/snowcrash/src/Parser.h +0 -29
  99. data/ext/snowcrash/src/ParserCore.cc +0 -120
  100. data/ext/snowcrash/src/ParserCore.h +0 -82
  101. data/ext/snowcrash/src/SectionUtility.h +0 -142
@@ -104,7 +104,7 @@ namespace snowcrash {
104
104
  * \param request A request to look for.
105
105
  * \return Iterator pointing to the matching request within given method requests.
106
106
  */
107
- FORCEINLINE Collection<Request>::const_iterator FindRequest(const TransactionExample& example, const Request& request) {
107
+ inline Collection<Request>::const_iterator FindRequest(const TransactionExample& example, const Request& request) {
108
108
  return std::find_if(example.requests.begin(),
109
109
  example.requests.end(),
110
110
  std::bind2nd(MatchPayload(), request));
@@ -116,7 +116,7 @@ namespace snowcrash {
116
116
  * \param response A response to look for.
117
117
  * \return Iterator pointing to the matching response within given method requests.
118
118
  */
119
- FORCEINLINE Collection<Response>::const_iterator FindResponse(const TransactionExample& example, const Response& response) {
119
+ inline Collection<Response>::const_iterator FindResponse(const TransactionExample& example, const Response& response) {
120
120
  return std::find_if(example.responses.begin(),
121
121
  example.responses.end(),
122
122
  std::bind2nd(MatchPayload(), response));
@@ -23,7 +23,7 @@ extern "C" {
23
23
  /** brief Blueprint Parser Options Enums */
24
24
  enum sc_blueprint_parser_option {
25
25
  SC_RENDER_DESCRIPTIONS_OPTION = (1 << 0), /// < Render Markdown in description.
26
- SC_REQUIRE_BLUEPRINT_NAME_OPTION = (1 << 1), /// < Treat missing blueprint name as error
26
+ SC_REQUIRE_BLUEPRINT_NAME_OPTION = (1 << 1) /// < Treat missing blueprint name as error
27
27
  };
28
28
 
29
29
  /** Parameter Use flag */
@@ -11,14 +11,14 @@
11
11
  #include "snowcrash.h"
12
12
 
13
13
 
14
- SC_API sc_result_t* sc_result_new()
14
+ SC_API sc_report_t* sc_report_new()
15
15
  {
16
- return AS_TYPE(sc_result_t, ::new snowcrash::Result);
16
+ return AS_TYPE(sc_report_t, ::new snowcrash::Report);
17
17
  }
18
18
 
19
- SC_API void sc_result_free(sc_result_t* result)
19
+ SC_API void sc_report_free(sc_report_t* report)
20
20
  {
21
- ::delete AS_TYPE(snowcrash::Result, result);
21
+ ::delete AS_TYPE(snowcrash::Report, report);
22
22
  }
23
23
 
24
24
  /*----------------------------------------------------------------------*/
@@ -33,7 +33,7 @@ SC_API const sc_location_t* sc_location_handler(const sc_source_annotation_t* so
33
33
 
34
34
  SC_API size_t sc_location_size(const sc_location_t* location)
35
35
  {
36
- const snowcrash::SourceCharactersBlock* p = AS_CTYPE(snowcrash::SourceCharactersBlock, location);
36
+ const mdp::CharactersRangeSet* p = AS_CTYPE(mdp::CharactersRangeSet, location);
37
37
  if(!p)
38
38
  return 0;
39
39
  return p->size();
@@ -41,7 +41,7 @@ SC_API size_t sc_location_size(const sc_location_t* location)
41
41
 
42
42
  SC_API size_t sc_location_length(const sc_location_t* location, size_t index)
43
43
  {
44
- const snowcrash::SourceCharactersBlock* p = AS_CTYPE(snowcrash::SourceCharactersBlock, location);
44
+ const mdp::CharactersRangeSet* p = AS_CTYPE(mdp::CharactersRangeSet, location);
45
45
  if(!p)
46
46
  return 0;
47
47
  return p->at(index).length;
@@ -49,7 +49,7 @@ SC_API size_t sc_location_length(const sc_location_t* location, size_t index)
49
49
 
50
50
  SC_API size_t sc_location_location(const sc_location_t* location, size_t index)
51
51
  {
52
- const snowcrash::SourceCharactersBlock* p = AS_CTYPE(snowcrash::SourceCharactersBlock, location);
52
+ const mdp::CharactersRangeSet* p = AS_CTYPE(mdp::CharactersRangeSet, location);
53
53
  if(!p)
54
54
  return 0;
55
55
  return p->at(index).location;
@@ -57,9 +57,9 @@ SC_API size_t sc_location_location(const sc_location_t* location, size_t index)
57
57
 
58
58
  /*----------------------------------------------------------------------*/
59
59
 
60
- SC_API const sc_error_t* sc_error_handler(const sc_result_t* result)
60
+ SC_API const sc_error_t* sc_error_handler(const sc_report_t* report)
61
61
  {
62
- const snowcrash::Result* p = AS_CTYPE(snowcrash::Result, result);
62
+ const snowcrash::Report* p = AS_CTYPE(snowcrash::Report, report);
63
63
  if(!p)
64
64
  return NULL;
65
65
  return AS_CTYPE(sc_error_t, &p->error);
@@ -91,9 +91,9 @@ SC_API int sc_error_ok(const sc_error_t* error)
91
91
 
92
92
  /*----------------------------------------------------------------------*/
93
93
 
94
- SC_API const sc_warnings_t* sc_warnings_handler(const sc_result_t* result)
94
+ SC_API const sc_warnings_t* sc_warnings_handler(const sc_report_t* report)
95
95
  {
96
- const snowcrash::Result* p = AS_CTYPE(snowcrash::Result, result);
96
+ const snowcrash::Report* p = AS_CTYPE(snowcrash::Report, report);
97
97
  if(!p)
98
98
  return NULL;
99
99
  return AS_CTYPE(sc_warnings_t, &p->warnings);
@@ -17,9 +17,9 @@
17
17
  extern "C" {
18
18
  #endif
19
19
 
20
- /** Class Result wrapper */
21
- struct sc_result_s;
22
- typedef struct sc_result_s sc_result_t;
20
+ /** Class Report wrapper */
21
+ struct sc_report_s;
22
+ typedef struct sc_report_s sc_report_t;
23
23
 
24
24
  /** Array warnings wrapper */
25
25
  struct sc_warnings_s;
@@ -43,11 +43,11 @@ extern "C" {
43
43
 
44
44
  /*----------------------------------------------------------------------*/
45
45
 
46
- /** \returns pointer to allocated Result*/
47
- SC_API sc_result_t* sc_result_new();
46
+ /** \returns pointer to allocated Report*/
47
+ SC_API sc_report_t* sc_report_new();
48
48
 
49
- /** \deallocate Result from pointer*/
50
- SC_API void sc_result_free(sc_result_t* result);
49
+ /** \deallocate Report from pointer*/
50
+ SC_API void sc_report_free(sc_report_t* report);
51
51
 
52
52
  /*----------------------------------------------------------------------*/
53
53
 
@@ -66,7 +66,7 @@ extern "C" {
66
66
  /*----------------------------------------------------------------------*/
67
67
 
68
68
  /** \returns error handler*/
69
- SC_API const sc_error_t* sc_error_handler(const sc_result_t* result);
69
+ SC_API const sc_error_t* sc_error_handler(const sc_report_t* report);
70
70
 
71
71
  /** \returns error message*/
72
72
  SC_API const char* sc_error_message(const sc_error_t* error);
@@ -80,7 +80,7 @@ extern "C" {
80
80
  /*----------------------------------------------------------------------*/
81
81
 
82
82
  /** \returns warnings handler*/
83
- SC_API const sc_warnings_t* sc_warnings_handler(const sc_result_t* result);
83
+ SC_API const sc_warnings_t* sc_warnings_handler(const sc_report_t* report);
84
84
 
85
85
  /** \returns warnings array size*/
86
86
  SC_API size_t sc_warnings_size(const sc_warnings_t* warning);
@@ -10,180 +10,230 @@
10
10
  #define SNOWCRASH_CODEBLOCKUTILITY_H
11
11
 
12
12
  #include <sstream>
13
- #include "BlockUtility.h"
13
+ #include "Section.h"
14
+ #include "StringUtility.h"
14
15
 
15
16
  namespace snowcrash {
16
17
 
17
- /**
18
- * Compute expected indentation level of a code block.
19
- * \param section A section to compute indentation level for
20
- * \return Indentation level (number of tabs) for a block to be
21
- * considered a pre-formatted code block in given section.
22
- */
23
- FORCEINLINE size_t CodeBlockIndentationLevel(const BlueprintSection& section)
24
- {
25
- if (!section.hasParent() ||
26
- section.parent().type == BlueprintSectionType ||
27
- section.parent().type == ResourceGroupSectionType ||
28
- section.parent().type == ResourceSectionType ||
29
- section.parent().type == ResourceMethodSectionType ||
30
- section.parent().type == ActionSectionType) {
31
-
32
- return 1;
18
+ struct CodeBlockUtility {
19
+
20
+ /**
21
+ * \brief Expected indentation level of a code block.
22
+ *
23
+ * \param type Section type to retrieve the indentation level for
24
+ * \return Indentation level (number of tabs) for a block to be
25
+ * considered a pre-formatted code block in given section.
26
+ */
27
+ static size_t codeBlockIndentationLevel(const SectionType& type)
28
+ {
29
+ if (type == BlueprintSectionType ||
30
+ type == ResourceGroupSectionType ||
31
+ type == ResourceSectionType ||
32
+ type == ActionSectionType) {
33
+
34
+ return 1;
35
+ }
36
+ else if (type == RequestBodySectionType ||
37
+ type == ResponseBodySectionType ||
38
+ type == ModelBodySectionType) {
39
+
40
+ return 2;
41
+ }
42
+ else {
43
+
44
+ return 3;
45
+ }
33
46
  }
34
- else if (section.parent().type == RequestBodySectionType ||
35
- section.parent().type == ResponseBodySectionType ||
36
- section.parent().type == ObjectBodySectionType ||
37
- section.parent().type == ModelBodySectionType) {
47
+
48
+ /**
49
+ * \brief Retrieve the textual content of a Markdown node as if it was a code block.
50
+ * \param pd Parser status
51
+ * \param report Report log
52
+ * \param conten The content retrieved
53
+ */
54
+ static void contentAsCodeBlock(const MarkdownNodeIterator& node,
55
+ const SectionParserData& pd,
56
+ Report& report,
57
+ mdp::ByteBuffer& content) {
38
58
 
39
- return 2;
40
- }
41
- else {
59
+ if (node->type == mdp::CodeMarkdownNodeType) {
60
+ content += node->text;
61
+
62
+ checkExcessiveIndentation(node, pd, report);
63
+ return;
64
+ }
65
+
66
+ // Other blocks, process & warn
67
+ content += mdp::MapBytesRangeSet(node->sourceMap, pd.sourceData);
68
+
69
+ // WARN: Not a preformatted code block
70
+ size_t level = codeBlockIndentationLevel(pd.parentSectionContext());
71
+ std::stringstream ss;
72
+ ss << SectionName(pd.sectionContext());
73
+
74
+ if (pd.sectionContext() == BodySectionType) {
75
+ ss << " asset";
76
+ }
77
+
78
+ ss << " is expected to be a pre-formatted code block, every of its line indented by exactly ";
79
+ ss << level * 4 << " spaces or " << level << " tabs";
42
80
 
43
- return 3;
81
+ mdp::CharactersRangeSet sourceMap = mdp::BytesRangeSetToCharactersRangeSet(node->sourceMap, pd.sourceData);
82
+ report.warnings.push_back(Warning(ss.str(),
83
+ IndentationWarning,
84
+ sourceMap));
44
85
  }
45
- }
46
-
47
- /**
48
- * \brief Check code block for potential excessive indentation of a list item.
49
- * \return True if code block does not contain potential recognized list, false otherwise.
50
- */
51
- template <class T>
52
- FORCEINLINE bool CheckCodeBlockListItem(const BlueprintSection& section,
53
- const BlockIterator& cur,
54
- const SourceData& sourceData,
55
- Result& result)
56
- {
57
-
58
- // Check for possible superfluous indentation of a recognized list items.
59
- std::string line = GetFirstLine(cur->content);
60
- TrimStringStart(line);
61
86
 
62
- // If line appears to be a Markdown list construct a dummy list item
63
- // with the first line of code block as its content.
64
- // Check the list item with respective internal classifier.
65
- if (line.empty() ||
66
- (line[0] != '-' && line[0] != '+' && line[0] != '*'))
67
- return true;
68
-
69
- // Skip leading Markdown list item mark
70
- std::string listItemContent = line.substr(1, std::string::npos);
71
- TrimStringStart(listItemContent);
72
- MarkdownBlock::Stack dummyList;
73
-
74
- dummyList.push_back(MarkdownBlock(ListItemBlockBeginType, SourceData(), 0, SourceDataBlock()));
75
- dummyList.push_back(MarkdownBlock(ListItemBlockEndType, listItemContent, 0, MakeSourceDataBlock(0, 0)));
76
-
77
- SectionType type = ClassifyInternaListBlock<T>(dummyList.begin(), dummyList.end());
78
- if (type != UndefinedSectionType) {
87
+ /** \brief Retrieve the textual content of a signature markdown */
88
+ static void signatureContentAsCodeBlock(const MarkdownNodeIterator& node,
89
+ const SectionParserData& pd,
90
+ Report& report,
91
+ mdp::ByteBuffer& content) {
79
92
 
80
- size_t level = CodeBlockIndentationLevel(section);
81
- --level;
93
+ mdp::ByteBuffer remainingContent;
94
+ GetFirstLine(node->text, remainingContent);
82
95
 
83
- // WARN: Superfluous indentation
96
+ if (remainingContent.empty())
97
+ return;
98
+
99
+ content += remainingContent;
100
+ content += "\n";
101
+
102
+ // WARN: Not a preformatted code block but multiline signature
103
+ size_t level = codeBlockIndentationLevel(pd.parentSectionContext());
84
104
  std::stringstream ss;
85
- ss << "excessive indentation, ";
86
- ss << SectionName(type) << " ";
87
- if (level) {
88
- ss << "section is expected to be indented by just ";
89
- ss << level * 4 << " spaces or " << level << " tab";
90
- if (level > 1)
91
- ss << "s";
92
- }
93
- else {
94
- ss << "section is not expected to be indented";
105
+
106
+ ss << SectionName(pd.sectionContext());
107
+
108
+ if (pd.sectionContext() == BodySectionType) {
109
+ ss << " asset";
95
110
  }
111
+
112
+ ss << " is expected to be a pre-formatted code block, separate it by a newline and ";
113
+ ss << "indent every of its line by ";
114
+ ss << level * 4 << " spaces or " << level << " tabs";
96
115
 
97
- SourceCharactersBlock sourceBlock = CharacterMapForBlock(cur,
98
- cur,
99
- section.bounds,
100
- sourceData);
101
- result.warnings.push_back(Warning(ss.str(),
116
+ mdp::CharactersRangeSet sourceMap = mdp::BytesRangeSetToCharactersRangeSet(node->sourceMap, pd.sourceData);
117
+ report.warnings.push_back(Warning(ss.str(),
102
118
  IndentationWarning,
103
- sourceBlock));
104
-
105
- return false;
119
+ sourceMap));
106
120
  }
107
121
 
108
- return true;
109
- }
110
-
111
- /**
112
- * \brief Parses given block as a preformatted code block.
113
- * \param section Actual section being parsed.
114
- * \param cur Cursor within the section boundaries.
115
- * \param parser Parser instance.
116
- * \param action An output data buffer.
117
- * \param sourceMap An output source map buffer.
118
- * \return A block parser section result, pointing at the last block parsed.
119
- */
120
- template <class T>
121
- FORCEINLINE ParseSectionResult ParsePreformattedBlock(const BlueprintSection& section,
122
- const BlockIterator& cur,
123
- BlueprintParserCore& parser,
124
- SourceData& data,
125
- SourceDataBlock& sourceMap) {
126
-
127
- ParseSectionResult result = std::make_pair(Result(), cur);
128
- BlockIterator sectionCur = cur;
129
- std::stringstream dataStream;
130
-
131
- if (sectionCur->type == CodeBlockType) {
132
- // Well formatted content, stream it up
133
- dataStream << sectionCur->content;
122
+ /**
123
+ * \brief Check for potential excessive indentation of a list section
124
+ * \return True if code block contains a recognized list section, false otherwise.
125
+ */
126
+ static bool checkExcessiveIndentation(const MarkdownNodeIterator& node,
127
+ const SectionParserData& pd,
128
+ Report& report) {
134
129
 
135
- // Check for excessive indentation
136
- CheckCodeBlockListItem<T>(section, sectionCur, parser.sourceData, result.first);
137
- }
138
- else {
139
- // Other blocks, process & warn
140
- if (sectionCur->type == QuoteBlockBeginType) {
141
- sectionCur = SkipToClosingBlock(sectionCur, section.bounds.second, QuoteBlockBeginType, QuoteBlockEndType);
142
- }
143
- else if (sectionCur->type == ListBlockBeginType) {
144
- sectionCur = SkipToClosingBlock(sectionCur, section.bounds.second, ListBlockBeginType, ListBlockEndType);
145
- }
146
- else if (sectionCur->type == ListItemBlockBeginType) {
147
- sectionCur = SkipToClosingBlock(sectionCur, section.bounds.second, ListItemBlockBeginType, ListItemBlockEndType);
130
+ // Check for possible superfluous indentation of a recognized list items.
131
+ mdp::ByteBuffer r;
132
+ mdp::ByteBuffer line = GetFirstLine(node->text, r);
133
+ TrimString(line);
134
+
135
+ // If line appears to be a Markdown list.
136
+ if (line.empty() ||
137
+ (line[0] != '-' && line[0] != '+' && line[0] != '*'))
138
+ return false;
139
+
140
+ // Skip leading Markdown list item mark
141
+ std::string signature = line.substr(1, std::string::npos);
142
+ TrimStringStart(signature);
143
+
144
+ SectionType type = RecognizeCodeBlockFirstLine(signature);
145
+
146
+ if (type != UndefinedSectionType) {
147
+
148
+ // Check signature.
149
+ size_t level = codeBlockIndentationLevel(pd.sectionContext());
150
+ --level;
151
+
152
+ // WARN: Superfluous indentation
153
+ std::stringstream ss;
154
+ ss << "excessive indentation, ";
155
+ ss << SectionName(type) << " ";
156
+
157
+ if (level) {
158
+ ss << "section is expected to be indented by just ";
159
+ ss << level * 4 << " spaces or " << level << " tab";
160
+
161
+ if (level > 1)
162
+ ss << "s";
163
+ }
164
+ else {
165
+ ss << "section is not expected to be indented";
166
+ }
167
+
168
+ mdp::CharactersRangeSet sourceMap = mdp::BytesRangeSetToCharactersRangeSet(node->sourceMap, pd.sourceData);
169
+ report.warnings.push_back(Warning(ss.str(),
170
+ IndentationWarning,
171
+ sourceMap));
148
172
  }
149
173
 
150
- if (!CheckCursor(section, sectionCur, parser.sourceData, result.first))
151
- return result;
152
- dataStream << MapSourceData(parser.sourceData, sectionCur->sourceMap);
174
+ return false;
175
+ }
176
+
177
+ /**
178
+ * \brief Parse one line of raw `key:value` data.
179
+ * \param line A line to parse
180
+ * \param keyValuePair The output buffer to place the parsed data into
181
+ * \return True on success, false otherwise
182
+ */
183
+ static bool keyValueFromLine(const mdp::ByteBuffer& line,
184
+ KeyValuePair& keyValuePair) {
153
185
 
154
- // WARN: Not a preformatted code block
155
- std::stringstream ss;
186
+ std::vector<std::string> rawMetadata = SplitOnFirst(line, ':');
187
+ if (rawMetadata.size() != 2)
188
+ return false;
156
189
 
157
- // Build the warning message
158
- size_t level = CodeBlockIndentationLevel(section);
159
- if (section.type == DanglingBodySectionType ||
160
- section.type == DanglingSchemaSectionType) {
161
-
162
- ss << "dangling " << SectionName(section.type) << " asset, ";
163
- ss << "expected a pre-formatted code block, indent every of its line by ";
164
- ss << level * 4 << " spaces or " << level << " tabs";
190
+ keyValuePair = std::make_pair(rawMetadata[0], rawMetadata[1]);
191
+ TrimString(keyValuePair.first);
192
+ TrimString(keyValuePair.second);
193
+
194
+ return (!keyValuePair.first.empty() && !keyValuePair.second.empty());
195
+ }
196
+
197
+ /**
198
+ * \brief Add dangling message body asset to the given string
199
+ * \param out The string to which the dangling asset should be added
200
+ */
201
+ static void addDanglingAsset(const MarkdownNodeIterator& node,
202
+ SectionParserData& pd,
203
+ SectionType& sectionType,
204
+ Report& report,
205
+ mdp::ByteBuffer& out) {
206
+
207
+ mdp::ByteBuffer asset;
208
+
209
+ if (node->type == mdp::CodeMarkdownNodeType) {
210
+ asset = node->text;
211
+ } else {
212
+ asset = mdp::MapBytesRangeSet(node->sourceMap, pd.sourceData);
165
213
  }
166
- else {
214
+
215
+ TwoNewLines(asset);
216
+ out += asset;
217
+
218
+ size_t level = CodeBlockUtility::codeBlockIndentationLevel(sectionType);
219
+
220
+ if (node->type == mdp::CodeMarkdownNodeType)
221
+ level--; // Deduct one level for a code block
222
+
167
223
 
168
- ss << SectionName(section.type) << " asset ";
169
- ss << "is expected to be a pre-formatted code block, every of its line indented by exactly ";
170
- ss << level * 4 << " spaces or " << level << " tabs";
224
+ if (level) {
225
+ // WARN: Dangling asset
226
+ std::stringstream ss;
227
+ ss << "dangling message-body asset, expected a pre-formatted code block, ";
228
+ ss << "indent every of it's line by " << level*4 << " spaces or " << level << " tabs";
229
+
230
+ mdp::CharactersRangeSet sourceMap = mdp::BytesRangeSetToCharactersRangeSet(node->sourceMap, pd.sourceData);
231
+ report.warnings.push_back(Warning(ss.str(),
232
+ IndentationWarning,
233
+ sourceMap));
171
234
  }
172
-
173
- SourceCharactersBlock sourceBlock = CharacterMapForBlock(sectionCur, cur, section.bounds, parser.sourceData);
174
- result.first.warnings.push_back(Warning(ss.str(),
175
- IndentationWarning,
176
- sourceBlock));
177
235
  }
178
-
179
- data = dataStream.str();
180
- sourceMap = sectionCur->sourceMap;
181
-
182
- if (sectionCur != section.bounds.second)
183
- result.second = ++sectionCur;
184
-
185
- return result;
186
- }
236
+ };
187
237
  }
188
238
 
189
239
  #endif