breakout_parser 0.0.11 → 0.0.12

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.
@@ -51,35 +51,37 @@
51
51
  GIT_REVISION_LINK = 267,
52
52
  WIKI_LINK = 268,
53
53
  ANCHOR_LINK = 269,
54
- URL_WITH_PROTO_LINK = 270,
55
- URL_WITHOUT_PROTO_LINK = 271,
56
- FILE_LINK = 272,
57
- IMAGE_LINK = 273,
58
- URL = 274,
59
- EMAIL = 275,
60
- UL = 276,
61
- H1 = 277,
62
- H2 = 278,
63
- H3 = 279,
64
- H4 = 280,
65
- H5 = 281,
66
- INLINE_CODE = 282,
67
- SPACE = 283,
68
- BR = 284,
69
- OLI = 285,
70
- ULI = 286,
71
- PRE_CODE_START = 287,
72
- PRE_CODE_END = 288,
73
- PRE_START = 289,
74
- PRE_END = 290,
75
- CODE_START = 291,
76
- CODE_END = 292,
77
- NOTEXTILE_START = 293,
78
- NOTEXTILE_END = 294,
79
- BOLD_END = 295,
80
- ITALIC_END = 296,
81
- REVERT_BOLD = 297,
82
- REVERT_ITALIC = 298
54
+ SVN_N_REVISION_LINK = 270,
55
+ GIT_N_REVISION_LINK = 271,
56
+ URL_WITH_PROTO_LINK = 272,
57
+ URL_WITHOUT_PROTO_LINK = 273,
58
+ FILE_LINK = 274,
59
+ IMAGE_LINK = 275,
60
+ URL = 276,
61
+ EMAIL = 277,
62
+ UL = 278,
63
+ H1 = 279,
64
+ H2 = 280,
65
+ H3 = 281,
66
+ H4 = 282,
67
+ H5 = 283,
68
+ INLINE_CODE = 284,
69
+ SPACE = 285,
70
+ BR = 286,
71
+ OLI = 287,
72
+ ULI = 288,
73
+ PRE_CODE_START = 289,
74
+ PRE_CODE_END = 290,
75
+ PRE_START = 291,
76
+ PRE_END = 292,
77
+ CODE_START = 293,
78
+ CODE_END = 294,
79
+ NOTEXTILE_START = 295,
80
+ NOTEXTILE_END = 296,
81
+ BOLD_END = 297,
82
+ ITALIC_END = 298,
83
+ REVERT_BOLD = 299,
84
+ REVERT_ITALIC = 300
83
85
  };
84
86
  #endif
85
87
 
@@ -90,7 +92,7 @@ typedef union YYSTYPE
90
92
  {
91
93
 
92
94
  /* Line 1676 of yacc.c */
93
- #line 61 "parser.y"
95
+ #line 66 "parser.y"
94
96
 
95
97
  double dvalue;
96
98
  int ivalue;
@@ -99,7 +101,7 @@ typedef union YYSTYPE
99
101
 
100
102
 
101
103
  /* Line 1676 of yacc.c */
102
- #line 103 "parser.tab.h"
104
+ #line 105 "parser.tab.h"
103
105
  } YYSTYPE;
104
106
  # define YYSTYPE_IS_TRIVIAL 1
105
107
  # define yystype YYSTYPE /* obsolescent; will be withdrawn */
@@ -20,6 +20,11 @@ size_t bufsize = 0;
20
20
  const char *space_name = NULL;
21
21
  size_t space_name_len = 0;
22
22
 
23
+ const char *site_url = NULL;
24
+ size_t site_url_len = 0;
25
+
26
+ extern VALUE git_url;
27
+
23
28
  #define CHECK_BUF_SIZE(len) \
24
29
  if( (bufptr - buf + len + 1) >= bufsize ){ \
25
30
  /*printf("[.] REALLOC oldsz=%d, newsz=%d\n",bufsize, (bufsize+((len > 0x1000) ? (len+0x1000) : 0x1000)));*/ \
@@ -68,6 +73,7 @@ void yyerror(const char *msg)
68
73
  %token <ivalue> T_CHAR BOLD_START ITALIC_START
69
74
  %token <ivalue> BOLD_ITALIC_START ITALIC_BOLD_START
70
75
  %token <svalue> T_WORD TICKET_LINK LINK SVN_REVISION_LINK GIT_REVISION_LINK WIKI_LINK ANCHOR_LINK
76
+ %token <svalue> SVN_N_REVISION_LINK GIT_N_REVISION_LINK
71
77
  %token <svalue> URL_WITH_PROTO_LINK URL_WITHOUT_PROTO_LINK
72
78
  %token <svalue> FILE_LINK IMAGE_LINK
73
79
  %token <svalue> URL EMAIL
@@ -130,8 +136,10 @@ word : chars
130
136
  | REVERT_ITALIC {revert_italic()}
131
137
 
132
138
  link: TICKET_LINK {process_ticket_link($1)}
133
- | SVN_REVISION_LINK {process_svn_link($1)}
134
- | GIT_REVISION_LINK {process_git_link($1)}
139
+ | SVN_REVISION_LINK {process_svn_link($1,0)}
140
+ | GIT_REVISION_LINK {process_git_link($1,0)}
141
+ | SVN_N_REVISION_LINK {process_svn_link($1,1)}
142
+ | GIT_N_REVISION_LINK {process_git_link($1,1)}
135
143
  | URL_WITH_PROTO_LINK {process_url_link($1,NULL)}
136
144
  | URL_WITHOUT_PROTO_LINK {process_url_link($1,"http://")}
137
145
  | WIKI_LINK {process_wiki_link($1)}
@@ -286,29 +294,72 @@ process_url_link(const char*target,const char* proto){
286
294
  process_link_tail(target,NULL,proto);
287
295
  }
288
296
 
289
- process_svn_link(const char*target){
297
+ concat_site_url(){
298
+ if( site_url && site_url_len > 0 ){
299
+ concat(site_url, site_url_len);
300
+ }
301
+ }
302
+
303
+ process_svn_link(const char*target, int numbered_repo){
290
304
  const char *c;
291
- concat("<a href=\"/code/",15);
305
+ // can use sprintf here.. but I think it's a way slower than raw concat
306
+ concat("<a href=\"",9);
307
+ concat_site_url();
308
+ concat("/code/",6);
292
309
  concat(space_name,space_name_len);
293
- concat("/subversion/changesets/",23);
310
+ if( numbered_repo ){
311
+ concat("/subversion-",12);
312
+ while( *target >= '0' && *target <= '9' ) concat_raw_char(*target++);
313
+ while( *target == ':' ) target++;
314
+ concat("/changesets/",12);
315
+ } else {
316
+ concat("/subversion/changesets/",23);
317
+ }
294
318
  for(c=target; *c && *c!=']' && *c!='|'; c++) concat_raw_char(*c);
295
319
  process_link_tail(target,NULL,"revision:");
296
320
  }
297
321
 
298
- process_git_link(const char*target){
322
+ int concat_custom_git_url(){
299
323
  const char *c;
300
- concat("<a href=\"/code/",15);
301
- concat(space_name,space_name_len);
302
- concat("/git/changesets/",16);
324
+ if( git_url && (c = StringValuePtr(git_url)) ){
325
+ size_t l = strlen(c);
326
+ if( l>0 ){
327
+ concat2(c);
328
+ return 1;
329
+ }
330
+ }
331
+ return 0;
332
+ }
333
+
334
+ process_git_link(const char*target, int numbered_repo){
335
+ const char *c;
336
+ // can use sprintf here.. but I think it's a way slower than raw concat
337
+ concat("<a href=\"",9);
338
+ if( !concat_custom_git_url() ){
339
+ concat_site_url();
340
+ concat("/code/",6);
341
+ concat(space_name,space_name_len);
342
+ if( numbered_repo ){
343
+ concat("/git-",5);
344
+ while( *target >= '0' && *target <= '9' ) concat_raw_char(*target++);
345
+ while( *target == ':' ) target++;
346
+ concat("/changesets/",12);
347
+ } else {
348
+ concat("/git/changesets/",16);
349
+ }
350
+ }
303
351
  for(c=target; *c && *c!=']' && *c!='|'; c++) concat_raw_char(*c);
304
352
  process_link_tail(target,NULL,"revision:");
305
353
  }
306
354
 
307
355
  process_wiki_link(const char*target){
308
356
  const char *c;
357
+ // can use sprintf here.. but I think it's a way slower than raw concat
309
358
  concat("<a class=\"wiki_link\" title=\"",28);
310
359
  for(c=target; *c && *c!=']' && *c!='|'; c++) concat_raw_char(*c);
311
- concat("\" href=\"/wiki/show/",19);
360
+ concat("\" href=\"",8);
361
+ concat_site_url();
362
+ concat("/wiki/show/",11);
312
363
  concat(space_name,space_name_len);
313
364
  concat_raw_char('/');
314
365
  for(c=target; *c && *c!=']' && *c!='|'; c++) concat_raw_char(*c);
@@ -317,7 +368,10 @@ process_wiki_link(const char*target){
317
368
 
318
369
  process_file_link(const char*target){
319
370
  const char *c;
320
- concat("<a href=\"/spaces/",17);
371
+ // can use sprintf here.. but I think it's a way slower than raw concat
372
+ concat("<a href=\"",9);
373
+ concat_site_url();
374
+ concat("/spaces/",8);
321
375
  concat(space_name,space_name_len);
322
376
  concat("/documents/download/",20);
323
377
  for(c=target; *c && *c!=']' && *c!='|'; c++) concat_raw_char(*c);
@@ -326,7 +380,10 @@ process_file_link(const char*target){
326
380
 
327
381
  process_image_link(const char*target){
328
382
  const char *c, *p;
329
- concat("<img src=\"/spaces/",18);
383
+ // can use sprintf here.. but I think it's a way slower than raw concat
384
+ concat("<img src=\"",10);
385
+ concat_site_url();
386
+ concat("/spaces/",8);
330
387
  concat(space_name,space_name_len);
331
388
  concat("/documents/download/",20);
332
389
  for(c=target; *c && *c!=']' && *c!='|'; c++) concat_raw_char(*c);
@@ -342,7 +399,10 @@ process_image_link(const char*target){
342
399
  process_ticket_link(const char*ticket_id){
343
400
  const char *c;
344
401
  while(*ticket_id && (*ticket_id < '0' || *ticket_id > '9') ) ticket_id++;
345
- concat("<a href=\"/spaces/",17);
402
+ // can use sprintf here.. but I think it's a way slower than raw concat
403
+ concat("<a href=\"",9);
404
+ concat_site_url();
405
+ concat("/spaces/",8);
346
406
  concat(space_name,space_name_len);
347
407
  concat("/tickets/",9);
348
408
  for(c=ticket_id; *c && *c>='0' && *c<='9'; c++) concat_raw_char(*c);
@@ -375,36 +435,6 @@ concat_raw_char(int c){
375
435
  *bufptr++ = c;
376
436
  }
377
437
 
378
- /*
379
- concat_escaping_html(const char*what){
380
- char *po = buf + strlen(buf);
381
- const char *pi = what;
382
-
383
- for(;*pi;pi++){
384
- switch(*pi){
385
- case '<':
386
- strcpy(po,"&lt;");
387
- po += 4;
388
- break;
389
- case '>':
390
- strcpy(po,"&gt;");
391
- po += 4;
392
- break;
393
- case '"':
394
- strcpy(po,"&quot;");
395
- po += 6;
396
- break;
397
- case '&':
398
- strcpy(po,"&amp;");
399
- po += 5;
400
- break;
401
- default:
402
- *po++ = *pi;
403
- }
404
- }
405
- *po = 0;
406
- }*/
407
-
408
438
  process_url(const char*url){
409
439
  const char *p;
410
440
 
@@ -3,15 +3,15 @@
3
3
  #include "ruby.h"
4
4
 
5
5
  void Init_breakout_parser();
6
- VALUE method_parse(VALUE, VALUE, VALUE);
7
- VALUE method_parse_links_only(VALUE, VALUE, VALUE);
6
+ VALUE method_parse(int, VALUE*, VALUE);
7
+ VALUE method_parse_links_only(int, VALUE*, VALUE);
8
8
 
9
9
  VALUE breakout_parser = Qnil;
10
10
 
11
11
  void Init_breakout_parser() {
12
12
  breakout_parser = rb_define_class("BreakoutParser",rb_cObject);
13
- rb_define_singleton_method(breakout_parser, "parse", method_parse, 2);
14
- rb_define_singleton_method(breakout_parser, "parse_links_only", method_parse_links_only, 2);
13
+ rb_define_singleton_method(breakout_parser, "parse", method_parse, -1);
14
+ rb_define_singleton_method(breakout_parser, "parse_links_only", method_parse_links_only, -1);
15
15
  }
16
16
 
17
17
  extern char *buf, *bufptr;
@@ -19,12 +19,40 @@ extern char *in_buf, *in_pos;
19
19
  extern const char *space_name;
20
20
  extern size_t in_buf_len, bufsize, space_name_len;
21
21
 
22
+ extern const char *site_url;
23
+ extern size_t site_url_len;
24
+
25
+ VALUE git_url;
26
+
22
27
  extern int parse_links_only;
23
28
 
24
- VALUE do_parse(VALUE self, VALUE text, VALUE r_space_name) {
25
- VALUE s;
29
+ VALUE do_parse(int argc, VALUE *argv, VALUE self) {
30
+ VALUE s, text, r_space_name;
26
31
  char *p;
27
32
 
33
+ if( argc < 2 || argc > 4 ){
34
+ rb_raise(rb_eArgError, "wrong number of arguments (%d for 2..4)", argc);
35
+ return rb_str_new("",0); // unreachable code, but for double safety
36
+ }
37
+
38
+ text = argv[0];
39
+ r_space_name = argv[1];
40
+
41
+ site_url = NULL; site_url_len = 0;
42
+ if( argc > 2 && argv[2] != Qnil && argv[2] != Qfalse ){
43
+ site_url = StringValueCStr(argv[2]);
44
+ site_url_len = site_url ? strlen(site_url) : 0;
45
+ while( site_url && site_url_len > 0 && site_url[site_url_len-1] == '/' ) {
46
+ // skip trailing slashes
47
+ site_url_len--;
48
+ }
49
+ }
50
+
51
+ git_url = NULL;
52
+ if( argc > 3 && argv[3] != Qnil && argv[3] != Qfalse ){
53
+ git_url = argv[3];
54
+ }
55
+
28
56
  if(!text || text == Qnil || text == Qfalse){
29
57
  // NULL input string
30
58
  return rb_str_new("",0);
@@ -73,14 +101,14 @@ VALUE do_parse(VALUE self, VALUE text, VALUE r_space_name) {
73
101
  return s;
74
102
  }
75
103
 
76
- VALUE method_parse(VALUE self, VALUE text, VALUE r_space_name) {
104
+ VALUE method_parse(int argc, VALUE *argv, VALUE self) {
77
105
  parse_links_only = 0;
78
- return do_parse(self,text,r_space_name);
106
+ return do_parse(argc, argv, self);
79
107
  }
80
108
 
81
- VALUE method_parse_links_only(VALUE self, VALUE text, VALUE r_space_name) {
109
+ VALUE method_parse_links_only(int argc, VALUE *argv, VALUE self) {
82
110
  parse_links_only = 1;
83
- return do_parse(self,text,r_space_name);
111
+ return do_parse(argc, argv, self);
84
112
  }
85
113
 
86
114
  #endif // ifdef RUBY_VERSION
data/spec/parser_spec.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require 'breakout_parser'
2
+ require File.dirname(__FILE__) + '/obj_proxy'
2
3
 
3
4
  describe 'BreakoutParser' do
4
5
  def self.hex_string s
@@ -10,6 +11,19 @@ describe 'BreakoutParser' do
10
11
  end
11
12
  def hex_string s; self.class.hex_string(s); end
12
13
 
14
+ it 'accepts from 2 to 4 arguments' do
15
+ [0,1,5,6,7,8,9,10].each do |argc|
16
+ lambda{
17
+ BreakoutParser.parse(*(['a']*argc))
18
+ }.should raise_error(ArgumentError, "wrong number of arguments (#{argc} for 2..4)")
19
+ end
20
+ (2..4).each do |argc|
21
+ lambda{
22
+ BreakoutParser.parse(*(['a']*argc))
23
+ }.should_not raise_error
24
+ end
25
+ end
26
+
13
27
  it 'converts \n to <br />' do
14
28
  parse("aaa\nbbb").should match(%r"aaa ?<br /> ?bbb")
15
29
  end
@@ -31,22 +45,22 @@ describe 'BreakoutParser' do
31
45
 
32
46
  it "handles nil & false text well" do
33
47
  parse(false).should == ""
34
- parse(false,false).should == ""
35
- parse("",false).should == ""
48
+ parse(false, :space_name => false).should == ""
49
+ parse("", :space_name => false).should == ""
36
50
  parse(nil).should == ""
37
- parse(nil,nil).should == ""
38
- parse("",nil).should == ""
51
+ parse(nil, :space_name => nil).should == ""
52
+ parse("", :space_name => nil).should == ""
39
53
  end
40
54
 
41
55
  it "handles nil space_name well" do
42
56
  lambda{
43
- parse("#123",nil)
57
+ parse("#123", :space_name => nil)
44
58
  }.should raise_error(TypeError)
45
59
  end
46
60
 
47
61
  it "handles false space_name well" do
48
62
  lambda{
49
- parse("#123",false)
63
+ parse("#123", :space_name => false)
50
64
  }.should raise_error(TypeError)
51
65
  end
52
66
 
@@ -740,8 +754,14 @@ describe 'BreakoutParser' do
740
754
  '<a href="/code/test_space/git/changesets/1f4bdab77be696efd">revision:1f4bdab77be696efd</a>'
741
755
  a["revision:12345"] =
742
756
  '<a href="/code/test_space/subversion/changesets/12345">revision:12345</a>'
757
+ a["revision:567:1f4bdab77be696efd"] =
758
+ '<a href="/code/test_space/git-567/changesets/1f4bdab77be696efd">revision:1f4bdab77be696efd</a>'
759
+ a["revision:3:12345"] =
760
+ '<a href="/code/test_space/subversion-3/changesets/12345">revision:12345</a>'
743
761
  a["r:2345"] = '<a href="/code/test_space/subversion/changesets/2345">revision:2345</a>'
744
762
  a["r:2345ef"] = '<a href="/code/test_space/git/changesets/2345ef">revision:2345ef</a>'
763
+ a["r:10:2345"] = '<a href="/code/test_space/subversion-10/changesets/2345">revision:2345</a>'
764
+ a["r:1:2345ef"] = '<a href="/code/test_space/git-1/changesets/2345ef">revision:2345ef</a>'
745
765
 
746
766
  a["url:http://www.ru"] = '<a rel="nofollow" href="http://www.ru">http://www.ru</a>'
747
767
  a["url:https://www.ru"] = '<a rel="nofollow" href="https://www.ru">https://www.ru</a>'
@@ -765,6 +785,69 @@ describe 'BreakoutParser' do
765
785
  it "parses [[#{k}|test & here]]" do
766
786
  parse("[[#{k}|test & here]]").should == v.sub(/>.*</,">test &amp; here<")
767
787
  end
788
+ if v['href="/'] && !k['url:']
789
+ it "parses [[#{k}]] with a site url" do
790
+ site_url = "http://www.ru"
791
+ parse("[[#{k}]]", :site_url => site_url).should ==
792
+ v.gsub('href="/',"href=\"#{site_url}/")
793
+
794
+ # with extraordinary slash
795
+ parse("[[#{k}]]", :site_url => "#{site_url}/").should ==
796
+ v.gsub('href="/',"href=\"#{site_url}/")
797
+
798
+ site_url = "http://127.0.0.1:3000"
799
+ parse("[[#{k}]]", :site_url => site_url).should ==
800
+ v.gsub('href="/',"href=\"#{site_url}/")
801
+
802
+ # with extraordinary slash
803
+ parse("[[#{k}]]", :site_url => "#{site_url}/").should ==
804
+ v.gsub('href="/',"href=\"#{site_url}/")
805
+ end
806
+ end
807
+ if v['/git/']
808
+ it "parses [[#{k}]] with custom git_url (String)" do
809
+ git_url = "http://www.ru/"
810
+ rev = k.split(':').last.tr(']','')
811
+ parse("[[#{k}]]", :git_url => git_url).should ==
812
+ v.sub('/code/test_space/git/changesets/',git_url)
813
+ end
814
+
815
+ it "parses [[#{k}]] with custom git_url (ObjProxy)" do
816
+ rev = k.split(':').last.tr(']','')
817
+ @asdfg = 'http://mmm.us'
818
+ git_url = Breakout::ObjProxy.new do
819
+ @asdfg + '/'
820
+ end
821
+ parse("[[#{k}]]", :git_url => git_url).should ==
822
+ v.sub('/code/test_space/git/changesets/',git_url)
823
+ end
824
+
825
+ it "parses [[#{k}]] with NULL git_url (ObjProxy)" do
826
+ rev = k.split(':').last.tr(']','')
827
+ git_url = Breakout::ObjProxy.new do
828
+ nil
829
+ end
830
+ parse("[[#{k}]]", :git_url => git_url).should == v
831
+ end
832
+
833
+ it "parses [[#{k}]] with FALSE git_url (ObjProxy)" do
834
+ rev = k.split(':').last.tr(']','')
835
+ git_url = Breakout::ObjProxy.new do
836
+ false
837
+ end
838
+ parse("[[#{k}]]", :git_url => git_url).should == v
839
+ end
840
+ end
841
+ end
842
+
843
+ it "should not instantiate ObjProxy's internal object if there's no git links in text" do
844
+ git_url = Breakout::ObjProxy.new do
845
+ raise 'should not be raised'
846
+ end
847
+ lambda {
848
+ parse("[[r:2345]]", :git_url => git_url).should ==
849
+ '<a href="/code/test_space/subversion/changesets/2345">revision:2345</a>'
850
+ }.should_not raise_error
768
851
  end
769
852
 
770
853
  a = {}
@@ -823,7 +906,8 @@ describe 'BreakoutParser' do
823
906
  s.to_s.gsub(/[&"><]/) { |special| HTML_ESCAPE[special] }
824
907
  end
825
908
 
826
- def parse s, space_name = "test_space"
827
- BreakoutParser.parse(s, space_name).strip
909
+ def parse s, h = {}
910
+ h[:space_name] = "test_space" unless h.key?(:space_name)
911
+ BreakoutParser.parse(s, h[:space_name], h[:site_url], h[:git_url]).strip
828
912
  end
829
913
  end