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
@@ -1,87 +1,97 @@
1
1
  //
2
2
  // MarkdownParser.h
3
- // snowcrash
3
+ // markdownparser
4
4
  //
5
- // Created by Zdenek Nemec on 4/15/13.
6
- // Copyright (c) 2013 Apiary Inc. All rights reserved.
5
+ // Created by Zdenek Nemec on 4/18/14.
6
+ // Copyright (c) 2014 Apiary Inc. All rights reserved.
7
7
  //
8
8
 
9
- #ifndef SNOWCRASH_MARKDOWNPARSER_H
10
- #define SNOWCRASH_MARKDOWNPARSER_H
9
+ #ifndef MARKDOWNPARSER_MARKDOWNPARSER_H
10
+ #define MARKDOWNPARSER_MARKDOWNPARSER_H
11
11
 
12
- #include "ParserCore.h"
13
- #include "SourceAnnotation.h"
14
- #include "MarkdownBlock.h"
12
+ #include "ByteBuffer.h"
13
+ #include "MarkdownNode.h"
15
14
  #include "markdown.h"
16
15
 
17
- namespace snowcrash {
16
+ namespace mdp {
18
17
 
19
- //
20
- // Markdown Parser
21
- //
18
+ /**
19
+ * GitHub-flavored Markdown Parser
20
+ */
22
21
  class MarkdownParser {
23
22
  public:
24
- // Default sundown parser configuration
25
- static const size_t OutputUnitSize; // = 64;
26
- static const size_t MaxNesting;// = 16;
27
- static const int ParserExtensions;// = MKDEXT_FENCED_CODE | MKDEXT_NO_INTRA_EMPHASIS /*| MKDEXT_TABLES */;
23
+ MarkdownParser();
24
+ MarkdownParser(const MarkdownParser&);
25
+ MarkdownParser& operator=(const MarkdownParser&);
26
+
27
+ /**
28
+ * \brief Parse source buffer
29
+ *
30
+ * \param source Markdown source data to be parsed
31
+ * \param ast Parsed AST (root node)
32
+ */
33
+ void parse(const ByteBuffer& source, MarkdownNode& ast);
28
34
 
29
- // Parse source Markdown into Markdown AST
30
- void parse(const SourceData& source, Result& result, MarkdownBlock::Stack& markdown);
31
-
32
35
  private:
36
+ MarkdownNode* m_workingNode;
37
+ bool m_listBlockContext;
38
+ const ByteBuffer* m_source;
39
+ size_t m_sourceLength;
40
+
41
+ static const size_t OutputUnitSize;
42
+ static const size_t MaxNesting;
43
+ static const int ParserExtensions;
44
+
33
45
  typedef sd_callbacks RenderCallbacks;
34
- typedef void * RenderCallbackData;
35
-
36
46
  RenderCallbacks renderCallbacks();
37
- RenderCallbackData renderCallbackData();
38
47
 
39
- MarkdownBlock::Stack m_renderStack;
48
+ typedef void * RenderCallbackData;
49
+ RenderCallbackData renderCallbackData();
40
50
 
41
51
  // Header
42
52
  static void renderHeader(struct buf *ob, const struct buf *text, int level, void *opaque);
43
- void renderHeader(const std::string& text, int level);
53
+ void renderHeader(const ByteBuffer& text, int level);
44
54
 
45
55
  // List
46
56
  static void beginList(int flags, void *opaque);
47
57
  void beginList(int flags);
48
58
 
49
59
  static void renderList(struct buf *ob, const struct buf *text, int flags, void *opaque);
50
- void renderList(const std::string& text, int flags);
60
+ void renderList(const ByteBuffer& text, int flags);
51
61
 
52
62
  // List item
53
63
  static void beginListItem(int flags, void *opaque);
54
64
  void beginListItem(int flags);
55
65
 
56
66
  static void renderListItem(struct buf *ob, const struct buf *text, int flags, void *opaque);
57
- void renderListItem(const std::string& text, int flags);
67
+ void renderListItem(const ByteBuffer& text, int flags);
58
68
 
59
69
  // Code block
60
70
  static void renderBlockCode(struct buf *ob, const struct buf *text, const struct buf *lang, void *opaque);
61
- void renderBlockCode(const std::string& text, const std::string& language);
71
+ void renderBlockCode(const ByteBuffer& text, const ByteBuffer& language);
62
72
 
63
73
  // Paragraph
64
74
  static void renderParagraph(struct buf *ob, const struct buf *text, void *opaque);
65
- void renderParagraph(const std::string& text);
75
+ void renderParagraph(const ByteBuffer& text);
66
76
 
67
77
  // Horizontal Rule
68
78
  static void renderHorizontalRule(struct buf *ob, void *opaque);
69
79
  void renderHorizontalRule();
70
-
80
+
71
81
  // HTML
72
82
  static void renderHTML(struct buf *ob, const struct buf *text, void *opaque);
73
- void renderHTML(const std::string& text);
74
-
83
+ void renderHTML(const ByteBuffer& text);
84
+
75
85
  // Quote
76
86
  static void beginQuote(void *opaque);
77
87
  void beginQuote();
78
-
88
+
79
89
  static void renderQuote(struct buf *ob, const struct buf *text, void *opaque);
80
90
  void renderQuote(const std::string& text);
81
91
 
82
92
  // Source maps
83
93
  static void blockDidParse(const src_map* map, const uint8_t *txt_data, size_t size, void *opaque);
84
- void blockDidParse(const SourceDataBlock& sourceMap);
94
+ void blockDidParse(const BytesRangeSet& sourceMap);
85
95
  };
86
96
  }
87
97
 
@@ -2,25 +2,52 @@
2
2
  "includes": [
3
3
  "common.gypi"
4
4
  ],
5
-
6
5
  'targets' : [
7
6
  {
8
- 'target_name': 'sundown',
7
+ 'target_name': 'libsundown',
9
8
  'type': 'static_library',
10
9
  'include_dirs': [
11
- 'sundown/src',
12
- 'sundown/html',
10
+ 'ext/markdown-parser/ext/sundown/src',
11
+ 'ext/markdown-parser/ext/sundown/html'
13
12
  ],
14
13
  'sources': [
15
- 'sundown/src/autolink.c',
16
- 'sundown/src/buffer.c',
17
- 'sundown/html/houdini_href_e.c',
18
- 'sundown/html/houdini_html_e.c',
19
- 'sundown/html/html.c',
20
- 'sundown/html/html_smartypants.c',
21
- 'sundown/src/markdown.c',
22
- 'sundown/src/stack.c',
23
- 'sundown/src/src_map.c'
14
+ 'ext/markdown-parser/ext/sundown/src/autolink.c',
15
+ 'ext/markdown-parser/ext/sundown/src/autolink.h',
16
+ 'ext/markdown-parser/ext/sundown/src/buffer.c',
17
+ 'ext/markdown-parser/ext/sundown/src/buffer.h',
18
+ 'ext/markdown-parser/ext/sundown/src/html_blocks.h',
19
+ 'ext/markdown-parser/ext/sundown/src/markdown.c',
20
+ 'ext/markdown-parser/ext/sundown/src/markdown.h',
21
+ 'ext/markdown-parser/ext/sundown/src/src_map.c',
22
+ 'ext/markdown-parser/ext/sundown/src/src_map.h',
23
+ 'ext/markdown-parser/ext/sundown/src/stack.c',
24
+ 'ext/markdown-parser/ext/sundown/src/stack.h',
25
+ 'ext/markdown-parser/ext/sundown/html/houdini.h',
26
+ 'ext/markdown-parser/ext/sundown/html/houdini_href_e.c',
27
+ 'ext/markdown-parser/ext/sundown/html/houdini_html_e.c',
28
+ 'ext/markdown-parser/ext/sundown/html/html.c',
29
+ 'ext/markdown-parser/ext/sundown/html/html.h',
30
+ 'ext/markdown-parser/ext/sundown/html/html_smartypants.c'
31
+ ]
32
+ },
33
+ {
34
+ 'target_name': 'libmarkdownparser',
35
+ 'type': 'static_library',
36
+ 'include_dirs': [
37
+ 'ext/markdown-parser/ext/sundown/src',
38
+ 'ext/markdown-parser/ext/sundown/html'
39
+ 'ext/markdown-parser/src',
40
+ ],
41
+ 'sources': [
42
+ 'ext/markdown-parser/src/ByteBuffer.cc',
43
+ 'ext/markdown-parser/src/ByteBuffer.h',
44
+ 'ext/markdown-parser/src/MarkdownNode.cc',
45
+ 'ext/markdown-parser/src/MarkdownNode.h',
46
+ 'ext/markdown-parser/src/MarkdownParser.cc',
47
+ 'ext/markdown-parser/src/MarkdownParser.h'
48
+ ],
49
+ 'dependencies': [
50
+ 'libsundown'
24
51
  ]
25
52
  },
26
53
  {
@@ -28,34 +55,64 @@
28
55
  'type': '<(libsnowcrash_type)',
29
56
  'include_dirs': [
30
57
  'src',
31
- 'sundown/src',
32
- 'sundown/src/html'
58
+ 'ext/markdown-parser/src',
59
+ 'ext/markdown-parser/ext/sundown/src',
60
+ 'ext/markdown-parser/ext/sundown/html'
33
61
  ],
34
62
  'sources': [
63
+ 'src/CBlueprint.cc',
64
+ 'src/CBlueprint.h',
65
+ 'src/CSourceAnnotation.cc',
66
+ 'src/CSourceAnnotation.h',
35
67
  'src/HTTP.cc',
36
- 'src/MarkdownBlock.cc',
37
- 'src/MarkdownParser.cc',
38
- 'src/Parser.cc',
39
- 'src/ParserCore.cc',
40
- 'src/RegexMatch.h',
68
+ 'src/HTTP.h',
69
+ 'src/Section.cc',
70
+ 'src/Section.h',
41
71
  'src/Serialize.cc',
42
72
  'src/Serialize.h',
43
73
  'src/SerializeJSON.cc',
74
+ 'src/SerializeJSON.h',
44
75
  'src/SerializeYAML.cc',
45
- 'src/UriTemplateParser.cc',
76
+ 'src/SerializeYAML.h',
77
+ 'src/Signature.cc',
78
+ 'src/Signature.h',
46
79
  'src/snowcrash.cc',
80
+ 'src/snowcrash.h',
47
81
  'src/csnowcrash.cc',
48
- 'src/CBlueprint.cc',
49
- 'src/CSourceAnnotation.cc'
82
+ 'src/csnowcrash.h',
83
+ 'src/UriTemplateParser.cc',
84
+ 'src/UriTemplateParser.h',
85
+ 'src/PayloadParser.h',
86
+ 'src/SectionParserData.h',
87
+ 'src/ActionParser.h',
88
+ 'src/AssetParser.h',
89
+ 'src/Blueprint.h',
90
+ 'src/BlueprintParser.h',
91
+ 'src/BlueprintUtility.h',
92
+ 'src/CodeBlockUtility.h',
93
+ 'src/HeadersParser.h',
94
+ 'src/ParameterParser.h',
95
+ 'src/ParametersParser.h',
96
+ 'src/Platform.h',
97
+ 'src/RegexMatch.h',
98
+ 'src/ResourceGroupParser.h',
99
+ 'src/ResourceParser.h',
100
+ 'src/SectionParser.h',
101
+ 'src/SectionProcessor.h',
102
+ 'src/SourceAnnotation.h',
103
+ 'src/StringUtility.h',
104
+ 'src/SymbolTable.h',
105
+ 'src/ValuesParser.h',
106
+ 'src/Version.h'
50
107
  ],
51
108
  'conditions': [
52
- [ 'OS=="win"',
53
- { 'sources': [ 'src/win/RegexMatch.cc' ] },
109
+ [ 'OS=="win"',
110
+ { 'sources': [ 'src/win/RegexMatch.cc' ] },
54
111
  { 'sources': [ 'src/posix/RegexMatch.cc' ] } # OS != Windows
55
112
  ]
56
113
  ],
57
114
  'dependencies': [
58
- 'sundown'
115
+ 'libmarkdownparser'
59
116
  ]
60
117
  },
61
118
  {
@@ -65,45 +122,44 @@
65
122
  'src',
66
123
  'test',
67
124
  'test/vendor/Catch/include',
68
- 'sundown/src',
69
- 'sundown/src/html'
125
+ 'ext/markdown-parser/src',
126
+ 'ext/markdown-parser/ext/sundown/src',
127
+ 'ext/markdown-parser/ext/sundown/html'
70
128
  ],
71
129
  'sources': [
72
130
  'test/test-ActionParser.cc',
73
131
  'test/test-AssetParser.cc',
74
132
  'test/test-Blueprint.cc',
75
133
  'test/test-BlueprintParser.cc',
76
- 'test/test-HeaderParser.cc',
134
+ 'test/test-HeadersParser.cc',
77
135
  'test/test-Indentation.cc',
78
- 'test/test-ListUtility.cc',
79
- 'test/test-MarkdownBlock.cc',
80
- 'test/test-MarkdownParser.cc',
81
- 'test/test-ParameterDefinitonParser.cc',
136
+ 'test/test-ParameterParser.cc',
82
137
  'test/test-ParametersParser.cc',
83
- 'test/test-Parser.cc',
84
138
  'test/test-PayloadParser.cc',
85
139
  'test/test-RegexMatch.cc',
86
- 'test/test-ResouceGroupParser.cc',
87
140
  'test/test-ResourceParser.cc',
141
+ 'test/test-ResourceGroupParser.cc',
142
+ 'test/test-SectionParser.cc',
88
143
  'test/test-SymbolIdentifier.cc',
89
144
  'test/test-SymbolTable.cc',
145
+ 'test/test-UriTemplateParser.cc',
146
+ 'test/test-ValuesParser.cc',
90
147
  'test/test-Warnings.cc',
91
148
  'test/test-csnowcrash.cc',
92
- 'test/test-UriTemplateParser.cc',
93
149
  'test/test-snowcrash.cc'
94
150
  ],
95
151
  'dependencies': [
96
152
  'libsnowcrash',
97
- 'sundown'
153
+ 'libmarkdownparser'
98
154
  ]
99
155
  },
100
-
101
156
  {
102
157
  'target_name': 'snowcrash',
103
158
  'type': 'executable',
104
159
  'include_dirs': [
105
160
  'src',
106
161
  'src/snowcrash',
162
+ 'ext/markdown-parser/src',
107
163
  'cmdline'
108
164
  ],
109
165
  'sources': [
@@ -111,31 +167,26 @@
111
167
  ],
112
168
  'dependencies': [
113
169
  'libsnowcrash',
114
- 'sundown'
170
+ 'libmarkdownparser'
115
171
  ]
116
- }
117
- ],
118
- 'conditions': [
119
- ['OS in "mac linux"', {
120
- 'targets': [
121
- {
122
- 'target_name': 'perf-libsnowcrash',
123
- 'type': 'executable',
124
- 'include_dirs': [
125
- 'src',
126
- 'cmdline',
127
- 'test',
128
- 'test/performance',
129
- ],
130
- 'sources': [
131
- 'test/performance/perf-snowcrash.cc'
132
- ],
133
- 'dependencies': [
134
- 'libsnowcrash',
135
- 'sundown'
136
- ]
137
- }
172
+ },
173
+ {
174
+ 'target_name': 'perf-libsnowcrash',
175
+ 'type': 'executable',
176
+ 'include_dirs': [
177
+ 'src',
178
+ 'ext/markdown-parser/src',
179
+ 'cmdline',
180
+ 'test',
181
+ 'test/performance',
182
+ ],
183
+ 'sources': [
184
+ 'test/performance/perf-snowcrash.cc'
185
+ ],
186
+ 'dependencies': [
187
+ 'libsnowcrash',
188
+ 'libmarkdownparser'
138
189
  ]
139
- }]
140
- ]
190
+ }
191
+ ]
141
192
  }
@@ -9,468 +9,331 @@
9
9
  #ifndef SNOWCRASH_ACTIONPARSER_H
10
10
  #define SNOWCRASH_ACTIONPARSER_H
11
11
 
12
- #include "BlueprintParserCore.h"
13
- #include "Blueprint.h"
14
- #include "RegexMatch.h"
15
- #include "PayloadParser.h"
16
- #include "HeaderParser.h"
17
- #include "ParametersParser.h"
18
12
  #include "HTTP.h"
19
- #include "DescriptionSectionUtility.h"
13
+ #include "SectionParser.h"
14
+ #include "ParametersParser.h"
15
+ #include "PayloadParser.h"
16
+ #include "RegexMatch.h"
17
+
18
+ namespace snowcrash {
20
19
 
21
- namespace snowcrashconst {
22
-
23
20
  /** Nameless action matching regex */
24
21
  const char* const ActionHeaderRegex = "^[[:blank:]]*" HTTP_REQUEST_METHOD "[[:blank:]]*" URI_TEMPLATE "?$";
25
-
22
+
26
23
  /** Named action matching regex */
27
24
  const char* const NamedActionHeaderRegex = "^[[:blank:]]*" SYMBOL_IDENTIFIER "\\[" HTTP_REQUEST_METHOD "]$";
28
- }
29
25
 
30
- namespace snowcrash {
26
+ /** Internal type alias for Collection of Action */
27
+ typedef Collection<Action>::type Actions;
28
+
29
+ typedef Collection<Action>::const_iterator ActionIterator;
31
30
 
32
- // Method signature
33
- enum ActionSignature {
34
- UndefinedActionSignature,
35
- NoActionSignature,
36
- MethodActionSignature, // # GET
37
- MethodURIActionSignature, // # GET /uri
38
- NamedActionSignature // # My Method [GET]
31
+ /** Action Definition Type */
32
+ enum ActionType {
33
+ NotActionType = 0,
34
+ DependentActionType, /// Action isn't fully defined, depends on parents resource URI
35
+ CompleteActionType, /// Action is fully defined including its URI
36
+ UndefinedActionType = -1
39
37
  };
40
-
41
- // Query method signature
42
- FORCEINLINE ActionSignature GetActionSignature(const MarkdownBlock& block,
43
- Name& name,
44
- HTTPMethod& method) {
45
- if (block.type != HeaderBlockType ||
46
- block.content.empty())
47
- return NoActionSignature;
48
-
49
- CaptureGroups captureGroups;
50
- if (RegexCapture(block.content, snowcrashconst::ActionHeaderRegex, captureGroups, 3)) {
51
- // Nameless action
52
- method = captureGroups[1];
53
- URITemplate uri = captureGroups[2];
54
- return (uri.empty()) ? MethodActionSignature : MethodURIActionSignature;
55
- }
56
- else if (RegexCapture(block.content, snowcrashconst::NamedActionHeaderRegex, captureGroups, 3)) {
57
- // Named action
58
- name = captureGroups[1];
59
- TrimString(name);
60
- method = captureGroups[2];
61
- return NamedActionSignature;
38
+
39
+ /**
40
+ * Action Section processor
41
+ */
42
+ template<>
43
+ struct SectionProcessor<Action> : public SectionProcessorBase<Action> {
44
+
45
+ static MarkdownNodeIterator processSignature(const MarkdownNodeIterator& node,
46
+ const MarkdownNodes& siblings,
47
+ SectionParserData& pd,
48
+ SectionLayout& layout,
49
+ Report& report,
50
+ Action& out) {
51
+
52
+ actionHTTPMethodAndName(node, out.method, out.name);
53
+ TrimString(out.name);
54
+
55
+ mdp::ByteBuffer remainingContent;
56
+ GetFirstLine(node->text, remainingContent);
57
+
58
+ if (!remainingContent.empty()) {
59
+ out.description += remainingContent;
60
+ }
61
+
62
+ return ++MarkdownNodeIterator(node);
62
63
  }
63
-
64
- return NoActionSignature;
65
- }
66
64
 
67
- // Returns true if block has HTTP Method signature, false otherwise
68
- FORCEINLINE bool HasActionSignature(const MarkdownBlock& block) {
69
-
70
- if (block.type != HeaderBlockType ||
71
- block.content.empty())
72
- return false;
73
-
74
- Name name;
75
- HTTPMethod method;
76
- return GetActionSignature(block, name, method) != NoActionSignature;
77
- }
78
-
79
- // Finds an action inside resource
80
- FORCEINLINE Collection<Action>::iterator FindAction(Resource& resource,
81
- const Action& action) {
82
- return std::find_if(resource.actions.begin(),
83
- resource.actions.end(),
84
- std::bind2nd(MatchAction<Action>(), action));
85
- }
86
-
87
- //
88
- // Classifier of internal list items, Payload context
89
- //
90
- template <>
91
- FORCEINLINE SectionType ClassifyInternaListBlock<Action>(const BlockIterator& begin,
92
- const BlockIterator& end) {
93
- if (HasHeaderSignature(begin, end))
94
- return HeadersSectionType;
95
-
96
- if (HasParametersSignature(begin, end))
97
- return ParametersSectionType;
98
-
99
- Name name;
100
- SourceData mediaType;
101
- PayloadSignature payload = GetPayloadSignature(begin, end, name, mediaType);
102
- if (payload == RequestPayloadSignature)
103
- return RequestSectionType;
104
- else if (payload == ResponsePayloadSignature)
105
- return ResponseSectionType;
106
- else if (payload == ObjectPayloadSignature)
107
- return ObjectSectionType;
108
- else if (payload == ModelPayloadSignature)
109
- return ModelSectionType;
110
-
111
- return UndefinedSectionType;
112
- }
113
-
114
- /** Children blocks classifier */
115
- template <>
116
- FORCEINLINE SectionType ClassifyChildrenListBlock<Action>(const BlockIterator& begin,
117
- const BlockIterator& end) {
118
-
119
- SectionType type = ClassifyInternaListBlock<Action>(begin, end);
120
- if (type != UndefinedSectionType)
121
- return type;
122
-
123
- type = ClassifyChildrenListBlock<HeaderCollection>(begin, end);
124
- if (type != UndefinedSectionType)
125
- return type;
126
-
127
- type = ClassifyChildrenListBlock<ParameterCollection>(begin, end);
128
- if (type != UndefinedSectionType)
129
- return type;
65
+ static MarkdownNodeIterator processNestedSection(const MarkdownNodeIterator& node,
66
+ const MarkdownNodes& siblings,
67
+ SectionParserData& pd,
68
+ Report& report,
69
+ Action& out) {
130
70
 
131
- type = ClassifyChildrenListBlock<Payload>(begin, end);
132
- if (type != UndefinedSectionType)
133
- return type;
134
-
135
- return UndefinedSectionType;
136
- }
137
-
138
- //
139
- // Block Classifier, Action Context
140
- //
141
- template <>
142
- FORCEINLINE SectionType ClassifyBlock<Action>(const BlockIterator& begin,
143
- const BlockIterator& end,
144
- const SectionType& context) {
145
-
146
- if (HasActionSignature(*begin))
147
- return (context == UndefinedSectionType) ? ActionSectionType : UndefinedSectionType;
148
-
149
- if (HasResourceSignature(*begin) ||
150
- HasResourceGroupSignature(*begin))
151
- return UndefinedSectionType;
152
-
153
- SectionType listSection = ClassifyInternaListBlock<Action>(begin, end);
154
- if (listSection != UndefinedSectionType)
155
- return listSection;
156
-
157
- // Unrecognized list item at this level
158
- if (begin->type == ListItemBlockBeginType)
159
- return ForeignSectionType;
160
-
161
- return (context == ActionSectionType) ? ActionSectionType : UndefinedSectionType;
162
- }
163
-
164
- //
165
- // Action SectionType Parser
166
- //
167
- template<>
168
- struct SectionParser<Action> {
169
-
170
- static ParseSectionResult ParseSection(const BlueprintSection& section,
171
- const BlockIterator& cur,
172
- BlueprintParserCore& parser,
173
- Action& action) {
174
-
175
- ParseSectionResult result = std::make_pair(Result(), cur);
176
-
177
- switch (section.type) {
178
- case ActionSectionType:
179
- result = HandleActionDescriptionBlock(section, cur, parser, action);
180
- break;
71
+ SectionType sectionType = pd.sectionContext();
72
+ MarkdownNodeIterator cur = node;
73
+ Payload payload;
74
+ std::stringstream ss;
181
75
 
76
+ mdp::CharactersRangeSet sourceMap = mdp::BytesRangeSetToCharactersRangeSet(node->sourceMap, pd.sourceData);
77
+
78
+ switch (sectionType) {
182
79
  case ParametersSectionType:
183
- result = HandleParameters(section, cur, parser, action);
184
- break;
80
+ return ParametersParser::parse(node, siblings, pd, report, out.parameters);
185
81
 
186
- case HeadersSectionType:
187
- result = HandleDeprecatedHeaders(section, cur, parser, action);
188
- break;
189
-
190
82
  case RequestSectionType:
191
- case ResponseSectionType:
192
- result = HandlePayload(section, cur, parser, action);
193
- break;
194
-
195
- case ForeignSectionType:
196
- result = HandleForeignSection<Action>(section, cur, parser.sourceData);
197
- break;
198
-
199
- case UndefinedSectionType:
200
- result.second = CloseList(cur, section.bounds.second);
83
+ case RequestBodySectionType:
84
+ cur = PayloadParser::parse(node, siblings, pd, report, payload);
85
+
86
+ if (out.examples.empty() || !out.examples.back().responses.empty()) {
87
+ TransactionExample transaction;
88
+ out.examples.push_back(transaction);
89
+ }
90
+
91
+ checkPayload(sectionType, sourceMap, payload, out, report);
92
+
93
+ out.examples.back().requests.push_back(payload);
201
94
  break;
202
-
203
- case ModelSectionType:
204
- case ObjectSectionType:
205
- {
206
- // ERR: Unexpected model definition
207
- SourceCharactersBlock sourceBlock = CharacterMapForBlock(cur,
208
- section.bounds.second,
209
- section.bounds,
210
- parser.sourceData);
211
- result.first.error = Error("unexpected model definiton, a model can be only defined in the resource section",
212
- SymbolError,
213
- sourceBlock);
95
+
96
+ case ResponseSectionType:
97
+ case ResponseBodySectionType:
98
+ cur = PayloadParser::parse(node, siblings, pd, report, payload);
99
+
100
+ if (out.examples.empty()) {
101
+ TransactionExample transaction;
102
+ out.examples.push_back(transaction);
214
103
  }
104
+
105
+ checkPayload(sectionType, sourceMap, payload, out, report);
106
+
107
+ out.examples.back().responses.push_back(payload);
215
108
  break;
216
-
109
+
110
+ case HeadersSectionType:
111
+ return SectionProcessor<Action>::handleDeprecatedHeaders(node, siblings, pd, report, out.headers);
112
+
217
113
  default:
218
- result.first.error = UnexpectedBlockError(section, cur, parser.sourceData);
219
114
  break;
220
115
  }
116
+
117
+ return cur;
118
+ }
119
+
120
+ static bool isUnexpectedNode(const MarkdownNodeIterator& node,
121
+ SectionType sectionType) {
221
122
 
222
- return result;
123
+ if ( SectionProcessor<Asset>::sectionType(node) != UndefinedSectionType) {
124
+ return true;
125
+ }
126
+
127
+ return SectionProcessorBase<Action>::isUnexpectedNode(node, sectionType);
223
128
  }
224
129
 
225
- static void Finalize(const SectionBounds& bounds,
226
- BlueprintParserCore& parser,
227
- Action& action,
228
- Result& result)
229
- {
230
- // Consolidate deprecated headers into subsequent payloads
231
- if (!action.headers.empty()) {
232
- InjectDeprecatedHeaders(action.headers, action.examples);
233
- action.headers.clear();
130
+ static MarkdownNodeIterator processUnexpectedNode(const MarkdownNodeIterator& node,
131
+ const MarkdownNodes& siblings,
132
+ SectionParserData& pd,
133
+ SectionType& sectionType,
134
+ Report& report,
135
+ Action& out) {
136
+
137
+ if ((node->type == mdp::ParagraphMarkdownNodeType ||
138
+ node->type == mdp::CodeMarkdownNodeType) &&
139
+ (sectionType == ResponseBodySectionType ||
140
+ sectionType == ResponseSectionType) &&
141
+ !out.examples.empty() &&
142
+ !out.examples.back().responses.empty()) {
143
+
144
+ CodeBlockUtility::addDanglingAsset(node, pd, sectionType, report, out.examples.back().responses.back().body);
145
+
146
+ return ++MarkdownNodeIterator(node);
234
147
  }
235
148
 
236
- // Check whether transaction example request is followed by a response
237
- if (action.examples.size() > 1 &&
238
- !action.examples.back().requests.empty() &&
239
- action.examples.back().responses.empty()) {
240
- // WARN: No response for request
149
+ if ((node->type == mdp::ParagraphMarkdownNodeType ||
150
+ node->type == mdp::CodeMarkdownNodeType) &&
151
+ (sectionType == RequestBodySectionType ||
152
+ sectionType == RequestSectionType) &&
153
+ !out.examples.empty() &&
154
+ !out.examples.back().requests.empty()) {
241
155
 
242
- std::stringstream ss;
243
- ss << "action is missing a response for ";
244
- if (action.examples.back().requests.back().name.empty())
245
- ss << "a request";
246
- else
247
- ss << "the '" << action.examples.back().requests.back().name << "' request";
156
+ CodeBlockUtility::addDanglingAsset(node, pd, sectionType, report, out.examples.back().requests.back().body);
248
157
 
249
- SourceCharactersBlock sourceBlock = CharacterMapForBlock(bounds.first, bounds.first, bounds, parser.sourceData);
250
- result.warnings.push_back(Warning(ss.str(),
251
- EmptyDefinitionWarning,
252
- sourceBlock));
158
+ return ++MarkdownNodeIterator(node);
253
159
  }
254
- }
255
-
256
- static ParseSectionResult HandleActionDescriptionBlock(const BlueprintSection& section,
257
- const BlockIterator& cur,
258
- BlueprintParserCore& parser,
259
- Action& action) {
260
160
 
261
- ParseSectionResult result = std::make_pair(Result(), cur);
262
- BlockIterator sectionCur(cur);
161
+ SectionType assetType = SectionProcessor<Asset>::sectionType(node);
263
162
 
264
- if (cur->type == HeaderBlockType &&
265
- cur == section.bounds.first) {
163
+ if (assetType != UndefinedSectionType) {
164
+
165
+ // WARN: Ignoring section
166
+ std::stringstream ss;
167
+ mdp::CharactersRangeSet sourceMap = mdp::BytesRangeSetToCharactersRangeSet(node->sourceMap, pd.sourceData);
266
168
 
267
- GetActionSignature(*cur, action.name, action.method);
268
- result.second = ++sectionCur;
269
- return result;
169
+ ss << "Ignoring " << SectionName(assetType) << " list item, ";
170
+ ss << SectionName(assetType) << " list item is expected to be indented by 4 spaces or 1 tab";
171
+
172
+ report.warnings.push_back(Warning(ss.str(),
173
+ IgnoringWarning,
174
+ sourceMap));
175
+
176
+ return ++MarkdownNodeIterator(node);
270
177
  }
271
178
 
272
- result = ParseDescriptionBlock<Action>(section,
273
- sectionCur,
274
- parser.sourceData,
275
- action);
276
- return result;
179
+ return SectionProcessorBase<Action>::processUnexpectedNode(node, siblings, pd, sectionType, report, out);
277
180
  }
278
-
279
- /** Parse Parameters section */
280
- static ParseSectionResult HandleParameters(const BlueprintSection& section,
281
- const BlockIterator& cur,
282
- BlueprintParserCore& parser,
283
- Action& action) {
284
- ParameterCollection parameters;
285
- ParseSectionResult result = ParametersParser::Parse(cur,
286
- section.bounds.second,
287
- section,
288
- parser,
289
- parameters);
290
- if (result.first.error.code != Error::OK)
291
- return result;
292
-
293
- if (parameters.empty()) {
294
- BlockIterator nameBlock = ListItemNameBlock(cur, section.bounds.second);
295
- SourceCharactersBlock sourceBlock = CharacterMapForBlock(nameBlock, cur, section.bounds, parser.sourceData);
296
- result.first.warnings.push_back(Warning(snowcrashconst::NoParametersMessage,
297
- FormattingWarning,
298
- sourceBlock));
299
- }
300
- else {
301
- action.parameters.insert(action.parameters.end(), parameters.begin(), parameters.end());
181
+
182
+ static SectionType sectionType(const MarkdownNodeIterator& node) {
183
+
184
+ if (node->type == mdp::HeaderMarkdownNodeType
185
+ && !node->text.empty()) {
186
+
187
+ mdp::ByteBuffer subject = node->text;
188
+ TrimString(subject);
189
+
190
+ if (RegexMatch(subject, ActionHeaderRegex) ||
191
+ RegexMatch(subject, NamedActionHeaderRegex)) {
192
+
193
+ return ActionSectionType;
194
+ }
302
195
  }
303
-
304
- return result;
196
+
197
+ return UndefinedSectionType;
305
198
  }
306
-
307
- /**
308
- * \brief Parse action payload
309
- * \param section Actual section being parsed.
310
- * \param cur Cursor within the section boundaries.
311
- * \param parser A parser's instance.
312
- * \param action An output buffer to store parsed payload into.
313
- * \return A block parser section result.
314
- */
315
- static ParseSectionResult HandlePayload(const BlueprintSection& section,
316
- const BlockIterator& cur,
317
- BlueprintParserCore& parser,
318
- Action& action)
319
- {
320
- Payload payload;
321
- ParseSectionResult result = PayloadParser::Parse(cur,
322
- section.bounds.second,
323
- section,
324
- parser,
325
- payload);
326
- if (result.first.error.code != Error::OK)
327
- return result;
328
-
329
- // Create transaction example if needed
330
- if (action.examples.empty()) {
331
- action.examples.push_back(TransactionExample());
199
+
200
+ static SectionType nestedSectionType(const MarkdownNodeIterator& node) {
201
+
202
+ SectionType nestedType = UndefinedSectionType;
203
+
204
+ // Check if parameters section
205
+ nestedType = SectionProcessor<Parameters>::sectionType(node);
206
+
207
+ if (nestedType != UndefinedSectionType) {
208
+ return nestedType;
332
209
  }
333
- else if (section.type == RequestSectionType) {
334
- // Automatic request response pairing:
335
- // If a request follows a response create a new transaction example
336
- if (!action.examples.back().responses.empty()) {
337
- action.examples.push_back(TransactionExample());
338
- }
210
+
211
+ // Check if headers section
212
+ nestedType = SectionProcessor<Headers>::sectionType(node);
213
+
214
+ if (nestedType == HeadersSectionType) {
215
+ return nestedType;
339
216
  }
340
-
341
- BlockIterator nameBlock = ListItemNameBlock(cur, section.bounds.second);
342
-
343
- // Check for duplicate
344
- if (IsPayloadDuplicate(section.type, payload, action.examples.back())) {
345
- // WARN: duplicate payload
346
- std::stringstream ss;
347
- ss << SectionName(section.type) << " payload `" << payload.name << "`";
348
- ss << " already defined for `" << action.method << "` method";
349
217
 
350
- SourceCharactersBlock sourceBlock = CharacterMapForBlock(nameBlock, cur, section.bounds, parser.sourceData);
351
- result.first.warnings.push_back(Warning(ss.str(),
352
- DuplicateWarning,
353
- sourceBlock));
218
+ // Check if payload section
219
+ nestedType = SectionProcessor<Payload>::sectionType(node);
220
+
221
+ if (nestedType != UndefinedSectionType) {
222
+ return nestedType;
354
223
  }
355
224
 
356
- // Check payload integrity
357
- CheckPayload(section.type, payload, action.method, nameBlock->sourceMap, parser.sourceData, result.first);
358
-
359
- // Inject parsed payload into the action
360
- if (section.type == RequestSectionType) {
361
- action.examples.back().requests.push_back(payload);
225
+ return UndefinedSectionType;
226
+ }
227
+
228
+ static SectionTypes nestedSectionTypes() {
229
+ SectionTypes nested, types;
230
+
231
+ // Payload & descendants
232
+ nested.push_back(ResponseBodySectionType);
233
+ nested.push_back(ResponseSectionType);
234
+ nested.push_back(RequestBodySectionType);
235
+ nested.push_back(RequestSectionType);
236
+
237
+ types = SectionProcessor<Payload>::nestedSectionTypes();
238
+ nested.insert(nested.end(), types.begin(), types.end());
239
+
240
+ return nested;
241
+ }
242
+
243
+ static void finalize(const MarkdownNodeIterator& node,
244
+ SectionParserData& pd,
245
+ Report& report,
246
+ Action& out) {
247
+
248
+ if (!out.headers.empty()) {
249
+
250
+ SectionProcessor<Headers>::injectDeprecatedHeaders(out.headers, out.examples);
251
+ out.headers.clear();
362
252
  }
363
- else if (section.type == ResponseSectionType) {
364
- action.examples.back().responses.push_back(payload);
253
+
254
+ if (out.examples.empty()) {
255
+
256
+ // WARN: No response for action
257
+ mdp::CharactersRangeSet sourceMap = mdp::BytesRangeSetToCharactersRangeSet(node->sourceMap, pd.sourceData);
258
+ report.warnings.push_back(Warning("action is missing a response",
259
+ EmptyDefinitionWarning,
260
+ sourceMap));
261
+ } else if (!out.examples.empty() &&
262
+ !out.examples.back().requests.empty() &&
263
+ out.examples.back().responses.empty()) {
264
+
265
+ // WARN: No response for request
266
+ std::stringstream ss;
267
+ ss << "action is missing a response for ";
268
+
269
+ if (out.examples.back().requests.back().name.empty()) {
270
+ ss << "a request";
271
+ } else {
272
+ ss << "the '" << out.examples.back().requests.back().name << "' request";
273
+ }
274
+
275
+ mdp::CharactersRangeSet sourceMap = mdp::BytesRangeSetToCharactersRangeSet(node->sourceMap, pd.sourceData);
276
+ report.warnings.push_back(Warning(ss.str(),
277
+ EmptyDefinitionWarning,
278
+ sourceMap));
365
279
  }
366
-
367
- // Check header duplicates
368
- CheckHeaderDuplicates(action, payload, nameBlock->sourceMap, parser.sourceData, result.first);
369
-
370
- return result;
371
280
  }
372
-
373
-
281
+
374
282
  /**
375
283
  * \brief Check & report payload validity.
376
- * \param section A section of the payload.
284
+ * \param sectionType A section of the payload.
377
285
  * \param sourceMap Payload signature source map.
378
286
  * \param payload The payload to be checked.
287
+ * \param action The Action to which payload belongs to.
288
+ * \param report Parser report.
379
289
  */
380
- static void CheckPayload(const SectionType& section,
290
+ static void checkPayload(SectionType sectionType,
291
+ const mdp::CharactersRangeSet sourceMap,
381
292
  const Payload& payload,
382
- const HTTPMethod method,
383
- const SourceDataBlock& sourceMap,
384
- const SourceData& sourceData,
385
- Result& result) {
386
-
387
- bool warnEmptyBody = false;
388
-
389
- std::string contentLength;
390
- std::string transferEncoding;
293
+ const Action& action,
294
+ Report& report) {
391
295
 
392
- for (Collection<Header>::const_iterator it = payload.headers.begin();
393
- it != payload.headers.end();
394
- ++it) {
296
+ if (isPayloadDuplicate(sectionType, payload, action.examples.back())) {
395
297
 
396
- if (it->first == HTTPHeaderName::ContentLength) {
397
- contentLength = it->second;
398
- }
298
+ // WARN: Duplicate payload
299
+ std::stringstream ss;
300
+ ss << SectionName(sectionType) << " payload `" << payload.name << "`";
301
+ ss << " already defined for `" << action.method << "` method";
399
302
 
400
- if (it->first == HTTPHeaderName::TransferEncoding) {
401
- transferEncoding = it->second;
402
- }
303
+ report.warnings.push_back(Warning(ss.str(),
304
+ DuplicateWarning,
305
+ sourceMap));
403
306
  }
404
-
405
- if (section == RequestSectionType) {
406
-
407
- if (payload.body.empty()) {
408
-
409
- // Warn when content-length or transfer-encoding is specified or both headers and body are empty
410
- if (payload.headers.empty()) {
411
- warnEmptyBody = true;
412
- }
413
- else {
414
- warnEmptyBody = !contentLength.empty() ||
415
- !transferEncoding.empty();
416
- }
417
307
 
418
- if (warnEmptyBody) {
419
- // WARN: empty body
420
- std::stringstream ss;
421
- ss << "empty " << SectionName(section) << " " << SectionName(BodySectionType);
308
+ if (sectionType == ResponseSectionType || sectionType == ResponseBodySectionType) {
422
309
 
423
- if (!contentLength.empty()) {
424
- ss << ", expected " << SectionName(BodySectionType) << " for '" << contentLength << "' Content-Length";
425
- }
426
- else if (!transferEncoding.empty()) {
427
- ss << ", expected " << SectionName(BodySectionType) << " for '" << transferEncoding << "' Transfer-Encoding";
428
- }
429
-
430
- result.warnings.push_back(Warning(ss.str(),
431
- EmptyDefinitionWarning,
432
- MapSourceDataBlock(sourceMap, sourceData)));
433
- }
434
-
435
- }
436
- }
437
- else if (section == ResponseSectionType) {
438
- // Check status code
439
- HTTPStatusCode code = 0;
310
+ HTTPStatusCode code;
440
311
 
441
312
  if (!payload.name.empty()) {
442
313
  std::stringstream(payload.name) >> code;
443
314
  }
444
315
 
445
- StatusCodeTraits statusCodeTraits = GetStatusCodeTrait(code);
446
- HTTPMethodTraits methodTraits = GetMethodTrait(method);
447
-
448
- if ((!statusCodeTraits.allowBody || !methodTraits.allowBody) && !payload.body.empty()) {
449
- // WARN: not empty body
316
+ HTTPMethodTraits methodTraits = GetMethodTrait(action.method);
450
317
 
451
- if (!statusCodeTraits.allowBody) {
452
- std::stringstream ss;
453
- ss << "the " << code << " response MUST NOT include a " << SectionName(BodySectionType);
454
- result.warnings.push_back(Warning(ss.str(),
455
- EmptyDefinitionWarning,
456
- MapSourceDataBlock(sourceMap, sourceData)));
457
- }
318
+ if (!methodTraits.allowBody && !payload.body.empty()) {
458
319
 
459
320
  // WARN: Edge case for 2xx CONNECT
460
- if (method == HTTPMethodName::Connect && code/100 == 2) {
321
+ if (action.method == HTTPMethodName::Connect && code/100 == 2) {
322
+
461
323
  std::stringstream ss;
462
- ss << "the response for " << code << " " << method << " request MUST NOT include a " << SectionName(BodySectionType);
463
- result.warnings.push_back(Warning(ss.str(),
324
+ ss << "the response for " << code << " " << action.method << " request MUST NOT include a " << SectionName(BodySectionType);
325
+
326
+ report.warnings.push_back(Warning(ss.str(),
464
327
  EmptyDefinitionWarning,
465
- MapSourceDataBlock(sourceMap, sourceData)));
328
+ sourceMap));
329
+ } else if (action.method != HTTPMethodName::Connect && !methodTraits.allowBody) {
466
330
 
467
- }
468
- else if (method != HTTPMethodName::Connect && !methodTraits.allowBody) {
469
331
  std::stringstream ss;
470
- ss << "the response for " << method << " request MUST NOT include a " << SectionName(BodySectionType);
471
- result.warnings.push_back(Warning(ss.str(),
332
+ ss << "the response for " << action.method << " request MUST NOT include a " << SectionName(BodySectionType);
333
+
334
+ report.warnings.push_back(Warning(ss.str(),
472
335
  EmptyDefinitionWarning,
473
- MapSourceDataBlock(sourceMap, sourceData)));
336
+ sourceMap));
474
337
  }
475
338
 
476
339
  return;
@@ -482,22 +345,95 @@ namespace snowcrash {
482
345
  * Checks whether given section payload has duplicate within its transaction examples
483
346
  * \return True when a duplicate is found, false otherwise.
484
347
  */
485
- static bool IsPayloadDuplicate(const SectionType& section, const Payload& payload, TransactionExample& example) {
486
-
487
- if (section == RequestSectionType) {
348
+ static bool isPayloadDuplicate(SectionType& sectionType,
349
+ const Payload& payload,
350
+ const TransactionExample& example) {
351
+
352
+ if (sectionType == RequestSectionType) {
353
+
488
354
  Collection<Request>::const_iterator duplicate = FindRequest(example, payload);
489
355
  return duplicate != example.requests.end();
490
- }
491
- else if (section == ResponseSectionType) {
356
+ } else if (sectionType == ResponseSectionType) {
357
+
492
358
  Collection<Response>::const_iterator duplicate = FindResponse(example, payload);
493
359
  return duplicate != example.responses.end();
494
360
  }
495
361
 
496
362
  return false;
497
363
  }
364
+
365
+ /** Warn about deprecated headers */
366
+ static MarkdownNodeIterator handleDeprecatedHeaders(const MarkdownNodeIterator& node,
367
+ const MarkdownNodes& siblings,
368
+ SectionParserData& pd,
369
+ Report& report,
370
+ Headers& headers) {
371
+
372
+ MarkdownNodeIterator cur = HeadersParser::parse(node, siblings, pd, report, headers);
373
+
374
+ // WARN: Deprecated header sections
375
+ std::stringstream ss;
376
+ ss << "the 'headers' section at this level is deprecated and will be removed in a future, use respective payload header section(s) instead";
377
+
378
+ mdp::CharactersRangeSet sourceMap = mdp::BytesRangeSetToCharactersRangeSet(node->sourceMap, pd.sourceData);
379
+ report.warnings.push_back(Warning(ss.str(),
380
+ DeprecatedWarning,
381
+ sourceMap));
382
+
383
+ return cur;
384
+ }
385
+
386
+ /** \return %ActionType of a node */
387
+ static ActionType actionType(const MarkdownNodeIterator& node) {
388
+
389
+ if (node->type != mdp::HeaderMarkdownNodeType || node->text.empty())
390
+ return NotActionType;
391
+
392
+ mdp::ByteBuffer subject = node->text;
393
+ TrimString(subject);
394
+
395
+ if (RegexMatch(subject, NamedActionHeaderRegex)) {
396
+ return DependentActionType;
397
+ }
398
+
399
+ CaptureGroups captureGroups;
400
+ if (RegexCapture(subject, ActionHeaderRegex, captureGroups, 3)) {
401
+
402
+ if (captureGroups[2].empty()) {
403
+ return DependentActionType;
404
+ }
405
+ else {
406
+ return CompleteActionType;
407
+ }
408
+ }
409
+
410
+ return NotActionType;
411
+ }
412
+
413
+ /** \return HTTP request method and name of an action */
414
+ static void actionHTTPMethodAndName(const MarkdownNodeIterator& node,
415
+ mdp::ByteBuffer& method,
416
+ mdp::ByteBuffer& name) {
417
+
418
+ CaptureGroups captureGroups;
419
+ mdp::ByteBuffer subject, remaining;
420
+
421
+ subject = GetFirstLine(node->text, remaining);
422
+ TrimString(subject);
423
+
424
+ if (RegexCapture(subject, ActionHeaderRegex, captureGroups, 3)) {
425
+ method = captureGroups[1];
426
+ } else if (RegexCapture(subject, NamedActionHeaderRegex, captureGroups, 3)) {
427
+ name = captureGroups[1];
428
+ method = captureGroups[2];
429
+ }
430
+
431
+ return;
432
+ }
498
433
  };
499
-
500
- typedef BlockParser<Action, SectionParser<Action> > ActionParser;
434
+
435
+ /** Action Section Parser */
436
+ typedef SectionParser<Action, HeaderSectionAdapter> ActionParser;
501
437
  }
502
438
 
503
439
  #endif