markdownplus 0.0.1.pre → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b5a4a83c2a959add9e237fd781aae968f8bdc567
4
- data.tar.gz: cbb9b6fd9e7fd12cd228db7037e00f8288e4a33b
3
+ metadata.gz: 59b5fb6c0a410a172db5e2aeba391eac6653eaff
4
+ data.tar.gz: 42154e62a00f5ec65919c512ad6398be9498fc64
5
5
  SHA512:
6
- metadata.gz: 1e4c4d3e0ff8cfe3dc2f5221b1cda3b4c8ebe1a933b9f28b7dc2978c701010984a9128df443849618c9fe6fdbe3bae4219b5afe7d122aa1ab92cd53d428ed10d
7
- data.tar.gz: 83852530992abfa1ee32ede91545a36f64f674397e534e3c86e64000aebb2276e14ea8ebe16a3ded01de003aea58ffe01cd5258273f8976021191f0e6867c93b
6
+ metadata.gz: c25d9c37887e2d41a4a3a12796fcb19badf60a4615c0e437c3ad2f5d1d0db6710a55b94f524c2fe76494d8c062180290c752309a374f9135c7bf8749724b575b
7
+ data.tar.gz: 97334f94d603ac07051958b58a074703a798485943f9a5b1dccc556517c02eb3301d3c7addf5405040e44c3b1be45353cd7b1af0dd4c36dd47fed65e03163a6b
data/LICENSE.txt CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2014 Christopher Petersen
1
+ Copyright (c) 2015 Christopher Petersen
2
2
 
3
3
  MIT License
4
4
 
data/README.md CHANGED
@@ -15,3 +15,15 @@ And then execute:
15
15
  Or install it yourself as:
16
16
 
17
17
  $ gem install markdownplus
18
+
19
+ # Syntax
20
+
21
+ ## Include external files
22
+
23
+ Use a fenced code block:
24
+
25
+ ```markdown
26
+ ```include|csv
27
+ https://gist.githubusercontent.com/cpetersen/b5a473ddf0b796cd9502/raw/e140bdc32ff2f6a600e357c2575220c0312a88ee/fake.csv
28
+ ```
29
+ ```
data/Rakefile CHANGED
@@ -1 +1,8 @@
1
+ #!/usr/bin/env rake
1
2
  require "bundler/gem_tasks"
3
+
4
+ require 'rspec/core/rake_task'
5
+ RSpec::Core::RakeTask.new(:spec)
6
+
7
+ task :test => :spec
8
+ task :default => :spec
@@ -0,0 +1,247 @@
1
+ require 'csv'
2
+ require 'json'
3
+ require 'open-uri'
4
+ require 'pygments'
5
+ require 'redcarpet'
6
+
7
+ module Markdownplus
8
+ class Parser
9
+ attr_reader :source
10
+ attr_accessor :current_block
11
+
12
+ def self.parse(value)
13
+ parser = Parser.new(value)
14
+ parser.parse
15
+ parser
16
+ end
17
+
18
+ def initialize(value=nil)
19
+ @source = value
20
+ end
21
+
22
+ def blocks
23
+ @blocks ||= []
24
+ end
25
+ def blocks=(value)
26
+ @blocks = value
27
+ end
28
+
29
+ def code_blocks
30
+ blocks.select { |b| b.class == CodeBlock }
31
+ end
32
+
33
+ def includable_blocks
34
+ code_blocks.select(&:includable?)
35
+ end
36
+
37
+ def executable_blocks
38
+ code_blocks.select(&:executable?)
39
+ end
40
+
41
+ def markdown
42
+ blocks.collect { |b| b.markdown }.join
43
+ end
44
+
45
+ def html
46
+ markdown_renderer.render(markdown)
47
+ end
48
+
49
+ def markdown_renderer
50
+ Redcarpet::Markdown.new(Bootstrap2Renderer, fenced_code_blocks: true)
51
+ end
52
+
53
+ def lines
54
+ @lines ||= source.split("\n")
55
+ end
56
+
57
+ def errors
58
+ blocks.collect { |b| b.errors }.flatten
59
+ end
60
+
61
+ def warnings
62
+ blocks.collect { |b| b.warnings }.flatten
63
+ end
64
+
65
+ def each_line(&block)
66
+ if block_given?
67
+ lines.each do |line|
68
+ block.call(line)
69
+ end
70
+ end
71
+ end
72
+
73
+ def parse
74
+ each_line do |line|
75
+ matcher = line.match(/\s*`{3,}\s*(\S*)\s*/)
76
+ if matcher
77
+ if self.current_block && self.current_block.class == CodeBlock
78
+ self.blocks << self.current_block
79
+ self.current_block = nil
80
+ else
81
+ self.blocks << self.current_block if self.current_block
82
+ self.current_block = CodeBlock.new(matcher[1])
83
+ end
84
+ else
85
+ self.current_block ||= TextBlock.new
86
+ self.current_block.append line
87
+ end
88
+ end
89
+ self.blocks << self.current_block if self.current_block
90
+ end
91
+
92
+ def include
93
+ includable_blocks.each do |block|
94
+ block.include
95
+ end
96
+ end
97
+ end
98
+
99
+ class Block
100
+ def source
101
+ @source ||= ""
102
+ end
103
+ def source=(value)
104
+ @source = value
105
+ end
106
+
107
+ def lines
108
+ self.source.split("\n")
109
+ end
110
+
111
+ def append(line)
112
+ self.source += "#{line}\n"
113
+ end
114
+
115
+ def errors
116
+ @errors ||= []
117
+ end
118
+
119
+ def warnings
120
+ @warnings ||= []
121
+ end
122
+ end
123
+
124
+ class TextBlock < Block
125
+ def markdown
126
+ self.source
127
+ end
128
+ end
129
+
130
+ class CodeBlock < Block
131
+ attr_reader :directives
132
+
133
+ def initialize(value=nil)
134
+ @directives = value.split("|").collect{|v| v.strip} if value
135
+ end
136
+
137
+ def markdown
138
+ s = source
139
+ if s.end_with?("\n")
140
+ result = "```#{directives.join("|")}\n#{source}```\n"
141
+ else
142
+ result = "```#{directives.join("|")}\n#{source}\n```\n"
143
+ end
144
+ end
145
+
146
+ def includable?
147
+ first_directive == "include"
148
+ end
149
+
150
+ def executable?
151
+ first_directive == "execute"
152
+ end
153
+
154
+ def include
155
+ if includable?
156
+ if lines.count == 0
157
+ self.warnings << "No url given"
158
+ else
159
+ self.warnings << "More than one line given" if lines.count > 1
160
+ begin
161
+ self.source = open(lines.first).read
162
+ rescue => e
163
+ self.errors << "Error opening [#{lines.first}] [#{e.message}]"
164
+ end
165
+ end
166
+ directives.shift
167
+ end
168
+ end
169
+
170
+ def first_directive
171
+ directives.first if directives
172
+ end
173
+
174
+ # def method
175
+ # matcher = directive.match(/(.*?)\((.*)\)/)
176
+ # if matcher
177
+ # method = matcher[1].strip
178
+ # params = matcher[2].split(",").collect { |p| p.strip }
179
+ # end
180
+ # end
181
+ end
182
+
183
+ # class Value
184
+ # def self.parse(string)
185
+ # items = string.split(",").collect do |item|
186
+ # matcher = item.match(/(.*?)\((.*)\)/)
187
+ # if matcher
188
+ # name = matcher[1].strip
189
+ # params = parse(matcher[2])
190
+ # Method.new(name: name, params: params)
191
+ # else
192
+ # Param.new(item.strip)
193
+ # end
194
+ # end
195
+ # end
196
+ # end
197
+
198
+ # class Param < Value
199
+ # def initialize(v)
200
+ # @value = value
201
+ # end
202
+
203
+ # def value
204
+ # @value
205
+ # end
206
+ # end
207
+
208
+ # class Method < Value
209
+ # attr_reader :name
210
+ # attr_reader :params
211
+
212
+ # def initialize(opts={})
213
+ # @name = opts[:name]
214
+ # @params = opts[:params]
215
+ # end
216
+ # end
217
+
218
+ class Bootstrap2Renderer < Redcarpet::Render::HTML
219
+ # alias_method :existing_block_code, :block_code
220
+ def block_code(code, language)
221
+ if language == "csv"
222
+ result = "<table class='table table-striped'>"
223
+ row_num = 0
224
+ CSV.parse(code) do |row|
225
+ if row_num == 0
226
+ result += "<thead><tr>#{row.collect { |c| "<th>#{c}</th>"}.join}</tr></thead>\n<tbody>\n"
227
+ else
228
+ result += "<tr>#{row.collect { |c| "<td>#{c}</td>"}.join}</tr>\n"
229
+ end
230
+ row_num += 1
231
+ end
232
+ result += "</tbody></table>"
233
+ elsif language == "formatted_json"
234
+ begin
235
+ obj = JSON.parse(code)
236
+ result = Pygments.highlight(JSON.pretty_generate(obj), lexer: "json")
237
+ rescue => e
238
+ result = Pygments.highlight(code, lexer: "json")
239
+ end
240
+ else
241
+ result = Pygments.highlight(code, lexer: language)
242
+ end
243
+ result
244
+ end
245
+ end
246
+ end
247
+
@@ -1,3 +1,3 @@
1
1
  module Markdownplus
2
- VERSION = "0.0.1.pre"
2
+ VERSION = "0.1.0"
3
3
  end
data/lib/markdownplus.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require "markdownplus/version"
2
+ require "markdownplus/parser"
2
3
 
3
4
  module Markdownplus
4
5
  # Your code goes here...
data/markdownplus.gemspec CHANGED
@@ -8,8 +8,8 @@ Gem::Specification.new do |spec|
8
8
  spec.version = Markdownplus::VERSION
9
9
  spec.authors = ["Christopher Petersen"]
10
10
  spec.email = ["chris@petersen.io"]
11
- spec.description = %q{A pre and post processor for markdown which adds programmable features and charting}
12
- spec.summary = %q{Markdown plus charts and scripting}
11
+ spec.description = %q{Pre processors that allows the inclusion of external files and post processors for csn and json data.}
12
+ spec.summary = %q{Pre and post processors for markdown}
13
13
  spec.homepage = ""
14
14
  spec.license = "MIT"
15
15
 
@@ -20,4 +20,8 @@ Gem::Specification.new do |spec|
20
20
 
21
21
  spec.add_development_dependency "bundler", "~> 1.3"
22
22
  spec.add_development_dependency "rake"
23
+ spec.add_development_dependency "rspec"
24
+
25
+ spec.add_dependency "redcarpet"
26
+ spec.add_dependency "pygments.rb"
23
27
  end
@@ -0,0 +1,33 @@
1
+ This is a markdown plus document illustrating include conditions
2
+
3
+ ```include
4
+ https://gist.githubusercontent.com/cpetersen/b5a473ddf0b796cd9502/raw/e140bdc32ff2f6a600e357c2575220c0312a88ee/fake.csv
5
+ ```
6
+
7
+ ```include|csv
8
+ https://gist.githubusercontent.com/cpetersen/b5a473ddf0b796cd9502/raw/e140bdc32ff2f6a600e357c2575220c0312a88ee/fake.csv
9
+ ```
10
+
11
+ ```include
12
+ ```
13
+
14
+ ```include|csv
15
+ https://gist.githubusercontent.com/cpetersen/b5a473ddf0b796cd9502/raw/e140bdc32ff2f6a600e357c2575220c0312a88ee/fake.csv
16
+ this
17
+ should
18
+ be
19
+ a
20
+ warning
21
+ ```
22
+
23
+ ```include|formatted_json
24
+ https://gist.githubusercontent.com/cpetersen/c6571117df132443ac81/raw/e5ac97e8e0665a0e4014ebc85ecef214763a7729/fake.json
25
+ ```
26
+
27
+ ```include|formatted_json
28
+ https://gist.githubusercontent.com/cpetersen/4ac0ab5fb4d1fda22322/raw/3856ed58d5cdfd07800067fc9fb8fcbcfc631d65/bad_json.json
29
+ ```
30
+
31
+ ```include
32
+ this should just be an error
33
+ ```
@@ -0,0 +1,21 @@
1
+ This is a test markdown document.
2
+
3
+ ```
4
+ This is a a code block
5
+ ```
6
+
7
+ ```ruby
8
+ This is a ruby code block
9
+ ```
10
+
11
+ ```include
12
+ This is a include block
13
+ ```
14
+
15
+ ```include|json
16
+ This is a include block with a filter
17
+ ```
18
+
19
+ ```execute|julia
20
+ This is an execute block with a language
21
+ ```
@@ -0,0 +1,181 @@
1
+ require 'markdownplus'
2
+ require 'spec_helper'
3
+
4
+ describe Markdownplus::Parser do
5
+ context "a simple file" do
6
+ let(:file) { File.read(File.join(File.dirname(__FILE__), "..", "spec", "fixtures", "simple.mdp")) }
7
+
8
+ it "should read the file" do
9
+ expect(file).not_to be_empty
10
+ end
11
+
12
+ context "the parser" do
13
+ let(:parser) { Markdownplus::Parser.parse(file) }
14
+
15
+ it "should have the correct number of lines" do
16
+ expect(parser.lines.count).to eq(21)
17
+ end
18
+
19
+ it "should have the correct number of blocks" do
20
+ expect(parser.blocks.count).to eq(10)
21
+ end
22
+
23
+ it "should have the correct number of code blocks" do
24
+ expect(parser.code_blocks.count).to eq(5)
25
+ end
26
+
27
+ it "should have the correct number of include blocks" do
28
+ expect(parser.includable_blocks.count).to eq(2)
29
+ end
30
+
31
+ it "should have the correct number of execute blocks" do
32
+ expect(parser.executable_blocks.count).to eq(1)
33
+ end
34
+
35
+ context "the markdown method" do
36
+ let(:markdown) { parser.markdown }
37
+
38
+ it "should match the contents of the original file" do
39
+ expect(markdown).to eq(file)
40
+ end
41
+ end
42
+
43
+ context "the first block" do
44
+ let(:block) { parser.blocks.first }
45
+ it "should be a text block" do
46
+ expect(block.class).to eq(Markdownplus::TextBlock)
47
+ end
48
+ end
49
+
50
+ context "the second block" do
51
+ let(:block) { parser.blocks[1] }
52
+ it "should be a code block" do
53
+ expect(block.class).to eq(Markdownplus::CodeBlock)
54
+ end
55
+
56
+ it "should have no directives" do
57
+ expect(block.directives).to eq([])
58
+ end
59
+ end
60
+
61
+ context "the fourth block" do
62
+ let(:block) { parser.blocks[3] }
63
+ it "should be a code block" do
64
+ expect(block.class).to eq(Markdownplus::CodeBlock)
65
+ end
66
+
67
+ it "should have the proper directives" do
68
+ expect(block.directives).to eq(["ruby"])
69
+ end
70
+ end
71
+
72
+ context "the sixth block" do
73
+ let(:block) { parser.blocks[5] }
74
+ it "should be a code block" do
75
+ expect(block.class).to eq(Markdownplus::CodeBlock)
76
+ end
77
+
78
+ it "should have the proper directives" do
79
+ expect(block.directives).to eq(["include"])
80
+ end
81
+
82
+ it "should be an include block" do
83
+ expect(block).to be_includable
84
+ end
85
+ end
86
+
87
+ context "the eighth block" do
88
+ let(:block) { parser.blocks[7] }
89
+ it "should be a code block" do
90
+ expect(block.class).to eq(Markdownplus::CodeBlock)
91
+ end
92
+
93
+ it "should have the proper directives" do
94
+ expect(block.directives).to eq(["include", "json"])
95
+ end
96
+
97
+ it "should be an include block" do
98
+ expect(block).to be_includable
99
+ end
100
+ end
101
+
102
+ context "the tenth block" do
103
+ let(:block) { parser.blocks[9] }
104
+ it "should be a code block" do
105
+ expect(block.class).to eq(Markdownplus::CodeBlock)
106
+ end
107
+
108
+ it "should have the proper directives" do
109
+ expect(block.directives).to eq(["execute", "julia"])
110
+ end
111
+
112
+ it "should be an execute block" do
113
+ expect(block).to be_executable
114
+ end
115
+ end
116
+ end
117
+ end
118
+
119
+ context "include directives" do
120
+ let(:parser) {
121
+ parser = Markdownplus::Parser.parse(File.read(File.join(File.dirname(__FILE__), "..", "spec", "fixtures", "include.mdp")))
122
+ parser.include
123
+ parser
124
+ }
125
+ it "should have the right number of blocks" do
126
+ expect(parser.blocks.count).to eq(14)
127
+ end
128
+
129
+ it "should have 2 warnings" do
130
+ expect(parser.warnings.count).to eq(2)
131
+ end
132
+
133
+ it "should have 1 error" do
134
+ expect(parser.errors.count).to eq(1)
135
+ end
136
+
137
+ context "the second block" do
138
+ let(:block) { parser.blocks[1] }
139
+
140
+ it "should include the proper number of lines" do
141
+ expect(block.lines.count).to eq(21)
142
+ end
143
+ end
144
+
145
+ context "the sixth block" do
146
+ let(:block) { parser.blocks[5] }
147
+
148
+ it "should have a warning" do
149
+ expect(block.warnings.count).to eq(1)
150
+ end
151
+
152
+ it "should have the missing url warning" do
153
+ expect(block.warnings.first).to eq("No url given")
154
+ end
155
+ end
156
+
157
+ context "the eighth block" do
158
+ let(:block) { parser.blocks[7] }
159
+
160
+ it "should have a warning" do
161
+ expect(block.warnings.count).to eq(1)
162
+ end
163
+
164
+ it "should have the multi line warning" do
165
+ expect(block.warnings.first).to eq("More than one line given")
166
+ end
167
+ end
168
+
169
+ context "the fourteenth block" do
170
+ let(:block) { parser.blocks[13] }
171
+
172
+ it "should have an error" do
173
+ expect(block.errors.count).to eq(1)
174
+ end
175
+
176
+ it "should have the multi line warning" do
177
+ expect(block.errors.first).to eq("Error opening [this should just be an error] [No such file or directory - this should just be an error]")
178
+ end
179
+ end
180
+ end
181
+ end
File without changes
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: markdownplus
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1.pre
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Christopher Petersen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-12-02 00:00:00.000000000 Z
11
+ date: 2015-03-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -38,8 +38,50 @@ dependencies:
38
38
  - - '>='
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
- description: A pre and post processor for markdown which adds programmable features
42
- and charting
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: redcarpet
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: pygments.rb
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: Pre processors that allows the inclusion of external files and post processors
84
+ for csn and json data.
43
85
  email:
44
86
  - chris@petersen.io
45
87
  executables: []
@@ -52,8 +94,13 @@ files:
52
94
  - README.md
53
95
  - Rakefile
54
96
  - lib/markdownplus.rb
97
+ - lib/markdownplus/parser.rb
55
98
  - lib/markdownplus/version.rb
56
99
  - markdownplus.gemspec
100
+ - spec/fixtures/include.mdp
101
+ - spec/fixtures/simple.mdp
102
+ - spec/parser_spec.rb
103
+ - spec/spec_helper.rb
57
104
  homepage: ''
58
105
  licenses:
59
106
  - MIT
@@ -69,14 +116,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
69
116
  version: '0'
70
117
  required_rubygems_version: !ruby/object:Gem::Requirement
71
118
  requirements:
72
- - - '>'
119
+ - - '>='
73
120
  - !ruby/object:Gem::Version
74
- version: 1.3.1
121
+ version: '0'
75
122
  requirements: []
76
123
  rubyforge_project:
77
124
  rubygems_version: 2.4.2
78
125
  signing_key:
79
126
  specification_version: 4
80
- summary: Markdown plus charts and scripting
81
- test_files: []
127
+ summary: Pre and post processors for markdown
128
+ test_files:
129
+ - spec/fixtures/include.mdp
130
+ - spec/fixtures/simple.mdp
131
+ - spec/parser_spec.rb
132
+ - spec/spec_helper.rb
82
133
  has_rdoc: