import sinatra-decompile
This commit is contained in:
parent
07a649ab6d
commit
f5e015894d
|
@ -0,0 +1,61 @@
|
||||||
|
require 'sinatra/base'
|
||||||
|
require 'backports'
|
||||||
|
|
||||||
|
module Sinatra
|
||||||
|
##
|
||||||
|
# Can be used as extension or stand-alone:
|
||||||
|
#
|
||||||
|
# Sinatra::Decompile.decompile(...)
|
||||||
|
module Decompile
|
||||||
|
extend self
|
||||||
|
|
||||||
|
##
|
||||||
|
# Regenerates a string pattern for a given route
|
||||||
|
#
|
||||||
|
# Example:
|
||||||
|
#
|
||||||
|
# class Sinatra::Application
|
||||||
|
# routes.each do |verb, list|
|
||||||
|
# puts "#{verb}:"
|
||||||
|
# list.each do |data|
|
||||||
|
# puts "\t" << decompile(data)
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# Will return the internal Regexp if unable to reconstruct the pattern,
|
||||||
|
# which likely indicates that a Regexp was used in the first place.
|
||||||
|
#
|
||||||
|
# You can also use this to check whether you could actually use a string
|
||||||
|
# pattern instead of your regexp:
|
||||||
|
#
|
||||||
|
# decompile /^/foo$/ # => '/foo'
|
||||||
|
def decompile(pattern, keys = nil, *)
|
||||||
|
# Everything in here is basically just the reverse of
|
||||||
|
# Sinatra::Base#compile
|
||||||
|
pattern, keys = pattern if pattern.respond_to? :to_ary
|
||||||
|
keys, str = keys.try(:dup), pattern.inspect
|
||||||
|
return pattern unless str.start_with? '/' and str.end_with? '/'
|
||||||
|
str.gsub! /^\/\^?|\$?\/$/, ''
|
||||||
|
return pattern if str =~ /^[\.\+]/
|
||||||
|
str.gsub! /\([^\(]*\)/ do |part|
|
||||||
|
case part
|
||||||
|
when '(.*?)'
|
||||||
|
return pattern if keys.shift != 'splat'
|
||||||
|
'*'
|
||||||
|
when '([^\/?#]+)'
|
||||||
|
return pattern if keys.empty?
|
||||||
|
":" << keys.shift
|
||||||
|
else
|
||||||
|
return pattern
|
||||||
|
end
|
||||||
|
end
|
||||||
|
str.gsub /(.)([\.\+\(\)\/])/ do
|
||||||
|
return pattern if $1 != "\\"
|
||||||
|
$2
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
register Decompile
|
||||||
|
end
|
|
@ -0,0 +1,42 @@
|
||||||
|
require 'backports'
|
||||||
|
require_relative 'spec_helper'
|
||||||
|
|
||||||
|
RSpec::Matchers.define :decompile do |path|
|
||||||
|
match do |app|
|
||||||
|
@compiled, @keys = app.send :compile, path
|
||||||
|
@decompiled = app.decompile(@compiled, @keys)
|
||||||
|
@decompiled.should == path
|
||||||
|
end
|
||||||
|
|
||||||
|
failure_message_for_should do |app|
|
||||||
|
values = [app, @compiled, @keys, path, @decompiled].map(&:inspect)
|
||||||
|
"expected %s to decompile %s with %s to %s, but was %s" % values
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe Sinatra::Decompile do
|
||||||
|
subject { Sinatra::Application }
|
||||||
|
it { should decompile("") }
|
||||||
|
it { should decompile("/") }
|
||||||
|
it { should decompile("/?") }
|
||||||
|
it { should decompile("/foo") }
|
||||||
|
it { should decompile("/:name") }
|
||||||
|
it { should decompile("/:name?") }
|
||||||
|
it { should decompile("/:foo/:bar") }
|
||||||
|
it { should decompile("/page/:id/edit") }
|
||||||
|
it { should decompile("/hello/*") }
|
||||||
|
it { should decompile("/*/foo/*") }
|
||||||
|
it { should decompile("*") }
|
||||||
|
it { should decompile(":name.:format") }
|
||||||
|
it { should decompile(/./) }
|
||||||
|
it { should decompile(/f(oo)/) }
|
||||||
|
it { should decompile(/ba+r/) }
|
||||||
|
|
||||||
|
it 'just returns strings' do
|
||||||
|
subject.decompile('/foo').should == '/foo'
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'just decompile simple regexps without keys' do
|
||||||
|
subject.decompile(%r{/foo}).should == '/foo'
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,11 @@
|
||||||
|
require 'forwardable'
|
||||||
|
|
||||||
|
module TestHelpers
|
||||||
|
end
|
||||||
|
|
||||||
|
require 'sinatra/contrib'
|
||||||
|
|
||||||
|
RSpec.configure do |config|
|
||||||
|
config.expect_with :rspec, :stdlib
|
||||||
|
config.include Sinatra::TestHelpers
|
||||||
|
end
|
Loading…
Reference in New Issue