markdownplus 0.0.1.pre → 0.1.0

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