breakout_parser 0.0.23 → 0.0.31
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/ChangeLog +19 -0
- data/README +23 -11
- data/ext/breakout_parser/extconf.rb +10 -5
- data/ext/breakout_parser/parser.h +27 -0
- data/ext/breakout_parser/parser.l +22 -6
- data/ext/breakout_parser/parser.y +294 -126
- data/ext/breakout_parser/ruby_ext.c +51 -22
- data/ext/breakout_parser/ruby_ext.h +2 -0
- data/spec/links_only_parser_spec.rb +916 -0
- data/spec/obj_proxy.rb +22 -0
- data/spec/parser_examples_spec.rb +115 -0
- data/spec/parser_spec.rb +146 -34
- data/spec/spec_helper.rb +1 -0
- metadata +89 -62
- data/ext/breakout_parser/lex.yy.c +0 -2996
- data/ext/breakout_parser/parser.tab.c +0 -2482
- data/ext/breakout_parser/parser.tab.h +0 -113
data/spec/obj_proxy.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
module Breakout
|
2
|
+
# A proxy class that will initialize it's internal object only when some other
|
3
|
+
# code will need something from it, and will call any method on a proxy object.
|
4
|
+
# On first call internal object will be initialized, and all further method
|
5
|
+
# calls (including a first one) will be proxied to it.
|
6
|
+
class ObjProxy
|
7
|
+
def initialize &block
|
8
|
+
@creator_block = block
|
9
|
+
end
|
10
|
+
def method_missing mname, *args
|
11
|
+
@obj = @creator_block.call unless @obj
|
12
|
+
@obj.send(mname,*args)
|
13
|
+
end
|
14
|
+
def inspect
|
15
|
+
@obj ? "ObjProxy: #{@obj.inspect}" : super
|
16
|
+
end
|
17
|
+
def to_str
|
18
|
+
@obj = @creator_block.call unless @obj
|
19
|
+
@obj.respond_to?(:to_str) ? @obj.to_str : ''
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
require 'breakout_parser'
|
2
|
+
|
3
|
+
describe 'BreakoutParser' do
|
4
|
+
|
5
|
+
describe "bad examples" do
|
6
|
+
Dir["examples/orig/*.bad"].sort.each do |fname|
|
7
|
+
it "should not die on #{fname} " do
|
8
|
+
data = File.read(fname)
|
9
|
+
parse_file(fname).size.should >= File.read(fname).strip.gsub(/\s+/,' ').size
|
10
|
+
end
|
11
|
+
it "should parse #{fname} differently from preparsed (or fix me)" do
|
12
|
+
preparsed = unify(preparsed_data(fname))
|
13
|
+
parsed = unify(parse_file(fname))
|
14
|
+
|
15
|
+
parsed.should_not == preparsed
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
describe "pending examples" do
|
20
|
+
Dir["examples/orig/*.pending"].sort.each do |fname|
|
21
|
+
it "should parse #{fname} "
|
22
|
+
it "should not die on #{fname} " do
|
23
|
+
data = File.read(fname)
|
24
|
+
parse_file(fname).size.should >= File.read(fname).strip.gsub(/\s+/,' ').size
|
25
|
+
end
|
26
|
+
it "should parse #{fname} differently from preparsed (or fix me)" do
|
27
|
+
preparsed = unify(preparsed_data(fname))
|
28
|
+
parsed = unify(parse_file(fname))
|
29
|
+
|
30
|
+
parsed.should_not == preparsed
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe "preparsed examples" do
|
36
|
+
Dir["examples/orig/*.txt"].sort.each do |fname|
|
37
|
+
it "should parse #{fname} " do
|
38
|
+
preparsed = unify(preparsed_data(fname))
|
39
|
+
parsed = unify(parse_file(fname))
|
40
|
+
|
41
|
+
if parsed != preparsed
|
42
|
+
# File.open("last-parsed.tmp","w"){ |f| f << parsed }
|
43
|
+
# File.open("last-preparsed.tmp","w"){ |f| f << preparsed }
|
44
|
+
pos = 0
|
45
|
+
pos += 1 while parsed[0..pos] == preparsed[0..pos]
|
46
|
+
pos -= 5
|
47
|
+
pos = 0 if pos<0
|
48
|
+
parsed[pos..-1].should == preparsed[pos..-1]
|
49
|
+
end
|
50
|
+
parsed.should == preparsed
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# unifies texts stripping unnecessary whitespaces
|
56
|
+
# b/c amounts of spaces can be different among parsers
|
57
|
+
def unify text
|
58
|
+
text.downcase.
|
59
|
+
gsub(/(\s*<br \/>\s*)+/,' ').
|
60
|
+
gsub(/\n\s*/,"\n").
|
61
|
+
gsub(/>[ \t]+/,">").
|
62
|
+
gsub(/[ \t]+</,"<").
|
63
|
+
gsub(/[\r\n \t]+/," ").
|
64
|
+
gsub("<a rel=\"nofollow\"","<a").
|
65
|
+
strip
|
66
|
+
end
|
67
|
+
|
68
|
+
def preparsed_data fname
|
69
|
+
bname = File.basename(fname,".*")
|
70
|
+
preparsed = File.read("examples/parsed/#{bname}.txt")
|
71
|
+
preparsed = preparsed[3..-1] if preparsed[0..2] == '<p>'
|
72
|
+
preparsed = preparsed[0..-5] if preparsed[-4..-1] == '</p>'
|
73
|
+
preparsed.gsub!("–","-")
|
74
|
+
preparsed.gsub!("—","--")
|
75
|
+
preparsed.gsub!("‘","'")
|
76
|
+
preparsed.gsub!("’","'")
|
77
|
+
preparsed.gsub!("…","...")
|
78
|
+
preparsed.gsub!("×","x")
|
79
|
+
preparsed.gsub!("©","(c)")
|
80
|
+
preparsed.gsub!("<br />\n","<br />")
|
81
|
+
preparsed.gsub!(/[ \t]+<br \/>/,"<br />")
|
82
|
+
preparsed.gsub!("\t"," ")
|
83
|
+
if preparsed['<hr />']
|
84
|
+
# find longest dash-line in source
|
85
|
+
dashline = File.read(fname).scan(/-+/).sort_by{ |x| -x.length }.first
|
86
|
+
preparsed.gsub!("</p>\n<hr />\n<p>","<br /><br />#{dashline}<br /><br />");
|
87
|
+
end
|
88
|
+
|
89
|
+
# preparsed.gsub!(/^<p>/,"");
|
90
|
+
# preparsed.gsub!(/<\/p>$/,"");
|
91
|
+
preparsed.gsub!("</pre>\n<ol>","</pre><br /><br /><ol>")
|
92
|
+
preparsed.gsub!(/<\/p>\s+<p>/,"<br /><br />")
|
93
|
+
preparsed.gsub!("</p>\n","<br /><br />")
|
94
|
+
preparsed.gsub!("<p>","<br /><br />")
|
95
|
+
preparsed.gsub!(/[\r\n]+ */," ")
|
96
|
+
preparsed.gsub!(/[ \t]{2,}/," ")
|
97
|
+
|
98
|
+
preparsed.gsub!("<del>","-")
|
99
|
+
preparsed.gsub!("</del>","-")
|
100
|
+
preparsed.gsub!(/<br \/>[ ]+/,"<br />")
|
101
|
+
preparsed.gsub!(/(<br \/>){2,}/,"<br /><br />")
|
102
|
+
# preparsed.gsub!("<br /><ol>","<ol>")
|
103
|
+
# preparsed.gsub!("<br /><ul>","<ul>")
|
104
|
+
# preparsed.gsub!("<br /><br /><ul>","<br /><ul>")
|
105
|
+
preparsed
|
106
|
+
end
|
107
|
+
|
108
|
+
###############################################################################
|
109
|
+
###############################################################################
|
110
|
+
###############################################################################
|
111
|
+
|
112
|
+
def parse_file(fname)
|
113
|
+
BreakoutParser.parse(File.read(fname), "test_space").strip
|
114
|
+
end
|
115
|
+
end
|
data/spec/parser_spec.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
|
-
require '
|
2
|
+
require 'spec_helper'
|
3
3
|
require File.dirname(__FILE__) + '/obj_proxy'
|
4
4
|
|
5
5
|
describe 'BreakoutParser' do
|
@@ -18,24 +18,18 @@ describe 'BreakoutParser' do
|
|
18
18
|
|
19
19
|
def get_data fname
|
20
20
|
r = File.read(File.dirname(__FILE__) + '/data/' + fname)
|
21
|
-
if self.class.description[' numbered list multilevel']
|
22
|
-
r.gsub!('*','#')
|
23
|
-
r.gsub!('ul>','ol>')
|
24
|
-
end
|
25
|
-
r
|
26
21
|
end
|
27
22
|
|
28
|
-
it 'accepts from 2 to
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
}.
|
23
|
+
it 'accepts from 2 to 7 arguments' do
|
24
|
+
expect { BreakoutParser.parse }.to raise_error(ArgumentError, "wrong number of arguments (0 for 2..7)")
|
25
|
+
expect { BreakoutParser.parse('a') }.to raise_error(ArgumentError, "wrong number of arguments (1 for 2..7)")
|
26
|
+
[9, 10].each do |argc|
|
27
|
+
expect { BreakoutParser.parse(*(['a'] * (argc - 1) + [{}])) }.to raise_error(ArgumentError, "wrong number of arguments (#{argc} for 2..7)")
|
33
28
|
end
|
34
|
-
(2..
|
35
|
-
|
36
|
-
BreakoutParser.parse(*(['a']*argc))
|
37
|
-
}.should_not raise_error
|
29
|
+
(2..6).each do |argc|
|
30
|
+
expect { BreakoutParser.parse(*(['a'] * argc)) }.to_not raise_error(ArgumentError)
|
38
31
|
end
|
32
|
+
expect { BreakoutParser.parse(*(['a'] * 6 + [{}])) }.to_not raise_error(ArgumentError)
|
39
33
|
end
|
40
34
|
|
41
35
|
it 'converts \n to <br />' do
|
@@ -309,7 +303,7 @@ describe 'BreakoutParser' do
|
|
309
303
|
|
310
304
|
###############################################################################
|
311
305
|
|
312
|
-
describe "
|
306
|
+
describe "unordered list" do
|
313
307
|
it "should work" do
|
314
308
|
parse("* a\n* b\n* c").should match(
|
315
309
|
%r"<ul><li>a</li><li>b</li><li>c</li></ul>"
|
@@ -333,28 +327,55 @@ describe 'BreakoutParser' do
|
|
333
327
|
parse("hello\n\n * a\n * b\n * c\nworld").should ==
|
334
328
|
"hello<br /><br /><ul><li>a</li><li>b</li><li>c</li></ul>world"
|
335
329
|
end
|
330
|
+
it "should respect bold text at the beggining of simple item" do
|
331
|
+
parse("* *this is a bold test* and this is not").should == "<ul><li> <strong>this is a bold test</strong> and this is not</li></ul>"
|
332
|
+
end
|
333
|
+
it "should respect italic text at the beggining of simple item" do
|
334
|
+
parse("* _this is a italic test_ and this is not").should == "<ul><li> <em>this is a italic test</em> and this is not</li></ul>"
|
335
|
+
end
|
336
|
+
|
337
|
+
describe "nested list" do
|
338
|
+
it "should respect bold text at the beginning of the second level item" do
|
339
|
+
parse("* item 1\n** *bold* working").should == "<ul><li>item 1<ul><li> <strong>bold</strong> working</li></ul></li></ul>"
|
340
|
+
end
|
336
341
|
|
337
|
-
|
338
|
-
|
339
|
-
|
342
|
+
it "should respect bold text at the beginning of the third level item" do
|
343
|
+
parse("* item 1\n** item 2\n*** *bold* working").should ==
|
344
|
+
"<ul><li>item 1<ul><li>item 2<ul><li> <strong>bold</strong> working</li></ul></li></ul></li></ul>"
|
345
|
+
end
|
346
|
+
|
347
|
+
it "should respect italic text at the beginning of the second level item" do
|
348
|
+
parse("* item 1\n** _italic_ working").should == "<ul><li>item 1<ul><li> <em>italic</em> working</li></ul></li></ul>"
|
349
|
+
end
|
350
|
+
|
351
|
+
it "should respect italic text at the beginning of the third level item" do
|
352
|
+
parse("* item 1\n** item 2\n*** _italic_ working").should ==
|
353
|
+
"<ul><li>item 1<ul><li>item 2<ul><li> <em>italic</em> working</li></ul></li></ul></li></ul>"
|
354
|
+
end
|
355
|
+
|
356
|
+
it "considers lists with level 2 or higher as level 1" do
|
340
357
|
parse(get_data('list1')).should == unformat(get_data('list1.html'))
|
341
358
|
end
|
342
359
|
|
343
|
-
it "
|
360
|
+
it "parses normally common nested lists with 2 levels deep" do
|
344
361
|
parse(get_data('list2')).should == unformat(get_data('list2.html'))
|
345
362
|
end
|
346
363
|
|
347
|
-
it "
|
364
|
+
it "parses normally common nested lists with 3 levels deep" do
|
348
365
|
parse(get_data('list3')).should == unformat(get_data('list3.html'))
|
349
366
|
end
|
350
367
|
|
351
|
-
it "
|
368
|
+
it "parses normally common nested lists with 3 levels deep [2]" do
|
369
|
+
parse(get_data('list7')).should == unformat(get_data('list7.html'))
|
370
|
+
end
|
371
|
+
|
372
|
+
it "doesn't parse correctly messed up nested list" do
|
352
373
|
r = parse(get_data('list4'))
|
353
374
|
r.scan('<ul>').count.should > 0
|
354
375
|
r.scan('<ul>').count.should == r.scan('</ul>').count
|
355
376
|
end
|
356
377
|
|
357
|
-
it "
|
378
|
+
it "parses normally common nested lists with 3 levels deep [3]" do
|
358
379
|
parse(get_data('list5')).should == unformat(get_data('list5.html'))
|
359
380
|
end
|
360
381
|
|
@@ -363,6 +384,13 @@ describe 'BreakoutParser' do
|
|
363
384
|
r.scan('<ul>').count.should > 0
|
364
385
|
r.scan('<ul>').count.should == r.scan('</ul>').count
|
365
386
|
end
|
387
|
+
|
388
|
+
context "when ordered list is nested within the unordered list," do
|
389
|
+
it 'indents the ordered list inside the unordered list' do
|
390
|
+
parse("* item 1\n## item 1.1\n## item 1.2\n* item 2").should ==
|
391
|
+
"<ul><li>item 1<ol><li>item 1.1</li><li>item 1.2</li></ol></li><li>item 2</li></ul>"
|
392
|
+
end
|
393
|
+
end
|
366
394
|
end
|
367
395
|
end
|
368
396
|
|
@@ -392,10 +420,34 @@ describe 'BreakoutParser' do
|
|
392
420
|
parse("hello\n\n # a\n # b\n # c\nworld").should ==
|
393
421
|
"hello<br /><br /><ol><li>a</li><li>b</li><li>c</li></ol>world"
|
394
422
|
end
|
423
|
+
it "should respect bold text at the beggining of simple item" do
|
424
|
+
parse("# *this is a bold test* and this is not").should == "<ol><li> <strong>this is a bold test</strong> and this is not</li></ol>"
|
425
|
+
end
|
426
|
+
it "should respect italic text at the beggining of simple item" do
|
427
|
+
parse("# _this is a italic test_ and this is not").should == "<ol><li> <em>this is a italic test</em> and this is not</li></ol>"
|
428
|
+
end
|
429
|
+
|
430
|
+
describe "numbered lists multilevel" do
|
431
|
+
it "should respect bold text at the beginning of the second level item" do
|
432
|
+
parse("# item 1\n## *bold* working").should == "<ol><li>item 1<ol><li> <strong>bold</strong> working</li></ol></li></ol>"
|
433
|
+
end
|
434
|
+
|
435
|
+
it "should respect bold text at the beginning of the third level item" do
|
436
|
+
parse("# item 1\n## item 2\n### *bold* working").should ==
|
437
|
+
"<ol><li>item 1<ol><li>item 2<ol><li> <strong>bold</strong> working</li></ol></li></ol></li></ol>"
|
438
|
+
end
|
439
|
+
|
440
|
+
it "should respect italic text at the beginning of the second level item" do
|
441
|
+
parse("# item 1\n## _italic_ working").should == "<ol><li>item 1<ol><li> <em>italic</em> working</li></ol></li></ol>"
|
442
|
+
end
|
395
443
|
|
396
|
-
|
397
|
-
|
398
|
-
|
444
|
+
it "should respect italic text at the beginning of the third level item" do
|
445
|
+
parse("# item 1\n## item 2\n### _italic_ working").should ==
|
446
|
+
"<ol><li>item 1<ol><li>item 2<ol><li> <em>italic</em> working</li></ol></li></ol></li></ol>"
|
447
|
+
end
|
448
|
+
|
449
|
+
it "converts starting level 2 list as starting level 1 list" do
|
450
|
+
File.open("./teste.txt", "a") { |fp| fp.puts("opa") }
|
399
451
|
parse(get_data('list1')).should == unformat(get_data('list1.html'))
|
400
452
|
end
|
401
453
|
|
@@ -409,8 +461,8 @@ describe 'BreakoutParser' do
|
|
409
461
|
|
410
462
|
it "mess - should have matching count of opening and closing tags" do
|
411
463
|
r = parse(unformat(get_data('list4')))
|
412
|
-
r.scan('<
|
413
|
-
r.scan('<
|
464
|
+
r.scan('<ul>').count.should > 0
|
465
|
+
r.scan('<ul>').count.should <= r.scan('</ul>').count
|
414
466
|
end
|
415
467
|
|
416
468
|
it "at end" do
|
@@ -419,6 +471,28 @@ describe 'BreakoutParser' do
|
|
419
471
|
end
|
420
472
|
end
|
421
473
|
|
474
|
+
describe "ordered list (with letters)" do
|
475
|
+
context "for one level deep lists," do
|
476
|
+
it "parses it correctly" do
|
477
|
+
expect(parse("% a\n% b\n% c")).to eq("<ol class='letters'><li>a</li><li>b</li><li>c</li></ol>")
|
478
|
+
end
|
479
|
+
|
480
|
+
it "parses it correctly when among a text" do
|
481
|
+
expect(parse("aaa\n% a\n% b\n% c\nbbb")).to include("<ol class='letters'><li>a</li><li>b</li><li>c</li></ol>")
|
482
|
+
end
|
483
|
+
end
|
484
|
+
|
485
|
+
context "when the list is a nested list," do
|
486
|
+
context "and it's mixed within other list types," do
|
487
|
+
it 'nests the lists correctly' do
|
488
|
+
parse("* a\n## a.1\n%%% a.1.1\n## a.2\n* b").should ==
|
489
|
+
"<ul><li>a<ol><li>a.1<ol class='letters'><li>a.1.1</li></ol></li><li>a.2</li></ol></li><li>b</li></ul>"
|
490
|
+
end
|
491
|
+
end
|
492
|
+
end
|
493
|
+
|
494
|
+
end
|
495
|
+
|
422
496
|
###############################################################################
|
423
497
|
# headers
|
424
498
|
|
@@ -841,7 +915,7 @@ describe 'BreakoutParser' do
|
|
841
915
|
a["url:http://www.ru"] = '<a rel="nofollow" href="http://www.ru">http://www.ru</a>'
|
842
916
|
a["url:https://www.ru"] = '<a rel="nofollow" href="https://www.ru">https://www.ru</a>'
|
843
917
|
a["url:www.ru"] = '<a rel="nofollow" href="http://www.ru">http://www.ru</a>'
|
844
|
-
a["url:www.ru/?a=1&b=2"] = '<a rel="nofollow" href="http://www.ru/?a=1&b=2">http://www.ru/?a=1&b=2</a>'
|
918
|
+
a["url:www.ru/?a=1&b=2"] = '<a rel="nofollow" href="http://www.ru/?a=1&b=2">http://www.ru/?a=1&b=2</a>'
|
845
919
|
a["url:ftp://www.ru"] = '<a rel="nofollow" href="ftp://www.ru">ftp://www.ru</a>'
|
846
920
|
a["url:/spaces/x2"] = '<a rel="nofollow" href="/spaces/x2">/spaces/x2</a>'
|
847
921
|
|
@@ -992,6 +1066,33 @@ describe 'BreakoutParser' do
|
|
992
1066
|
end
|
993
1067
|
end
|
994
1068
|
|
1069
|
+
describe 'large_files_url' do
|
1070
|
+
let(:large_files_url) { "https://bigfiles.assembla.com" }
|
1071
|
+
|
1072
|
+
it 'should use the url' do
|
1073
|
+
parse("[[file:MyFile.png]]", :large_files_url => large_files_url).should ==
|
1074
|
+
"<a href=\"https://bigfiles.assembla.com/spaces/test_space/documents/download/MyFile.png\">file:MyFile.png</a>"
|
1075
|
+
end
|
1076
|
+
|
1077
|
+
it 'should not use the url' do
|
1078
|
+
parse("[[file:MyFile.png]]").should ==
|
1079
|
+
"<a href=\"/spaces/test_space/documents/download/MyFile.png\">file:MyFile.png</a>"
|
1080
|
+
end
|
1081
|
+
end
|
1082
|
+
|
1083
|
+
describe 'data attributes' do
|
1084
|
+
let(:meta_attrs) { {"15000" => {"space" => "breakout", "number" => "15000"}} }
|
1085
|
+
|
1086
|
+
subject { parse("Comment to ticket #15000", :meta_attributes => meta_attrs) }
|
1087
|
+
|
1088
|
+
# We cannot test the exact match because Hash returns its elements in random order
|
1089
|
+
it 'adds data attributes to URL' do
|
1090
|
+
expect(subject).to include(%Q{data-space="breakout"})
|
1091
|
+
expect(subject).to include(%Q{data-number="15000"})
|
1092
|
+
expect(subject).to include(%Q{Comment to ticket <a href="/spaces/test_space/tickets/15000"})
|
1093
|
+
end
|
1094
|
+
end
|
1095
|
+
|
995
1096
|
a = {}
|
996
1097
|
a["image:ExistingImage.png"] =
|
997
1098
|
'<img src="/spaces/test_space/documents/download/ExistingImage.png" alt="ALT" />'
|
@@ -1034,27 +1135,38 @@ describe 'BreakoutParser' do
|
|
1034
1135
|
s = "[[image:aaa bbb]]"
|
1035
1136
|
parse(s).should == s
|
1036
1137
|
end
|
1138
|
+
|
1139
|
+
it 'escapes characters in urls' do
|
1140
|
+
expect(parse(%Q{[[url:http://;"onmouseover="alert(0000000000000000)"s"|Ae]]})).to eq(%Q{<a rel="nofollow" href="http://;"onmouseover="alert(0000000000000000)"s"">Ae</a>})
|
1141
|
+
end
|
1142
|
+
|
1143
|
+
it 'parses snippets' do
|
1144
|
+
result = parse("[[snippet:breakout:123]]")
|
1145
|
+
expect(result).to match(/<script async="true" id="snippet-123" src="\/spaces\/breakout\/snippets\/123.js\?_=\d+"><\/script>/)
|
1146
|
+
end
|
1037
1147
|
end
|
1038
1148
|
|
1039
1149
|
###############################################################################
|
1040
1150
|
###############################################################################
|
1041
1151
|
###############################################################################
|
1042
1152
|
|
1043
|
-
unless defined?HTML_ESCAPE
|
1044
|
-
HTML_ESCAPE
|
1153
|
+
unless defined?(HTML_ESCAPE)
|
1154
|
+
HTML_ESCAPE = { '&' => '&', '>' => '>', '<' => '<', '"' => '"' }
|
1045
1155
|
end
|
1046
1156
|
|
1047
|
-
def h
|
1157
|
+
def h(s)
|
1048
1158
|
s.to_s.gsub(/[&"><]/) { |special| HTML_ESCAPE[special] }
|
1049
1159
|
end
|
1050
1160
|
|
1051
|
-
def parse
|
1161
|
+
def parse(s, h = {})
|
1052
1162
|
h[:space_name] = "test_space" unless h.key?(:space_name)
|
1053
1163
|
BreakoutParser.parse(s,
|
1054
1164
|
h[:space_name],
|
1055
1165
|
h[:site_url],
|
1056
1166
|
h[:vcs_url],
|
1057
|
-
h[:absolute_urls]
|
1167
|
+
h[:absolute_urls],
|
1168
|
+
h[:large_files_url],
|
1169
|
+
h[:meta_attributes]
|
1058
1170
|
).strip
|
1059
1171
|
end
|
1060
1172
|
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'breakout_parser/breakout_parser'
|
metadata
CHANGED
@@ -1,99 +1,126 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: breakout_parser
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
prerelease: false
|
6
|
-
segments:
|
7
|
-
- 0
|
8
|
-
- 0
|
9
|
-
- 23
|
10
|
-
version: 0.0.23
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.31
|
11
5
|
platform: ruby
|
12
|
-
authors:
|
6
|
+
authors:
|
13
7
|
- Andrey "Zed" Zaikin
|
14
8
|
autorequire:
|
15
9
|
bindir: bin
|
16
10
|
cert_chain: []
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
11
|
+
date: 2014-06-12 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: jeweler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ! '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ! '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ! '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
23
35
|
prerelease: false
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ! '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake-compiler
|
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: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
34
61
|
version: 1.2.9
|
35
62
|
type: :development
|
36
|
-
|
37
|
-
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ! '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 1.2.9
|
69
|
+
description: BreakoutParser is a library that parses Breakout custom Textile input
|
38
70
|
email: zed.0xff@gmail.com
|
39
71
|
executables: []
|
40
|
-
|
41
|
-
extensions:
|
72
|
+
extensions:
|
42
73
|
- ext/breakout_parser/extconf.rb
|
43
|
-
extra_rdoc_files:
|
74
|
+
extra_rdoc_files:
|
44
75
|
- ChangeLog
|
45
76
|
- LICENSE
|
46
77
|
- README
|
47
|
-
files:
|
78
|
+
files:
|
48
79
|
- ChangeLog
|
49
80
|
- LICENSE
|
50
81
|
- README
|
51
82
|
- ext/breakout_parser/depend
|
52
83
|
- ext/breakout_parser/extconf.rb
|
53
|
-
- ext/breakout_parser/lex.yy.c
|
54
84
|
- ext/breakout_parser/main.c
|
55
85
|
- ext/breakout_parser/make_win32.bat
|
86
|
+
- ext/breakout_parser/parser.h
|
56
87
|
- ext/breakout_parser/parser.l
|
57
|
-
- ext/breakout_parser/parser.tab.c
|
58
|
-
- ext/breakout_parser/parser.tab.h
|
59
88
|
- ext/breakout_parser/parser.y
|
60
89
|
- ext/breakout_parser/ruby_ext.c
|
90
|
+
- ext/breakout_parser/ruby_ext.h
|
61
91
|
- ext/breakout_parser/yywrap.c
|
62
92
|
- lib/breakout_parser.rb
|
93
|
+
- spec/links_only_parser_spec.rb
|
94
|
+
- spec/obj_proxy.rb
|
95
|
+
- spec/parser_examples_spec.rb
|
63
96
|
- spec/parser_spec.rb
|
64
|
-
|
65
|
-
homepage:
|
97
|
+
- spec/spec_helper.rb
|
98
|
+
homepage: https://www.assembla.com
|
66
99
|
licenses: []
|
67
|
-
|
100
|
+
metadata: {}
|
68
101
|
post_install_message:
|
69
102
|
rdoc_options: []
|
70
|
-
|
71
|
-
require_paths:
|
103
|
+
require_paths:
|
72
104
|
- lib
|
73
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
none: false
|
84
|
-
requirements:
|
85
|
-
- - ">="
|
86
|
-
- !ruby/object:Gem::Version
|
87
|
-
hash: 3
|
88
|
-
segments:
|
89
|
-
- 0
|
90
|
-
version: "0"
|
105
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
111
|
+
requirements:
|
112
|
+
- - ! '>='
|
113
|
+
- !ruby/object:Gem::Version
|
114
|
+
version: '0'
|
91
115
|
requirements: []
|
92
|
-
|
93
116
|
rubyforge_project:
|
94
|
-
rubygems_version:
|
117
|
+
rubygems_version: 2.2.2
|
95
118
|
signing_key:
|
96
|
-
specification_version:
|
119
|
+
specification_version: 4
|
97
120
|
summary: BreakoutParser
|
98
|
-
test_files:
|
121
|
+
test_files:
|
122
|
+
- spec/links_only_parser_spec.rb
|
123
|
+
- spec/obj_proxy.rb
|
124
|
+
- spec/parser_examples_spec.rb
|
99
125
|
- spec/parser_spec.rb
|
126
|
+
- spec/spec_helper.rb
|