redsnow 0.0.8
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.
- checksums.yaml +7 -0
- data/.gitignore +34 -0
- data/.gitmodules +3 -0
- data/.travis.yml +20 -0
- data/CHANGELOG.md +4 -0
- data/Gemfile +4 -0
- data/LICENSE +21 -0
- data/README.md +62 -0
- data/Rakefile +36 -0
- data/Vagrantfile +20 -0
- data/ext/snowcrash/Makefile +64 -0
- data/ext/snowcrash/Vagrantfile +20 -0
- data/ext/snowcrash/bin/snowcrash +0 -0
- data/ext/snowcrash/common.gypi +163 -0
- data/ext/snowcrash/config.gypi +10 -0
- data/ext/snowcrash/config.mk +5 -0
- data/ext/snowcrash/configure +213 -0
- data/ext/snowcrash/provisioning.sh +15 -0
- data/ext/snowcrash/snowcrash.gyp +141 -0
- data/ext/snowcrash/src/ActionParser.h +503 -0
- data/ext/snowcrash/src/AssetParser.h +215 -0
- data/ext/snowcrash/src/BlockUtility.h +186 -0
- data/ext/snowcrash/src/Blueprint.h +283 -0
- data/ext/snowcrash/src/BlueprintParser.h +347 -0
- data/ext/snowcrash/src/BlueprintParserCore.h +190 -0
- data/ext/snowcrash/src/BlueprintSection.h +140 -0
- data/ext/snowcrash/src/BlueprintUtility.h +126 -0
- data/ext/snowcrash/src/CBlueprint.cc +600 -0
- data/ext/snowcrash/src/CBlueprint.h +354 -0
- data/ext/snowcrash/src/CSourceAnnotation.cc +140 -0
- data/ext/snowcrash/src/CSourceAnnotation.h +106 -0
- data/ext/snowcrash/src/CodeBlockUtility.h +189 -0
- data/ext/snowcrash/src/DescriptionSectionUtility.h +156 -0
- data/ext/snowcrash/src/HTTP.cc +46 -0
- data/ext/snowcrash/src/HTTP.h +105 -0
- data/ext/snowcrash/src/HeaderParser.h +289 -0
- data/ext/snowcrash/src/ListBlockUtility.h +273 -0
- data/ext/snowcrash/src/ListUtility.h +95 -0
- data/ext/snowcrash/src/MarkdownBlock.cc +176 -0
- data/ext/snowcrash/src/MarkdownBlock.h +93 -0
- data/ext/snowcrash/src/MarkdownParser.cc +266 -0
- data/ext/snowcrash/src/MarkdownParser.h +88 -0
- data/ext/snowcrash/src/ParameterDefinitonParser.h +570 -0
- data/ext/snowcrash/src/ParametersParser.h +252 -0
- data/ext/snowcrash/src/Parser.cc +71 -0
- data/ext/snowcrash/src/Parser.h +29 -0
- data/ext/snowcrash/src/ParserCore.cc +120 -0
- data/ext/snowcrash/src/ParserCore.h +82 -0
- data/ext/snowcrash/src/PayloadParser.h +672 -0
- data/ext/snowcrash/src/Platform.h +54 -0
- data/ext/snowcrash/src/RegexMatch.h +32 -0
- data/ext/snowcrash/src/ResourceGroupParser.h +195 -0
- data/ext/snowcrash/src/ResourceParser.h +584 -0
- data/ext/snowcrash/src/SectionUtility.h +142 -0
- data/ext/snowcrash/src/Serialize.cc +52 -0
- data/ext/snowcrash/src/Serialize.h +69 -0
- data/ext/snowcrash/src/SerializeJSON.cc +601 -0
- data/ext/snowcrash/src/SerializeJSON.h +21 -0
- data/ext/snowcrash/src/SerializeYAML.cc +336 -0
- data/ext/snowcrash/src/SerializeYAML.h +21 -0
- data/ext/snowcrash/src/SourceAnnotation.h +177 -0
- data/ext/snowcrash/src/StringUtility.h +109 -0
- data/ext/snowcrash/src/SymbolTable.h +83 -0
- data/ext/snowcrash/src/UriTemplateParser.cc +195 -0
- data/ext/snowcrash/src/UriTemplateParser.h +243 -0
- data/ext/snowcrash/src/Version.h +39 -0
- data/ext/snowcrash/src/csnowcrash.cc +23 -0
- data/ext/snowcrash/src/csnowcrash.h +38 -0
- data/ext/snowcrash/src/posix/RegexMatch.cc +99 -0
- data/ext/snowcrash/src/snowcrash.cc +18 -0
- data/ext/snowcrash/src/snowcrash.h +41 -0
- data/ext/snowcrash/src/snowcrash/snowcrash.cc +170 -0
- data/ext/snowcrash/src/win/RegexMatch.cc +78 -0
- data/ext/snowcrash/sundown/CONTRIBUTING.md +10 -0
- data/ext/snowcrash/sundown/Makefile +83 -0
- data/ext/snowcrash/sundown/Makefile.win +33 -0
- data/ext/snowcrash/sundown/examples/smartypants.c +72 -0
- data/ext/snowcrash/sundown/examples/sundown.c +80 -0
- data/ext/snowcrash/sundown/html/houdini.h +37 -0
- data/ext/snowcrash/sundown/html/houdini_href_e.c +108 -0
- data/ext/snowcrash/sundown/html/houdini_html_e.c +84 -0
- data/ext/snowcrash/sundown/html/html.c +647 -0
- data/ext/snowcrash/sundown/html/html.h +77 -0
- data/ext/snowcrash/sundown/html/html_smartypants.c +389 -0
- data/ext/snowcrash/sundown/html_block_names.txt +25 -0
- data/ext/snowcrash/sundown/src/autolink.c +297 -0
- data/ext/snowcrash/sundown/src/autolink.h +51 -0
- data/ext/snowcrash/sundown/src/buffer.c +225 -0
- data/ext/snowcrash/sundown/src/buffer.h +96 -0
- data/ext/snowcrash/sundown/src/html_blocks.h +206 -0
- data/ext/snowcrash/sundown/src/markdown.c +2701 -0
- data/ext/snowcrash/sundown/src/markdown.h +147 -0
- data/ext/snowcrash/sundown/src/src_map.c +200 -0
- data/ext/snowcrash/sundown/src/src_map.h +58 -0
- data/ext/snowcrash/sundown/src/stack.c +81 -0
- data/ext/snowcrash/sundown/src/stack.h +29 -0
- data/ext/snowcrash/sundown/sundown.def +20 -0
- data/ext/snowcrash/tools/gyp/AUTHORS +11 -0
- data/ext/snowcrash/tools/gyp/DEPS +24 -0
- data/ext/snowcrash/tools/gyp/OWNERS +1 -0
- data/ext/snowcrash/tools/gyp/PRESUBMIT.py +120 -0
- data/ext/snowcrash/tools/gyp/buildbot/buildbot_run.py +190 -0
- data/ext/snowcrash/tools/gyp/codereview.settings +10 -0
- data/ext/snowcrash/tools/gyp/data/win/large-pdb-shim.cc +12 -0
- data/ext/snowcrash/tools/gyp/gyp +8 -0
- data/ext/snowcrash/tools/gyp/gyp.bat +5 -0
- data/ext/snowcrash/tools/gyp/gyp_main.py +18 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/MSVSNew.py +340 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/MSVSProject.py +208 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/MSVSSettings.py +1063 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/MSVSToolFile.py +58 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/MSVSUserFile.py +147 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/MSVSUtil.py +267 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/MSVSVersion.py +409 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/__init__.py +537 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/__init__.pyc +0 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/common.py +521 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/common.pyc +0 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/easy_xml.py +157 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/flock_tool.py +49 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/generator/__init__.py +0 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/generator/__init__.pyc +0 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/generator/android.py +1069 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/generator/cmake.py +1143 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/generator/dump_dependency_json.py +81 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/generator/eclipse.py +335 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/generator/gypd.py +87 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/generator/gypsh.py +56 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/generator/make.py +2181 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/generator/make.pyc +0 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/generator/msvs.py +3335 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/generator/ninja.py +2156 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/generator/xcode.py +1224 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/generator/xcode.pyc +0 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/input.py +2809 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/input.pyc +0 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/mac_tool.py +510 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/msvs_emulation.py +972 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/ninja_syntax.py +160 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/ordered_dict.py +289 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/win_tool.py +292 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/xcode_emulation.py +1440 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/xcode_emulation.pyc +0 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/xcodeproj_file.py +2889 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/xcodeproj_file.pyc +0 -0
- data/ext/snowcrash/tools/gyp/pylib/gyp/xml_fix.py +69 -0
- data/ext/snowcrash/tools/gyp/pylintrc +307 -0
- data/ext/snowcrash/tools/gyp/samples/samples +81 -0
- data/ext/snowcrash/tools/gyp/samples/samples.bat +5 -0
- data/ext/snowcrash/tools/gyp/setup.py +19 -0
- data/ext/snowcrash/tools/gyp/tools/Xcode/Specifications/gyp.pbfilespec +27 -0
- data/ext/snowcrash/tools/gyp/tools/Xcode/Specifications/gyp.xclangspec +226 -0
- data/ext/snowcrash/tools/gyp/tools/emacs/gyp.el +252 -0
- data/ext/snowcrash/tools/gyp/tools/graphviz.py +100 -0
- data/ext/snowcrash/tools/gyp/tools/pretty_gyp.py +155 -0
- data/ext/snowcrash/tools/gyp/tools/pretty_sln.py +168 -0
- data/ext/snowcrash/tools/gyp/tools/pretty_vcproj.py +329 -0
- data/ext/snowcrash/tools/homebrew/snowcrash.rb +11 -0
- data/ext/snowcrash/vcbuild.bat +184 -0
- data/lib/redsnow.rb +31 -0
- data/lib/redsnow/binding.rb +132 -0
- data/lib/redsnow/blueprint.rb +365 -0
- data/lib/redsnow/object.rb +18 -0
- data/lib/redsnow/parseresult.rb +107 -0
- data/lib/redsnow/version.rb +4 -0
- data/provisioning.sh +20 -0
- data/redsnow.gemspec +35 -0
- data/test/_helper.rb +15 -0
- data/test/fixtures/sample-api-ast.json +97 -0
- data/test/fixtures/sample-api.apib +20 -0
- data/test/redsnow_binding_test.rb +35 -0
- data/test/redsnow_parseresult_test.rb +50 -0
- data/test/redsnow_test.rb +285 -0
- metadata +358 -0
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
//
|
|
2
|
+
// ListUtility.h
|
|
3
|
+
// snowcrash
|
|
4
|
+
//
|
|
5
|
+
// Deprecation Warning: The content of this file should be
|
|
6
|
+
// eventually replaced by the ListBlockUtility.h.
|
|
7
|
+
//
|
|
8
|
+
// Created by Zdenek Nemec on 5/12/13.
|
|
9
|
+
// Copyright (c) 2013 Apiary Inc. All rights reserved.
|
|
10
|
+
//
|
|
11
|
+
|
|
12
|
+
#ifndef SNOWCRASH_LISTUTILITY_H
|
|
13
|
+
#define SNOWCRASH_LISTUTILITY_H
|
|
14
|
+
|
|
15
|
+
#include <vector>
|
|
16
|
+
#include <string>
|
|
17
|
+
#include <sstream>
|
|
18
|
+
#include "MarkdownBlock.h"
|
|
19
|
+
#include "BlueprintParserCore.h"
|
|
20
|
+
#include "CodeBlockUtility.h"
|
|
21
|
+
|
|
22
|
+
namespace snowcrash {
|
|
23
|
+
|
|
24
|
+
// Pair of content parts
|
|
25
|
+
typedef std::vector<MarkdownBlock::Content> ContentParts;
|
|
26
|
+
|
|
27
|
+
// Extract first line from block content
|
|
28
|
+
// ContentParts[0] contains first line of block content
|
|
29
|
+
// ContentParts[1] contains the rest of block content
|
|
30
|
+
FORCEINLINE ContentParts ExtractFirstLine(const MarkdownBlock& block) {
|
|
31
|
+
|
|
32
|
+
ContentParts result;
|
|
33
|
+
if (block.content.empty())
|
|
34
|
+
return result;
|
|
35
|
+
|
|
36
|
+
std::string::size_type pos = block.content.find("\n");
|
|
37
|
+
if (pos == std::string::npos) {
|
|
38
|
+
result.push_back(block.content);
|
|
39
|
+
return result;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
result.push_back(block.content.substr(0, pos + 1));
|
|
43
|
+
result.push_back(block.content.substr(pos + 1, std::string::npos));
|
|
44
|
+
return result;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Return first list / list item content block block (paragraph)
|
|
48
|
+
// This is the first block inside the list / list item or the list item's closing block
|
|
49
|
+
// DEPRECATED - use ContentBlock() or SkipSignatureBlock() instead
|
|
50
|
+
FORCEINLINE BlockIterator FirstContentBlock(const BlockIterator& begin,
|
|
51
|
+
const BlockIterator& end) {
|
|
52
|
+
|
|
53
|
+
BlockIterator cur = begin;
|
|
54
|
+
if (cur->type == ListBlockBeginType)
|
|
55
|
+
if (++cur == end)
|
|
56
|
+
return end;
|
|
57
|
+
|
|
58
|
+
if (cur->type == ListItemBlockBeginType)
|
|
59
|
+
if (++cur == end)
|
|
60
|
+
return end;
|
|
61
|
+
|
|
62
|
+
return cur;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
// Returns true if list item (begin) contains nested list block false otherwise
|
|
67
|
+
// Look ahead.
|
|
68
|
+
FORCEINLINE bool HasNestedListBlock(const BlockIterator& begin,
|
|
69
|
+
const BlockIterator& end) {
|
|
70
|
+
|
|
71
|
+
BlockIterator sectionBegin = begin;
|
|
72
|
+
if (sectionBegin == end)
|
|
73
|
+
return false;
|
|
74
|
+
|
|
75
|
+
if (sectionBegin->type == ListBlockBeginType &&
|
|
76
|
+
++sectionBegin == end)
|
|
77
|
+
return false;
|
|
78
|
+
|
|
79
|
+
if (sectionBegin->type != ListItemBlockBeginType)
|
|
80
|
+
return false;
|
|
81
|
+
|
|
82
|
+
BlockIterator sectionEnd = SkipToClosingBlock(sectionBegin,
|
|
83
|
+
end,
|
|
84
|
+
ListItemBlockBeginType,
|
|
85
|
+
ListItemBlockEndType);
|
|
86
|
+
for (BlockIterator it = sectionBegin; it != sectionEnd; ++it) {
|
|
87
|
+
if (it->type == ListBlockBeginType)
|
|
88
|
+
return true;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
#endif
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
//
|
|
2
|
+
// MarkdownBlock.cc
|
|
3
|
+
// snowcrash
|
|
4
|
+
//
|
|
5
|
+
// Created by Zdenek Nemec on 4/15/13.
|
|
6
|
+
// Copyright (c) 2013 Apiary Inc. All rights reserved.
|
|
7
|
+
//
|
|
8
|
+
|
|
9
|
+
#include <sstream>
|
|
10
|
+
#include "MarkdownBlock.h"
|
|
11
|
+
|
|
12
|
+
#ifdef DEBUG
|
|
13
|
+
#include <iostream>
|
|
14
|
+
#endif
|
|
15
|
+
|
|
16
|
+
std::string snowcrash::BlockName(const MarkdownBlockType& blockType)
|
|
17
|
+
{
|
|
18
|
+
switch (blockType) {
|
|
19
|
+
case UndefinedBlockType:
|
|
20
|
+
return "undefined";
|
|
21
|
+
|
|
22
|
+
case CodeBlockType:
|
|
23
|
+
return "code";
|
|
24
|
+
|
|
25
|
+
case QuoteBlockBeginType:
|
|
26
|
+
case QuoteBlockEndType:
|
|
27
|
+
return "quote";
|
|
28
|
+
|
|
29
|
+
case HTMLBlockType:
|
|
30
|
+
return "html";
|
|
31
|
+
|
|
32
|
+
case HeaderBlockType:
|
|
33
|
+
return "header";
|
|
34
|
+
|
|
35
|
+
case ListBlockBeginType:
|
|
36
|
+
case ListBlockEndType:
|
|
37
|
+
return "list";
|
|
38
|
+
|
|
39
|
+
case ListItemBlockBeginType:
|
|
40
|
+
case ListItemBlockEndType:
|
|
41
|
+
return "list item";
|
|
42
|
+
|
|
43
|
+
case ParagraphBlockType:
|
|
44
|
+
return "paragraph";
|
|
45
|
+
|
|
46
|
+
case TableBlockType:
|
|
47
|
+
return "table";
|
|
48
|
+
|
|
49
|
+
case TableRowBlockType:
|
|
50
|
+
return "table row";
|
|
51
|
+
|
|
52
|
+
case TableCellBlockType:
|
|
53
|
+
return "table cell";
|
|
54
|
+
|
|
55
|
+
default:
|
|
56
|
+
return "markdown";
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
std::string snowcrash::MapSourceData(const SourceData& source, const SourceDataBlock& sourceMap)
|
|
61
|
+
{
|
|
62
|
+
if (source.empty())
|
|
63
|
+
return std::string();
|
|
64
|
+
|
|
65
|
+
size_t length = source.length();
|
|
66
|
+
std::stringstream ss;
|
|
67
|
+
for (SourceDataBlock::const_iterator it = sourceMap.begin(); it != sourceMap.end(); ++it) {
|
|
68
|
+
|
|
69
|
+
if (it->location + it->length > length) {
|
|
70
|
+
// Sundown adds an extra newline on the source input if needed.
|
|
71
|
+
if (it->location + it->length - length) {
|
|
72
|
+
ss << source.substr(it->location, length - it->location);
|
|
73
|
+
return ss.str();
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
// Wrong map
|
|
77
|
+
return std::string();
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
ss << source.substr(it->location, it->length);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return ss.str();
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
#ifdef DEBUG
|
|
88
|
+
|
|
89
|
+
#include "Serialize.h"
|
|
90
|
+
|
|
91
|
+
using namespace snowcrash;
|
|
92
|
+
|
|
93
|
+
static std::string BlockTypeToString(MarkdownBlockType type) {
|
|
94
|
+
switch (type) {
|
|
95
|
+
case UndefinedBlockType:
|
|
96
|
+
return "UndefinedBlockType";
|
|
97
|
+
|
|
98
|
+
case CodeBlockType:
|
|
99
|
+
return "CodeBlockType";
|
|
100
|
+
|
|
101
|
+
case QuoteBlockBeginType:
|
|
102
|
+
return "QuoteBlockBeginType";
|
|
103
|
+
|
|
104
|
+
case QuoteBlockEndType:
|
|
105
|
+
return "QuoteBlockEndType";
|
|
106
|
+
|
|
107
|
+
case HTMLBlockType:
|
|
108
|
+
return "HTMLBlockType";
|
|
109
|
+
|
|
110
|
+
case HeaderBlockType:
|
|
111
|
+
return "HeaderBlockType";
|
|
112
|
+
|
|
113
|
+
case HRuleBlockType:
|
|
114
|
+
return "HRuleBlockType";
|
|
115
|
+
|
|
116
|
+
case ListBlockBeginType:
|
|
117
|
+
return "ListBlockBeginType";
|
|
118
|
+
|
|
119
|
+
case ListBlockEndType:
|
|
120
|
+
return "ListBlockEndType";
|
|
121
|
+
|
|
122
|
+
case ListItemBlockBeginType:
|
|
123
|
+
return "ListItemBlockBeginType";
|
|
124
|
+
|
|
125
|
+
case ListItemBlockEndType:
|
|
126
|
+
return "ListItemBlockEndType";
|
|
127
|
+
|
|
128
|
+
case ParagraphBlockType:
|
|
129
|
+
return "ParagraphBlockType";
|
|
130
|
+
|
|
131
|
+
case TableBlockType:
|
|
132
|
+
return "TableBlockType";
|
|
133
|
+
|
|
134
|
+
case TableRowBlockType:
|
|
135
|
+
return "TableRowBlockType";
|
|
136
|
+
|
|
137
|
+
case TableCellBlockType:
|
|
138
|
+
return "TableCellBlockType";
|
|
139
|
+
|
|
140
|
+
default:
|
|
141
|
+
return "n/a";
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
void snowcrash::printMarkdown(const MarkdownBlock::Stack& markdown, unsigned int level)
|
|
146
|
+
{
|
|
147
|
+
std::string indent;
|
|
148
|
+
for (unsigned int i = 0; i < level; ++i) {
|
|
149
|
+
indent += " ";
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
for (MarkdownBlock::Stack::const_iterator block = markdown.begin(); block != markdown.end(); ++block) {
|
|
153
|
+
|
|
154
|
+
std::cout << indent << BlockTypeToString(block->type);
|
|
155
|
+
if (block->content.length()) {
|
|
156
|
+
std::cout << ", content: '" << EscapeNewlines(block->content) << "'";
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
if (!block->sourceMap.empty()) {
|
|
160
|
+
for (SourceDataBlock::const_iterator sourceMap = block->sourceMap.begin();
|
|
161
|
+
sourceMap != block->sourceMap.end();
|
|
162
|
+
++sourceMap) {
|
|
163
|
+
|
|
164
|
+
std::cout << ((sourceMap == block->sourceMap.begin()) ? ", :" : ";");
|
|
165
|
+
std::cout << sourceMap->location << ":" << sourceMap->length;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
std::cout << std::endl;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
if (level == 0)
|
|
173
|
+
std::cout << std::endl;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
#endif
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
//
|
|
2
|
+
// MarkdownBlock.h
|
|
3
|
+
// snowcrash
|
|
4
|
+
//
|
|
5
|
+
// Created by Zdenek Nemec on 4/15/13.
|
|
6
|
+
// Copyright (c) 2013 Apiary Inc. All rights reserved.
|
|
7
|
+
//
|
|
8
|
+
|
|
9
|
+
#ifndef SNOWCRASH_MARKDOWBLOCK_H
|
|
10
|
+
#define SNOWCRASH_MARKDOWBLOCK_H
|
|
11
|
+
|
|
12
|
+
#include <vector>
|
|
13
|
+
#include <string>
|
|
14
|
+
#include "ParserCore.h"
|
|
15
|
+
|
|
16
|
+
namespace snowcrash {
|
|
17
|
+
|
|
18
|
+
/** Type of a Markdown Block */
|
|
19
|
+
enum MarkdownBlockType {
|
|
20
|
+
UndefinedBlockType = 0,
|
|
21
|
+
CodeBlockType = 1,
|
|
22
|
+
QuoteBlockBeginType = 2,
|
|
23
|
+
QuoteBlockEndType = 3,
|
|
24
|
+
HTMLBlockType = 4,
|
|
25
|
+
HeaderBlockType = 5,
|
|
26
|
+
HRuleBlockType = 6,
|
|
27
|
+
ListBlockBeginType = 7,
|
|
28
|
+
ListBlockEndType = 8,
|
|
29
|
+
ListItemBlockBeginType = 9,
|
|
30
|
+
ListItemBlockEndType = 10,
|
|
31
|
+
ParagraphBlockType = 11,
|
|
32
|
+
TableBlockType = 12,
|
|
33
|
+
TableRowBlockType = 13,
|
|
34
|
+
TableCellBlockType = 14
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* \return Name of the markdown block.
|
|
39
|
+
*/
|
|
40
|
+
std::string BlockName(const MarkdownBlockType& blockType);
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Markdown Block Element
|
|
44
|
+
*/
|
|
45
|
+
struct MarkdownBlock {
|
|
46
|
+
|
|
47
|
+
typedef std::vector<MarkdownBlock> Stack;
|
|
48
|
+
typedef SourceData Content;
|
|
49
|
+
typedef int Data;
|
|
50
|
+
|
|
51
|
+
MarkdownBlock()
|
|
52
|
+
: type(UndefinedBlockType), data(0) {}
|
|
53
|
+
|
|
54
|
+
MarkdownBlock(MarkdownBlockType t, Content c = Content(), Data d = Data(), SourceDataBlock map = SourceDataBlock())
|
|
55
|
+
{ type = t; content = c; data = d; sourceMap = map; }
|
|
56
|
+
|
|
57
|
+
MarkdownBlock(const MarkdownBlock& b)
|
|
58
|
+
{ type = b.type; content = b.content; data = b.data; sourceMap = b.sourceMap; }
|
|
59
|
+
|
|
60
|
+
virtual ~MarkdownBlock() {}
|
|
61
|
+
|
|
62
|
+
MarkdownBlock& operator=(const MarkdownBlock& b)
|
|
63
|
+
{ type = b.type; content = b.content; data = b.data; sourceMap = b.sourceMap; return *this; }
|
|
64
|
+
|
|
65
|
+
// Type of the Markdown Block
|
|
66
|
+
MarkdownBlockType type;
|
|
67
|
+
|
|
68
|
+
// Text content excluding nested blocks
|
|
69
|
+
Content content;
|
|
70
|
+
|
|
71
|
+
// Arbitrary data from parser
|
|
72
|
+
Data data;
|
|
73
|
+
|
|
74
|
+
// Position of this block in source module
|
|
75
|
+
SourceDataBlock sourceMap;
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* \brief Maps block of source data bytes into source string.
|
|
80
|
+
* \param block A %SourceDataBlock to map into %SourceCharactersBlock
|
|
81
|
+
* \param data A mapped source data.
|
|
82
|
+
* \returns A string concatenated from the source string using the byte map.
|
|
83
|
+
*/
|
|
84
|
+
std::string MapSourceData(const SourceData& source, const SourceDataBlock& sourceMap);
|
|
85
|
+
|
|
86
|
+
#ifdef DEBUG
|
|
87
|
+
// Prints markdown block recursively to stdout
|
|
88
|
+
void printMarkdown(const MarkdownBlock::Stack& markdown, unsigned int level = 0);
|
|
89
|
+
#endif
|
|
90
|
+
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
#endif
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
//
|
|
2
|
+
// MarkdownParser.cc
|
|
3
|
+
// snowcrash
|
|
4
|
+
//
|
|
5
|
+
// Created by Zdenek Nemec on 4/15/13.
|
|
6
|
+
// Copyright (c) 2013 Apiary Inc. All rights reserved.
|
|
7
|
+
//
|
|
8
|
+
|
|
9
|
+
#include <cstring>
|
|
10
|
+
#include "MarkdownParser.h"
|
|
11
|
+
|
|
12
|
+
using namespace snowcrash;
|
|
13
|
+
|
|
14
|
+
// Returns text from sundown buffer
|
|
15
|
+
static std::string BufText(const struct buf *text)
|
|
16
|
+
{
|
|
17
|
+
if (!text || !text->data || !text->size)
|
|
18
|
+
return std::string();
|
|
19
|
+
|
|
20
|
+
return std::string(reinterpret_cast<char *>(text->data), text->size);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const size_t MarkdownParser::OutputUnitSize = 64;
|
|
24
|
+
const size_t MarkdownParser::MaxNesting = 16;
|
|
25
|
+
const int MarkdownParser::ParserExtensions = MKDEXT_FENCED_CODE | MKDEXT_NO_INTRA_EMPHASIS | MKDEXT_LAX_SPACING /*| MKDEXT_TABLES */;
|
|
26
|
+
|
|
27
|
+
void MarkdownParser::parse(const SourceData& source, Result& result, MarkdownBlock::Stack& markdown)
|
|
28
|
+
{
|
|
29
|
+
// Push default render stack
|
|
30
|
+
m_renderStack.clear();
|
|
31
|
+
|
|
32
|
+
// Build render callbacks & setup parser
|
|
33
|
+
RenderCallbacks callbacks = renderCallbacks();
|
|
34
|
+
sd_markdown *sundown = sd_markdown_new(ParserExtensions, MaxNesting, &callbacks, renderCallbackData());
|
|
35
|
+
|
|
36
|
+
buf *output = bufnew(OutputUnitSize);
|
|
37
|
+
|
|
38
|
+
// Parse & build AST
|
|
39
|
+
sd_markdown_render(output, reinterpret_cast<const uint8_t *>(source.c_str()), source.length(), sundown);
|
|
40
|
+
|
|
41
|
+
bufrelease(output);
|
|
42
|
+
sd_markdown_free(sundown);
|
|
43
|
+
|
|
44
|
+
// Compose final Markdown object
|
|
45
|
+
markdown = m_renderStack; // FIXME: C++11 move
|
|
46
|
+
|
|
47
|
+
#ifdef DEBUG
|
|
48
|
+
printMarkdown(markdown, 0);
|
|
49
|
+
#endif
|
|
50
|
+
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
MarkdownParser::RenderCallbacks MarkdownParser::renderCallbacks()
|
|
54
|
+
{
|
|
55
|
+
// Custom callbacks
|
|
56
|
+
sd_callbacks callbacks;
|
|
57
|
+
::memset(&callbacks, 0, sizeof(sd_callbacks));
|
|
58
|
+
|
|
59
|
+
callbacks.blockcode = &MarkdownParser::renderBlockCode;
|
|
60
|
+
callbacks.blockquote = &MarkdownParser::renderQuote;
|
|
61
|
+
callbacks.blockhtml = &MarkdownParser::renderHTML;
|
|
62
|
+
callbacks.header = &MarkdownParser::renderHeader;
|
|
63
|
+
callbacks.hrule = &MarkdownParser::renderHorizontalRule;
|
|
64
|
+
callbacks.list = &MarkdownParser::renderList;
|
|
65
|
+
callbacks.listitem = &MarkdownParser::renderListItem;
|
|
66
|
+
callbacks.paragraph = &MarkdownParser::renderParagraph;
|
|
67
|
+
|
|
68
|
+
// FUTURE: Table support
|
|
69
|
+
callbacks.table = NULL;
|
|
70
|
+
callbacks.table_row = NULL;
|
|
71
|
+
callbacks.table_cell = NULL;
|
|
72
|
+
|
|
73
|
+
// AST building extensions
|
|
74
|
+
callbacks.blockquote_begin = &MarkdownParser::beginQuote;
|
|
75
|
+
callbacks.list_begin = &MarkdownParser::beginList;
|
|
76
|
+
callbacks.listitem_begin = &MarkdownParser::beginListItem;
|
|
77
|
+
|
|
78
|
+
// Source maps
|
|
79
|
+
callbacks.block_did_parse = &MarkdownParser::blockDidParse;
|
|
80
|
+
|
|
81
|
+
return callbacks;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
MarkdownParser::RenderCallbackData MarkdownParser::renderCallbackData()
|
|
85
|
+
{
|
|
86
|
+
return this;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
void MarkdownParser::renderHeader(struct buf *ob, const struct buf *text, int level, void *opaque)
|
|
90
|
+
{
|
|
91
|
+
if (!opaque)
|
|
92
|
+
return;
|
|
93
|
+
|
|
94
|
+
MarkdownParser *p = static_cast<MarkdownParser *>(opaque);
|
|
95
|
+
p->renderHeader(BufText(text), level);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
void MarkdownParser::renderHeader(const std::string& text, int level)
|
|
99
|
+
{
|
|
100
|
+
m_renderStack.push_back(MarkdownBlock(HeaderBlockType, text, level));
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
void MarkdownParser::beginList(int flags, void *opaque)
|
|
104
|
+
{
|
|
105
|
+
if (!opaque)
|
|
106
|
+
return;
|
|
107
|
+
|
|
108
|
+
MarkdownParser *p = static_cast<MarkdownParser *>(opaque);
|
|
109
|
+
p->beginList(flags);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
void MarkdownParser::beginList(int flags)
|
|
113
|
+
{
|
|
114
|
+
m_renderStack.push_back(MarkdownBlock(ListBlockBeginType, SourceData(), flags));
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
void MarkdownParser::renderList(struct buf *ob, const struct buf *text, int flags, void *opaque)
|
|
118
|
+
{
|
|
119
|
+
if (!opaque)
|
|
120
|
+
return;
|
|
121
|
+
|
|
122
|
+
MarkdownParser *p = static_cast<MarkdownParser *>(opaque);
|
|
123
|
+
p->renderList(BufText(text), flags);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
void MarkdownParser::renderList(const std::string& text, int flags)
|
|
127
|
+
{
|
|
128
|
+
m_renderStack.push_back(MarkdownBlock(ListBlockEndType, text, flags));
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
void MarkdownParser::beginListItem(int flags, void *opaque)
|
|
132
|
+
{
|
|
133
|
+
if (!opaque)
|
|
134
|
+
return;
|
|
135
|
+
|
|
136
|
+
MarkdownParser *p = static_cast<MarkdownParser *>(opaque);
|
|
137
|
+
p->beginListItem(flags);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
void MarkdownParser::beginListItem(int flags)
|
|
141
|
+
{
|
|
142
|
+
m_renderStack.push_back(MarkdownBlock(ListItemBlockBeginType, SourceData(), flags));
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
void MarkdownParser::renderListItem(struct buf *ob, const struct buf *text, int flags, void *opaque)
|
|
146
|
+
{
|
|
147
|
+
if (!opaque)
|
|
148
|
+
return;
|
|
149
|
+
|
|
150
|
+
MarkdownParser *p = static_cast<MarkdownParser *>(opaque);
|
|
151
|
+
p->renderListItem(BufText(text), flags);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
void MarkdownParser::renderListItem(const std::string& text, int flags)
|
|
155
|
+
{
|
|
156
|
+
m_renderStack.push_back(MarkdownBlock(ListItemBlockEndType, text, flags));
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
void MarkdownParser::renderBlockCode(struct buf *ob, const struct buf *text, const struct buf *lang, void *opaque)
|
|
160
|
+
{
|
|
161
|
+
if (!opaque)
|
|
162
|
+
return;
|
|
163
|
+
|
|
164
|
+
MarkdownParser *p = static_cast<MarkdownParser *>(opaque);
|
|
165
|
+
p->renderBlockCode(BufText(text), BufText(lang));
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
void MarkdownParser::renderBlockCode(const std::string& text, const std::string& language)
|
|
169
|
+
{
|
|
170
|
+
m_renderStack.push_back(MarkdownBlock(CodeBlockType, text));
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
void MarkdownParser::renderParagraph(struct buf *ob, const struct buf *text, void *opaque)
|
|
174
|
+
{
|
|
175
|
+
if (!opaque)
|
|
176
|
+
return;
|
|
177
|
+
|
|
178
|
+
MarkdownParser *p = static_cast<MarkdownParser *>(opaque);
|
|
179
|
+
p->renderParagraph(BufText(text));
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
void MarkdownParser::renderParagraph(const std::string& text)
|
|
183
|
+
{
|
|
184
|
+
m_renderStack.push_back(MarkdownBlock(ParagraphBlockType, text));
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
void MarkdownParser::renderHorizontalRule(struct buf *ob, void *opaque)
|
|
188
|
+
{
|
|
189
|
+
if (!opaque)
|
|
190
|
+
return;
|
|
191
|
+
|
|
192
|
+
MarkdownParser *p = static_cast<MarkdownParser *>(opaque);
|
|
193
|
+
p->renderHorizontalRule();
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
void MarkdownParser::renderHorizontalRule()
|
|
197
|
+
{
|
|
198
|
+
m_renderStack.push_back(MarkdownBlock(HRuleBlockType));
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
void MarkdownParser::renderHTML(struct buf *ob, const struct buf *text, void *opaque)
|
|
202
|
+
{
|
|
203
|
+
if (!opaque)
|
|
204
|
+
return;
|
|
205
|
+
|
|
206
|
+
MarkdownParser *p = static_cast<MarkdownParser *>(opaque);
|
|
207
|
+
p->renderHTML(BufText(text));
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
void MarkdownParser::renderHTML(const std::string& text)
|
|
211
|
+
{
|
|
212
|
+
m_renderStack.push_back(MarkdownBlock(HTMLBlockType, text));
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
void MarkdownParser::beginQuote(void *opaque)
|
|
216
|
+
{
|
|
217
|
+
if (!opaque)
|
|
218
|
+
return;
|
|
219
|
+
|
|
220
|
+
MarkdownParser *p = static_cast<MarkdownParser *>(opaque);
|
|
221
|
+
p->beginQuote();
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
void MarkdownParser::beginQuote()
|
|
225
|
+
{
|
|
226
|
+
m_renderStack.push_back(MarkdownBlock(QuoteBlockBeginType, SourceData(), 0));
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
void MarkdownParser::renderQuote(struct buf *ob, const struct buf *text, void *opaque)
|
|
230
|
+
{
|
|
231
|
+
if (!opaque)
|
|
232
|
+
return;
|
|
233
|
+
|
|
234
|
+
MarkdownParser *p = static_cast<MarkdownParser *>(opaque);
|
|
235
|
+
p->renderQuote(BufText(text));
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
void MarkdownParser::renderQuote(const std::string& text)
|
|
239
|
+
{
|
|
240
|
+
m_renderStack.push_back(MarkdownBlock(QuoteBlockEndType, text, 0));
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
void MarkdownParser::blockDidParse(const src_map* map, const uint8_t *txt_data, size_t size, void *opaque)
|
|
244
|
+
{
|
|
245
|
+
if (!opaque || !map)
|
|
246
|
+
return;
|
|
247
|
+
|
|
248
|
+
SourceDataBlock sourceMap;
|
|
249
|
+
for (size_t i = 0; i < map->size; ++i) {
|
|
250
|
+
SourceDataRange sourceRange = {((range *)map->item[i])->loc, ((range *)map->item[i])->len};
|
|
251
|
+
sourceMap.push_back(sourceRange);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
MarkdownParser *p = static_cast<MarkdownParser *>(opaque);
|
|
255
|
+
p->blockDidParse(sourceMap);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
void MarkdownParser::blockDidParse(const SourceDataBlock& sourceMap)
|
|
259
|
+
{
|
|
260
|
+
if (m_renderStack.empty()) {
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
MarkdownBlock& lastBlock = m_renderStack.back();
|
|
265
|
+
AppendSourceDataBlock(lastBlock.sourceMap, sourceMap);
|
|
266
|
+
}
|