radius-ts 1.1.0 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -5,7 +5,8 @@
5
5
  action _prefix { mark_pfx = p }
6
6
  action prefix {
7
7
  if data[mark_pfx..p-1] != @prefix
8
- @nodes.last << data[mark_pfx-1..p]
8
+ closing = data[mark_pfx-1,1] == '/'
9
+ @nodes.last << data[mark_pfx-(closing ? 2 : 1)..p]
9
10
  fbreak;
10
11
  end
11
12
  }
@@ -0,0 +1,125 @@
1
+ %%{
2
+ machine parser;
3
+
4
+
5
+ # action _prefix { mark_pfx = p }
6
+ # action prefix {
7
+ # if data[mark_pfx..p-1] != @prefix
8
+ # @nodes.last << data[mark_pfx-1..p]
9
+ # fbreak;
10
+ # end
11
+ # }
12
+ action _starttag { mark_stg = p }
13
+ action starttag { @starttag = data[mark_stg..p-1] }
14
+ action _attr { mark_attr = p }
15
+ action attr {
16
+ @attrs[@nat] = @vat
17
+ }
18
+
19
+ action prematch {
20
+ @prematch_end = p
21
+ @prematch = data[0..p] if p > 0
22
+ }
23
+
24
+ action _nameattr { mark_nat = p }
25
+ action nameattr { @nat = data[mark_nat..p-1] }
26
+ action _valattr { mark_vat = p }
27
+ action valattr { @vat = data[mark_vat..p-1] }
28
+
29
+ action opentag { @flavor = :open }
30
+ action selftag { @flavor = :self }
31
+ action closetag { @flavor = :close }
32
+
33
+ action stopparse {
34
+ @cursor = p;
35
+ fbreak;
36
+ }
37
+
38
+
39
+ Closeout := empty;
40
+
41
+ # words
42
+ # PrefixChar = [\-A-Za-z0-9._?] ;
43
+ NameChar = [\-A-Za-z0-9._:?] ;
44
+ TagName = NameChar+ >_starttag %starttag;
45
+ # Prefix = PrefixChar+ >_prefix %prefix;
46
+
47
+ # Name = Prefix ":" TagName;
48
+
49
+ NameAttr = NameChar+ >_nameattr %nameattr;
50
+ Q1Char = ( "\\\'" | [^'] ) ;
51
+ Q1Attr = Q1Char* >_valattr %valattr;
52
+ Q2Char = ( "\\\"" | [^"] ) ;
53
+ Q2Attr = Q2Char* >_valattr %valattr;
54
+
55
+ Attr = NameAttr space* "=" space* ('"' Q2Attr '"' | "'" Q1Attr "'") space* >_attr %attr;
56
+ Attrs = (space+ Attr* | empty);
57
+
58
+ CloseTrailer = "/}" %selftag;
59
+ OpenTrailer = "}" %opentag;
60
+
61
+ Trailer = (OpenTrailer | CloseTrailer);
62
+
63
+ # OpenOrSelfTag = Name Attrs? Trailer;
64
+ OpenOrSelfTag = TagName Attrs? Trailer;
65
+ # CloseTag = "/" Name space* "}" %closetag;
66
+ CloseTag = "/" TagName space* "}" %closetag;
67
+
68
+ SomeTag = '{' space* (OpenOrSelfTag | CloseTag);
69
+
70
+ main := |*
71
+ SomeTag => {
72
+ tag = {:prefix=>@prefix, :name=>@starttag, :flavor => @flavor, :attrs => @attrs}
73
+ @prefix = nil
74
+ @name = nil
75
+ @flavor = :tasteless
76
+ @attrs = {}
77
+ @nodes << tag << ''
78
+ fbreak;
79
+ };
80
+ any => {
81
+ @nodes.last << data[p]
82
+ @tagstart = p
83
+ };
84
+ *|;
85
+ }%%
86
+
87
+ module Radius
88
+ class SquiggleScanner
89
+ def operate(prefix, data)
90
+ buf = ""
91
+ csel = ""
92
+ @prematch = ''
93
+ @starttag = nil
94
+ @attrs = {}
95
+ @flavor = :tasteless
96
+ @cursor = 0
97
+ @tagstart = 0
98
+ @nodes = ['']
99
+ remainder = data.dup
100
+
101
+ until remainder.length == 0
102
+ p = perform_parse(prefix, remainder)
103
+ remainder = remainder[p..-1]
104
+ end
105
+
106
+ return @nodes
107
+ end
108
+
109
+ private
110
+ def perform_parse(prefix, data)
111
+ stack = []
112
+ p = 0
113
+ ts = 0
114
+ te = 0
115
+ act = 0
116
+ eof = data.length
117
+
118
+ @prefix = prefix
119
+ %% write data;
120
+ %% write init;
121
+ %% write exec;
122
+ return p
123
+ end
124
+ end
125
+ end
@@ -26,5 +26,15 @@ module Radius
26
26
  underscored_string.split('_').each { |part| string << part.capitalize }
27
27
  string
28
28
  end
29
+
30
+ if RUBY_VERSION[0,3] == '1.8'
31
+ def self.array_to_s(c)
32
+ c.to_s
33
+ end
34
+ else
35
+ def self.array_to_s(c)
36
+ c.map{|x| x.is_a?(Array) ? array_to_s(x) : x.to_s }.join
37
+ end
38
+ end
29
39
  end
30
40
  end
@@ -1,14 +1,8 @@
1
- module Radius
2
- module Version
3
- Major = '1'
4
- Minor = '1'
5
- Tiny = '0'
6
-
7
- class << self
8
- def to_s
9
- [Major, Minor, Tiny].join('.')
10
- end
11
- alias :to_str :to_s
1
+ module Radius #:nodoc:
2
+ def self.version
3
+ @version ||= begin
4
+ filename = File.join(File.dirname(__FILE__), '..', '..', 'VERSION')
5
+ IO.read(filename).strip
12
6
  end
13
7
  end
14
8
  end
@@ -0,0 +1,23 @@
1
+ begin
2
+ require 'jeweler'
3
+ Jeweler::Tasks.new do |gem|
4
+ gem.name = "radius-ts"
5
+ gem.summary = "A tag-based templating language for Ruby. (JRuby Extensions)"
6
+ gem.description = "Radius is a powerful tag-based template language for Ruby inspired by the template languages used in MovableType and TextPattern. It uses tags similar to XML, but can be used to generate any form of plain text (HTML, e-mail, etc...). This is likely the last release before merging back upstream to jlong/radius."
7
+ gem.email = "todd@rubidine.com"
8
+ gem.homepage = "http://github.com/xtoddx/radius-ts"
9
+ gem.authors = [
10
+ "John W. Long (me@johnwlong.com)",
11
+ "David Chelimsky (dchelimsky@gmail.com)",
12
+ "Bryce Kerley (bkerley@brycekerley.net)",
13
+ "Todd Willey <todd@rubidine.com>"
14
+ ]
15
+ gem.files = FileList["[A-Z]*", "{bin,lib,tasks,test}/**/*"].exclude("tmp")
16
+ gem.extra_rdoc_files = ['README.rdoc', 'QUICKSTART.rdoc', 'LICENSE', 'CHANGELOG']
17
+ gem.add_development_dependency('RedCloth')
18
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
19
+ end
20
+ Jeweler::GemcutterTasks.new
21
+ rescue LoadError
22
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
23
+ end
data/tasks/rdoc.rake ADDED
@@ -0,0 +1,13 @@
1
+ require 'rake/rdoctask'
2
+ Rake::RDocTask.new do |rdoc|
3
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
4
+
5
+ rdoc.rdoc_dir = 'rdoc'
6
+ rdoc.title = "Radius #{version}"
7
+ rdoc.main = "README.rdoc"
8
+ rdoc.rdoc_files.include('*.rdoc')
9
+ rdoc.rdoc_files.include('LICENSE')
10
+ rdoc.rdoc_files.include('CHANGELOG')
11
+ rdoc.rdoc_files.include('QUICKSTART.rdoc')
12
+ rdoc.rdoc_files.include('lib/**/*.rb')
13
+ end
@@ -0,0 +1,4 @@
1
+ desc "remove Rubinius rbc files"
2
+ task "rubinius:clean" do
3
+ (Dir['**/*.rbc']).each { |f| rm f }
4
+ end
data/tasks/scan.rake CHANGED
@@ -2,11 +2,12 @@ namespace :scan do
2
2
  desc 'Generate the parsers'
3
3
  task 'build' => [
4
4
  'lib/radius/parser/scanner.rb',
5
- 'lib/radius/parser/squiggle_scanner.rb'
5
+ 'lib/radius/parser/squiggle_scanner.rb',
6
+ 'lib/radius/parser/java_scanner.jar'
6
7
  ]
7
8
 
8
9
  desc 'Generate a PDF state graph from the parsers'
9
- task 'graph' => ['doc/scanner.pdf', 'doc/squiggle_scanner.rb']
10
+ task 'graph' => ['doc/scanner.pdf', 'doc/squiggle_scanner.pdf']
10
11
 
11
12
  desc 'turn the scanner.rl file into a ruby file'
12
13
  file 'lib/radius/parser/scanner.rb' => 'lib/radius/parser/scanner.rl' do |t|
@@ -24,6 +25,28 @@ namespace :scan do
24
25
  end
25
26
  end
26
27
 
28
+ desc 'package JavaScanner into a jar file'
29
+ file 'lib/radius/parser/java_scanner.jar' => 'lib/radius/parser/JavaScanner.class' do
30
+ cd 'lib' do
31
+ sh "jar -cf radius/parser/java_scanner.jar radius/parser/*.class"
32
+ end
33
+ end
34
+
35
+ desc 'turn the JavaScanner.java file into a java class file'
36
+ file 'lib/radius/parser/JavaScanner.class' => 'lib/radius/parser/JavaScanner.java' do |t|
37
+ cd 'lib' do
38
+ jruby_path = ENV['JRUBY_HOME'] || '/usr/local/jruby/current'
39
+ sh "javac -cp #{jruby_path}/lib/jruby.jar radius/parser/JavaScanner.java"
40
+ end
41
+ end
42
+
43
+ desc 'turn the JavaScanner.rl file into a java source file'
44
+ file 'lib/radius/parser/JavaScanner.java' => 'lib/radius/parser/JavaScanner.rl' do |t|
45
+ cd 'lib/radius/parser' do
46
+ sh "ragel -J -F1 JavaScanner.rl"
47
+ end
48
+ end
49
+
27
50
  desc 'pdf of the ragel scanner'
28
51
  file 'doc/scanner.pdf' => 'lib/radius/parser/scanner.dot' do |t|
29
52
  cd 'lib/radius/parser' do
data/tasks/test.rake ADDED
@@ -0,0 +1,7 @@
1
+ require 'rake/testtask'
2
+
3
+ Rake::TestTask.new do |t|
4
+ t.libs << "lib" << "test"
5
+ t.test_files = FileList['test/*_test.rb']
6
+ t.verbose = true
7
+ end
@@ -0,0 +1,35 @@
1
+ $: << File.join(File.dirname(__FILE__), '..', 'lib')
2
+ require 'radius'
3
+
4
+ if RUBY_PLATFORM == 'java'
5
+ require 'java'
6
+ require 'radius/parser/jscanner'
7
+ end
8
+
9
+ require 'benchmark'
10
+
11
+ document = <<EOF
12
+ Before it all
13
+ <r:foo>
14
+ Middle Top
15
+ <r:bar />
16
+ Middle Bottom
17
+ </r:foo>
18
+ After it all
19
+ EOF
20
+
21
+ amount = 1000
22
+
23
+ Benchmark.bmbm do |bm|
24
+ bm.report('vanilla') do
25
+ scanner = Radius::Scanner.new(:scanner => Radius::Scanner)
26
+ amount.times { scanner.operate('r', document) }
27
+ end
28
+
29
+ if RUBY_PLATFORM == 'java'
30
+ bm.report('JavaScanner') do
31
+ scanner = Radius::JavaScanner.new(JRuby.runtime)
32
+ amount.times { scanner.operate('r', document) }
33
+ end
34
+ end
35
+ end
data/test/context_test.rb CHANGED
@@ -1,4 +1,4 @@
1
- require File.join(File.dirname(__FILE__), 'test_helper')
1
+ require File.expand_path(File.dirname(__FILE__) + '/test_helper')
2
2
 
3
3
  class RadiusContextTest < Test::Unit::TestCase
4
4
  include RadiusTestHelper
@@ -12,18 +12,49 @@ class MultithreadTest < Test::Unit::TestCase
12
12
  end
13
13
  end
14
14
 
15
- def test_runs_multithreaded
16
- threads = []
17
- 1000.times do |t|
18
- threads << Thread.new do
19
- parser = Radius::Parser.new(@context, :tag_prefix => 'r')
20
- parser.context.globals.thread_id = Thread.current.object_id
21
- expected = "#{Thread.current.object_id} / #{parser.context.globals.object_id}"
22
- actual = parser.parse('<r:thread />')
23
- assert_equal expected, actual
15
+ if RUBY_PLATFORM == 'java'
16
+ require 'java'
17
+ def test_runs_multithreaded
18
+ lock = java.lang.String.new("lock")
19
+ threads = []
20
+ 1000.times do |t|
21
+ thread = Thread.new do
22
+ parser = Radius::Parser.new(@context, :tag_prefix => 'r')
23
+ parser.context.globals.thread_id = Thread.current.object_id
24
+ expected = "#{Thread.current.object_id} / "+
25
+ "#{parser.context.globals.object_id}"
26
+ actual = parser.parse('<r:thread />')
27
+ assert_equal expected, actual
28
+ end
29
+ lock.synchronized do
30
+ threads << thread
31
+ end
32
+ end
33
+ lock.synchronized do
34
+ threads.each{|t| t.join }
35
+ end
36
+ end
37
+ else
38
+ def test_runs_multithreaded
39
+ threads = []
40
+ mute = Mutex.new
41
+ 1000.times do |t|
42
+ thread = Thread.new do
43
+ parser = Radius::Parser.new(@context, :tag_prefix => 'r')
44
+ parser.context.globals.thread_id = Thread.current.object_id
45
+ expected = "#{Thread.current.object_id} / "+
46
+ "#{parser.context.globals.object_id}"
47
+ actual = parser.parse('<r:thread />')
48
+ assert_equal expected, actual
49
+ end
50
+ mute.synchronize do
51
+ threads << thread
52
+ end
53
+ end
54
+ mute.synchronize do
55
+ threads.each{|t| t.join }
24
56
  end
25
57
  end
26
- threads.each{|t| t.join }
27
58
  end
28
59
 
29
60
  end
data/test/parser_test.rb CHANGED
@@ -1,4 +1,4 @@
1
- require File.join(File.dirname(__FILE__), 'test_helper')
1
+ require File.expand_path(File.dirname(__FILE__) + '/test_helper')
2
2
 
3
3
  class RadiusParserTest < Test::Unit::TestCase
4
4
  include RadiusTestHelper
@@ -261,6 +261,11 @@ class RadiusParserTest < Test::Unit::TestCase
261
261
  assert_equal 'bar', @context.globals.foo
262
262
  end
263
263
 
264
+ def test_parse_with_other_namespaces
265
+ @parser = Radius::Parser.new(@context, :tag_prefix => 'r')
266
+ assert_equal "<fb:test>hello world</fb:test>", @parser.parse("<fb:test>hello world</fb:test>")
267
+ end
268
+
264
269
  protected
265
270
 
266
271
  def assert_parse_output(output, input, message = nil)
@@ -1,4 +1,4 @@
1
- require File.join(File.dirname(__FILE__), 'test_helper')
1
+ require File.expand_path(File.dirname(__FILE__) + '/test_helper')
2
2
 
3
3
  class QuickstartTest < Test::Unit::TestCase
4
4
 
@@ -20,7 +20,7 @@ class QuickstartTest < Test::Unit::TestCase
20
20
  RedCloth.new(contents).to_html
21
21
  end
22
22
  parser = Radius::Parser.new(context)
23
- assert_equal "<h1>Hello <b>World</b>!</h1>", parser.parse('<radius:textile>h1. Hello **World**!</radius:textile>')
23
+ assert_equal "<p>Hello <b>World</b>!</p>", parser.parse('<radius:textile>Hello **World**!</radius:textile>')
24
24
  end
25
25
 
26
26
  def test_nested_example
@@ -10,7 +10,7 @@ class RadiusSquiggleTest < Test::Unit::TestCase
10
10
  end
11
11
 
12
12
  def test_sane_scanner_default
13
- assert_kind_of Radius::Scanner, Radius::Parser.new.scanner
13
+ assert !Radius::Parser.new.scanner.is_a?(Radius::SquiggleScanner)
14
14
  end
15
15
 
16
16
  def test_initialize_with_params
@@ -235,6 +235,11 @@ class RadiusSquiggleTest < Test::Unit::TestCase
235
235
  assert_equal 'bar', @context.globals.foo
236
236
  end
237
237
 
238
+ def test_parse_with_other_namespaces
239
+ @parser = Radius::Parser.new(@context, :tag_prefix => 'r')
240
+ assert_equal "{fb:test}hello world{/fb:test}", @parser.parse("{fb:test}hello world{/fb:test}")
241
+ end
242
+
238
243
  protected
239
244
 
240
245
  def assert_parse_output(output, input, message = nil)
data/test/test_helper.rb CHANGED
@@ -1,3 +1,4 @@
1
+ require 'rubygems'
1
2
  require 'timeout'
2
3
 
3
4
  unless defined? RADIUS_LIB
@@ -15,9 +16,12 @@ unless defined? RADIUS_LIB
15
16
  Radius::Context.new do |c|
16
17
  c.define_tag("reverse" ) { |tag| tag.expand.reverse }
17
18
  c.define_tag("capitalize") { |tag| tag.expand.upcase }
18
- c.define_tag("attr" ) { |tag| tag.attr.inspect }
19
19
  c.define_tag("echo" ) { |tag| tag.attr['value'] }
20
20
  c.define_tag("wrap" ) { |tag| "[#{tag.expand}]" }
21
+ c.define_tag("attr") do |tag|
22
+ kv = tag.attr.keys.sort.collect{|k| "#{k.inspect}=>#{tag[k].inspect}"}
23
+ "{#{kv.join(', ')}}"
24
+ end
21
25
  end
22
26
  end
23
27