d-mark 0.2.0 → 1.0.0a1

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: bee205ce9623266e9787eec60d991ddc1f3b99a3
4
- data.tar.gz: 490bbf23b2a0a0b8cb1767f6b7a542f38a749ba1
3
+ metadata.gz: a113f03eb0aba71874ec39fdb2eeeb53327da22a
4
+ data.tar.gz: 8a022441c7fb0ef0bb82b23d696e2d165f0e5193
5
5
  SHA512:
6
- metadata.gz: 13cabb5e530a7067fe5e665c883d42f1bf59208249e2fd2ef9fe49cf87cfa0dffa1974be4307769dbb862d51ba466403154e6bbbbf655a244a275d760b26bacd
7
- data.tar.gz: e65a20361865f63a70cf4de93fa27634dcf831ac4d966c64ccb146dabd03796e277b23fdb43dd7ebeef9fdde947f2c1d800e2afeb5710ebf79ec4d9231608bc9
6
+ metadata.gz: 9b67ee738116a651db12715abf33da46b4d9ab78425b30d801ca6c5398be45bbd2bcae3092b7e48566538ec98d7a6620063a94d2da4a3546342229b143f9e991
7
+ data.tar.gz: a61696ac50d227e5b90c652d3593d300a46a66bed352e852c26feb5951c88c639fed7e9af32e6c304cb520b7edfd0b37e5b8716fddbedea77acb151f8aac02e0
data/Gemfile CHANGED
@@ -2,6 +2,7 @@ source 'https://rubygems.org'
2
2
 
3
3
  gemspec
4
4
 
5
+ gem 'codecov', require: false
5
6
  gem 'guard'
6
7
  gem 'guard-rake'
7
8
  gem 'rspec'
@@ -1,15 +1,19 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- d-mark (0.1.0)
5
- treetop (~> 1.4)
4
+ d-mark (1.0.0a1)
6
5
 
7
6
  GEM
8
7
  remote: https://rubygems.org/
9
8
  specs:
10
9
  ast (2.2.0)
10
+ codecov (0.1.4)
11
+ json
12
+ simplecov
13
+ url
11
14
  coderay (1.1.0)
12
15
  diff-lcs (1.2.5)
16
+ docile (1.1.5)
13
17
  ffi (1.9.10)
14
18
  formatador (0.2.5)
15
19
  guard (2.13.0)
@@ -24,6 +28,7 @@ GEM
24
28
  guard-rake (1.0.0)
25
29
  guard
26
30
  rake
31
+ json (1.8.3)
27
32
  listen (3.0.6)
28
33
  rb-fsevent (>= 0.9.3)
29
34
  rb-inotify (>= 0.9.7)
@@ -35,7 +40,6 @@ GEM
35
40
  shellany (~> 0.0)
36
41
  parser (2.3.0.4)
37
42
  ast (~> 2.2)
38
- polyglot (0.3.5)
39
43
  powerpack (0.1.1)
40
44
  pry (0.10.3)
41
45
  coderay (~> 1.1.0)
@@ -67,17 +71,22 @@ GEM
67
71
  unicode-display_width (~> 0.3)
68
72
  ruby-progressbar (1.7.5)
69
73
  shellany (0.0.1)
74
+ simplecov (0.11.2)
75
+ docile (~> 1.1.0)
76
+ json (~> 1.8)
77
+ simplecov-html (~> 0.10.0)
78
+ simplecov-html (0.10.0)
70
79
  slop (3.6.0)
71
80
  thor (0.19.1)
72
- treetop (1.6.3)
73
- polyglot (~> 0.3)
74
81
  unicode-display_width (0.3.1)
82
+ url (0.3.2)
75
83
 
76
84
  PLATFORMS
77
85
  ruby
78
86
 
79
87
  DEPENDENCIES
80
88
  bundler (>= 1.11.2, < 2.0)
89
+ codecov
81
90
  d-mark!
82
91
  guard
83
92
  guard-rake
data/NEWS.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # D★Mark news
2
2
 
3
+ ## 1.0.0a1 (2016-02-20)
4
+
5
+ Fixes:
6
+
7
+ * Allowed document to begin with blank lines (#4)
8
+ * Ensured error is raised on incorrectly escaped attribute value (#5)
9
+
3
10
  ## 0.2 (2016-02-11)
4
11
 
5
12
  Fixes:
@@ -1,7 +1,10 @@
1
1
  = D★Mark
2
2
  Denis Defreyne <denis@stoneship.org>
3
3
 
4
- CAUTION: D★Mark is experimental — use at your own risk!
4
+ image:http://img.shields.io/gem/v/d-mark.svg[Gem version, link="http://rubygems.org/gems/d-mark"]
5
+ image:http://img.shields.io/travis/ddfreyne/d-mark.svg[Build status, link="https://travis-ci.org/ddfreyne/d-mark"]
6
+ image:http://img.shields.io/codeclimate/github/ddfreyne/d-mark.svg[Code Climate, link="https://codeclimate.com/github/ddfreyne/d-mark"]
7
+ image:http://img.shields.io/codecov/c/github/ddfreyne/d-mark.svg[Code Coverage, link="https://codecov.io/github/ddfreyne/d-mark"]
5
8
 
6
9
  _D★Mark_ is a language for marking up prose. It facilitates writing semantically meaningful text, without limiting itself to the semantics provided by HTML or Markdown.
7
10
 
@@ -205,7 +208,7 @@ class MyXMLLikeTranslator < DMark::Translator
205
208
  case node
206
209
  when String
207
210
  out << node
208
- when DMark::Parser::ElementNode
211
+ when DMark::ElementNode
209
212
  out << "<#{node.name}>"
210
213
  handle_children(node)
211
214
  out << "</#{node.name}>"
@@ -22,6 +22,5 @@ Gem::Specification.new do |s|
22
22
 
23
23
  s.required_ruby_version = '>= 2.1.0'
24
24
 
25
- s.add_runtime_dependency('treetop', '~> 1.4')
26
25
  s.add_development_dependency('bundler', '>= 1.11.2', '< 2.0')
27
26
  end
@@ -1,2 +1,3 @@
1
+ require_relative 'd-mark/element_node'
1
2
  require_relative 'd-mark/parser'
2
3
  require_relative 'd-mark/translator'
@@ -0,0 +1,36 @@
1
+ module DMark
2
+ class ElementNode
3
+ attr_reader :name
4
+ attr_reader :attributes
5
+ attr_reader :children
6
+
7
+ def initialize(name, attributes, children)
8
+ @name = name
9
+ @attributes = attributes
10
+ @children = children
11
+ end
12
+
13
+ def inspect
14
+ io = ''
15
+ io << 'Element(' << @name << ', '
16
+ if @attributes.any?
17
+ io << @attributes.inspect
18
+ io << ', '
19
+ end
20
+ io << @children.inspect
21
+ io << ')'
22
+ io
23
+ end
24
+
25
+ def ==(other)
26
+ case other
27
+ when ElementNode
28
+ @name == other.name &&
29
+ @children == other.children &&
30
+ @attributes == other.attributes
31
+ else
32
+ false
33
+ end
34
+ end
35
+ end
36
+ end
@@ -13,41 +13,6 @@ module DMark
13
13
  end
14
14
  end
15
15
 
16
- class ElementNode
17
- attr_reader :name
18
- attr_reader :attributes
19
- attr_reader :children
20
-
21
- def initialize(name, attributes, children)
22
- @name = name
23
- @attributes = attributes
24
- @children = children
25
- end
26
-
27
- def inspect
28
- io = ''
29
- io << 'Element(' << @name << ', '
30
- if @attributes.any?
31
- io << @attributes.inspect
32
- io << ', '
33
- end
34
- io << @children.inspect
35
- io << ')'
36
- io
37
- end
38
-
39
- def ==(other)
40
- case other
41
- when ElementNode
42
- @name == other.name &&
43
- @children == other.children &&
44
- @attributes == other.attributes
45
- else
46
- false
47
- end
48
- end
49
- end
50
-
51
16
  attr_reader :pos
52
17
 
53
18
  def initialize(input)
@@ -62,6 +27,17 @@ module DMark
62
27
  def parse
63
28
  res = []
64
29
 
30
+ loop do
31
+ break if eof?
32
+
33
+ blank_pos = try_read_blank_line
34
+ break unless blank_pos
35
+
36
+ @pos = blank_pos
37
+ @line_nr += 1
38
+ @col_nr = 0
39
+ end
40
+
65
41
  loop do
66
42
  break if eof?
67
43
  res << read_block_with_children
@@ -161,14 +137,14 @@ module DMark
161
137
 
162
138
  success =
163
139
  if try_read_identifier_head
164
- if try_read_identifier_tail
165
- case peek_char
166
- when '['
167
- true
168
- when '.'
169
- advance
170
- [' ', "\n", nil].include?(peek_char)
171
- end
140
+ read_identifier_tail
141
+
142
+ case peek_char
143
+ when '['
144
+ true
145
+ when '.'
146
+ advance
147
+ [' ', "\n", nil].include?(peek_char)
172
148
  end
173
149
  end
174
150
 
@@ -186,24 +162,6 @@ module DMark
186
162
  end
187
163
  end
188
164
 
189
- # FIXME: ugly and duplicated
190
- def try_read_identifier_tail
191
- res = ''
192
-
193
- loop do
194
- char = peek_char
195
- case char
196
- when 'a'..'z', '-', '0'..'9'
197
- advance
198
- res << char
199
- else
200
- break
201
- end
202
- end
203
-
204
- res.to_s
205
- end
206
-
207
165
  def detect_indentation
208
166
  indentation_chars = 0
209
167
  pos = @pos
@@ -221,26 +179,6 @@ module DMark
221
179
  indentation_chars / 2
222
180
  end
223
181
 
224
- def read_until_eol_or_eof
225
- res = ''
226
-
227
- loop do
228
- char = peek_char
229
- case char
230
- when "\n"
231
- advance
232
- break
233
- when nil
234
- break
235
- else
236
- advance
237
- res << char
238
- end
239
- end
240
-
241
- res.to_s
242
- end
243
-
244
182
  def read_indentation(indentation)
245
183
  indentation.times do
246
184
  read_char(' ')
@@ -363,20 +301,28 @@ module DMark
363
301
 
364
302
  if is_escaping
365
303
  case char
366
- when nil, "\n"
367
- break
368
- else
304
+ when '%', ']', ','
369
305
  advance
370
306
  res << char
371
307
  is_escaping = false
308
+ when nil
309
+ raise_parse_error('unexpected file end in attribute value')
310
+ when "\n"
311
+ raise_parse_error('unexpected line break in attribute value')
312
+ else
313
+ raise_parse_error(%(expected "%", "," or "]" after "%", but got #{char.inspect}))
372
314
  end
373
315
  else
374
316
  case char
375
- when nil, "\n", ']', ','
317
+ when ']', ','
376
318
  break
377
319
  when '%'
378
320
  advance
379
321
  is_escaping = true
322
+ when nil
323
+ raise_parse_error('unexpected file end in attribute value')
324
+ when "\n"
325
+ raise_parse_error('unexpected line break in attribute value')
380
326
  else
381
327
  advance
382
328
  res << char
@@ -1,3 +1,3 @@
1
1
  module DMark
2
- VERSION = '0.2.0'.freeze
2
+ VERSION = '1.0.0a1'.freeze
3
3
  end
@@ -5,7 +5,7 @@ class MyHTMLTranslator < DMark::Translator
5
5
  case node
6
6
  when String
7
7
  out << node
8
- when DMark::Parser::ElementNode
8
+ when DMark::ElementNode
9
9
  out << "<#{node.name}>"
10
10
  handle_children(node)
11
11
  out << "</#{node.name}>"
@@ -0,0 +1,54 @@
1
+ describe DMark::ElementNode do
2
+ let(:element_node) { described_class.new(name, attributes, children) }
3
+
4
+ let(:name) { 'para' }
5
+ let(:attributes) { {} }
6
+ let(:children) { ['Hello!'] }
7
+
8
+ describe '#inspect' do
9
+ subject { element_node.inspect }
10
+
11
+ context 'no attributes' do
12
+ let(:attributes) { {} }
13
+
14
+ it { is_expected.to eql('Element(para, ["Hello!"])') }
15
+ end
16
+
17
+ context 'attributes' do
18
+ let(:attributes) { { 'only' => 'web' } }
19
+
20
+ it { is_expected.to eql('Element(para, {"only"=>"web"}, ["Hello!"])') }
21
+ end
22
+ end
23
+
24
+ describe '#==' do
25
+ subject { element_node == other }
26
+
27
+ context 'other is not an element node' do
28
+ let(:other) { 'donkey' }
29
+ it { is_expected.to be false }
30
+ end
31
+
32
+ context 'other is an element node' do
33
+ context 'other does not differ' do
34
+ let(:other) { described_class.new(name, attributes, children) }
35
+ it { is_expected.to be true }
36
+ end
37
+
38
+ context 'other differs in name' do
39
+ let(:other) { described_class.new('giraffe', attributes, children) }
40
+ it { is_expected.to be false }
41
+ end
42
+
43
+ context 'other differs in attributes' do
44
+ let(:other) { described_class.new(name, { 'friend' => 'donkey' }, children) }
45
+ it { is_expected.to be false }
46
+ end
47
+
48
+ context 'other differs in children' do
49
+ let(:other) { described_class.new(name, attributes, []) }
50
+ it { is_expected.to be false }
51
+ end
52
+ end
53
+ end
54
+ end
@@ -3,7 +3,7 @@ def parse(s)
3
3
  end
4
4
 
5
5
  def element(name, attributes, children)
6
- DMark::Parser::ElementNode.new(name, attributes, children)
6
+ DMark::ElementNode.new(name, attributes, children)
7
7
  end
8
8
 
9
9
  describe 'DMark::Parser#parser' do
@@ -260,6 +260,37 @@ describe 'DMark::Parser#parser' do
260
260
  ]
261
261
  end
262
262
 
263
+ it 'parses document starting with blank lines' do
264
+ expect(parse(" \n \np. Hi!")).to eq [
265
+ element('p', {}, ['Hi!'])
266
+ ]
267
+ end
268
+
269
+ it 'does not parse percent escapes' do
270
+ expect { parse('p. %ref[url=https://github.com/pulls?q=is%3Aopen+user%3Ananoc]{eek}') }
271
+ .to raise_error(DMark::Parser::ParserError, 'parse error at line 1, col 43: expected "%", "," or "]" after "%", but got "3"')
272
+ end
273
+
274
+ it 'does not parse attribute values ending with an end-of-file' do
275
+ expect { parse('p. %ref[url=hello') }
276
+ .to raise_error(DMark::Parser::ParserError, 'parse error at line 1, col 18: unexpected file end in attribute value')
277
+ end
278
+
279
+ it 'does not parse attribute values ending with a line break' do
280
+ expect { parse("p. %ref[url=hello\n") }
281
+ .to raise_error(DMark::Parser::ParserError, 'parse error at line 1, col 18: unexpected line break in attribute value')
282
+ end
283
+
284
+ it 'does not parse escaped attribute values ending with an end-of-file' do
285
+ expect { parse('p. %ref[url=hello%') }
286
+ .to raise_error(DMark::Parser::ParserError, 'parse error at line 1, col 19: unexpected file end in attribute value')
287
+ end
288
+
289
+ it 'does not parse escaped attribute values ending with a line break' do
290
+ expect { parse("p. %ref[url=hello%\n") }
291
+ .to raise_error(DMark::Parser::ParserError, 'parse error at line 1, col 19: unexpected line break in attribute value')
292
+ end
293
+
263
294
  it 'does not parse' do
264
295
  expect { parse('p') }.to raise_error(DMark::Parser::ParserError)
265
296
  expect { parse('0') }.to raise_error(DMark::Parser::ParserError)
@@ -0,0 +1,45 @@
1
+ describe DMark::Translator do
2
+ let(:translator) { translator_class.new(nodes) }
3
+ let(:translator_class) { described_class }
4
+
5
+ let(:nodes) do
6
+ [
7
+ DMark::ElementNode.new(
8
+ 'para',
9
+ { 'only' => 'web', 'animal' => 'donkey' },
10
+ ['Hi!']
11
+ )
12
+ ]
13
+ end
14
+
15
+ describe '#run' do
16
+ subject { translator.run }
17
+
18
+ context 'translator base class' do
19
+ it 'raises NotImplementedError' do
20
+ expect { subject }.to raise_error(NotImplementedError)
21
+ end
22
+ end
23
+
24
+ context 'custom translator' do
25
+ let(:translator_class) do
26
+ Class.new(described_class) do
27
+ def handle(node)
28
+ case node
29
+ when String
30
+ out << node
31
+ when DMark::ElementNode
32
+ out << "<#{node.name}"
33
+ out << node.attributes.map { |k, v| ' ' + [k, v].join('=') }.join
34
+ out << '>'
35
+ handle_children(node)
36
+ out << "</#{node.name}>"
37
+ end
38
+ end
39
+ end
40
+ end
41
+
42
+ it { is_expected.to eql('<para only=web animal=donkey>Hi!</para>') }
43
+ end
44
+ end
45
+ end
@@ -1,2 +1,10 @@
1
1
  require 'rspec'
2
+
3
+ require 'simplecov'
4
+ SimpleCov.start
5
+ if ENV['CI'] == 'true'
6
+ require 'codecov'
7
+ SimpleCov.formatter = SimpleCov::Formatter::Codecov
8
+ end
9
+
2
10
  require 'd-mark'
metadata CHANGED
@@ -1,29 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: d-mark
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 1.0.0a1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Denis Defreyne
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-02-11 00:00:00.000000000 Z
11
+ date: 2016-02-20 00:00:00.000000000 Z
12
12
  dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: treetop
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - "~>"
18
- - !ruby/object:Gem::Version
19
- version: '1.4'
20
- type: :runtime
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - "~>"
25
- - !ruby/object:Gem::Version
26
- version: '1.4'
27
13
  - !ruby/object:Gem::Dependency
28
14
  name: bundler
29
15
  requirement: !ruby/object:Gem::Requirement
@@ -64,13 +50,16 @@ files:
64
50
  - d-mark.gemspec
65
51
  - lib/d-mark.rb
66
52
  - lib/d-mark/cli.rb
53
+ - lib/d-mark/element_node.rb
67
54
  - lib/d-mark/parser.rb
68
55
  - lib/d-mark/translator.rb
69
56
  - lib/d-mark/version.rb
70
57
  - samples/identifiers-and-patterns.dmark
71
58
  - samples/trivial.dmark
72
59
  - samples/trivial.rb
60
+ - spec/d-mark/element_node_spec.rb
73
61
  - spec/d-mark/parser_spec.rb
62
+ - spec/d-mark/translator_spec.rb
74
63
  - spec/spec_helper.rb
75
64
  homepage: http://rubygems.org/gems/d-mark
76
65
  licenses:
@@ -89,9 +78,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
89
78
  version: 2.1.0
90
79
  required_rubygems_version: !ruby/object:Gem::Requirement
91
80
  requirements:
92
- - - ">="
81
+ - - ">"
93
82
  - !ruby/object:Gem::Version
94
- version: '0'
83
+ version: 1.3.1
95
84
  requirements: []
96
85
  rubyforge_project:
97
86
  rubygems_version: 2.5.2