breakout_parser 0.0.11 → 0.0.12

Sign up to get free protection for your applications and to get access to all the features.
@@ -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