redsnow 0.1.6 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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