staticmatic2 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +12 -0
- data/Gemfile.lock +27 -0
- data/LICENSE +20 -0
- data/README.markdown +107 -0
- data/Rakefile +45 -0
- data/VERSION.yml +5 -0
- data/bin/staticmatic +140 -0
- data/lib/staticmatic.rb +25 -0
- data/lib/staticmatic/base.rb +123 -0
- data/lib/staticmatic/compass.rb +5 -0
- data/lib/staticmatic/compass/app_integration.rb +18 -0
- data/lib/staticmatic/compass/configuration_defaults.rb +44 -0
- data/lib/staticmatic/compass/installer.rb +15 -0
- data/lib/staticmatic/configuration.rb +20 -0
- data/lib/staticmatic/deployers/aws-s3.rb +71 -0
- data/lib/staticmatic/deployers/config/amazon.yml +7 -0
- data/lib/staticmatic/error.rb +17 -0
- data/lib/staticmatic/helpers.rb +12 -0
- data/lib/staticmatic/helpers/assets_helper.rb +116 -0
- data/lib/staticmatic/helpers/current_path_helper.rb +22 -0
- data/lib/staticmatic/helpers/form_helper.rb +23 -0
- data/lib/staticmatic/helpers/render_helper.rb +13 -0
- data/lib/staticmatic/helpers/tag_helper.rb +35 -0
- data/lib/staticmatic/helpers/url_helper.rb +59 -0
- data/lib/staticmatic/mixins/build.rb +77 -0
- data/lib/staticmatic/mixins/helpers.rb +15 -0
- data/lib/staticmatic/mixins/render.rb +153 -0
- data/lib/staticmatic/mixins/rescue.rb +12 -0
- data/lib/staticmatic/mixins/server.rb +7 -0
- data/lib/staticmatic/mixins/setup.rb +16 -0
- data/lib/staticmatic/server.rb +86 -0
- data/lib/staticmatic/template_error.rb +44 -0
- data/lib/staticmatic/templates/rescues/default.haml +7 -0
- data/lib/staticmatic/templates/rescues/template.haml +18 -0
- data/spec/base_spec.rb +13 -0
- data/spec/compass_integration_spec.rb +27 -0
- data/spec/helpers/asset_helper_spec.rb +43 -0
- data/spec/helpers/custom_helper_spec.rb +18 -0
- data/spec/render_spec.rb +44 -0
- data/spec/rescue_spec.rb +36 -0
- data/spec/sandbox/test_site/config/compass.rb +1 -0
- data/spec/sandbox/test_site/config/site.rb +0 -0
- data/spec/sandbox/test_site/src/helpers/application_helper.rb +5 -0
- data/spec/sandbox/test_site/src/layouts/alternate_layout.haml +3 -0
- data/spec/sandbox/test_site/src/layouts/default.haml +7 -0
- data/spec/sandbox/test_site/src/layouts/projects.haml +1 -0
- data/spec/sandbox/test_site/src/pages/hello_world.erb +1 -0
- data/spec/sandbox/test_site/src/pages/index.haml +5 -0
- data/spec/sandbox/test_site/src/pages/layout_test.haml +2 -0
- data/spec/sandbox/test_site/src/pages/page_one.haml +3 -0
- data/spec/sandbox/test_site/src/pages/page_two.haml +2 -0
- data/spec/sandbox/test_site/src/pages/page_with_error.haml +5 -0
- data/spec/sandbox/test_site/src/pages/page_with_partial_error.haml +3 -0
- data/spec/sandbox/test_site/src/partials/menu.haml +1 -0
- data/spec/sandbox/test_site/src/partials/partial_with_error.haml +1 -0
- data/spec/sandbox/test_site/src/stylesheets/application.sass +5 -0
- data/spec/sandbox/test_site/src/stylesheets/css_with_error.sass +5 -0
- data/spec/sandbox/test_site/src/stylesheets/nested/a_nested_stylesheet.sass +0 -0
- data/spec/sandbox/test_site/src/stylesheets/partials/_forms.sass +2 -0
- data/spec/sandbox/test_site/src/stylesheets/sassy.scss +12 -0
- data/spec/server_spec.rb +11 -0
- data/spec/setup_spec.rb +22 -0
- data/spec/spec_helper.rb +14 -0
- data/spec/template_error_spec.rb +23 -0
- data/staticmatic.gemspec +158 -0
- data/website/Gemfile +1 -0
- data/website/config/site.rb +17 -0
- data/website/site/docs/compass_integration.html +70 -0
- data/website/site/docs/getting_started.html +49 -0
- data/website/site/docs/helpers.html +22 -0
- data/website/site/images/bycurve21.gif +0 -0
- data/website/site/images/curve21.jpg +0 -0
- data/website/site/images/homepage-build.jpg +0 -0
- data/website/site/images/homepage-previewing.jpg +0 -0
- data/website/site/images/homepage-templating.jpg +0 -0
- data/website/site/stylesheets/ie.css +5 -0
- data/website/site/stylesheets/print.css +372 -0
- data/website/site/stylesheets/screen.css +488 -0
- data/website/src/helpers/content_helper.rb +10 -0
- data/website/src/layouts/default.haml +15 -0
- data/website/src/pages/development.haml +9 -0
- data/website/src/pages/docs/_menu.haml +4 -0
- data/website/src/pages/docs/_requires_prerelease.haml +4 -0
- data/website/src/pages/docs/compass_integration.haml +54 -0
- data/website/src/pages/docs/getting_started.haml +31 -0
- data/website/src/pages/docs/helpers.haml +1 -0
- data/website/src/pages/index.haml +27 -0
- data/website/src/stylesheets/_base.scss +43 -0
- data/website/src/stylesheets/_defaults.scss +260 -0
- data/website/src/stylesheets/ie.scss +10 -0
- data/website/src/stylesheets/print.scss +33 -0
- data/website/src/stylesheets/screen.scss +73 -0
- metadata +238 -0
@@ -0,0 +1,18 @@
|
|
1
|
+
|
2
|
+
module Compass
|
3
|
+
module AppIntegration
|
4
|
+
module Staticmatic
|
5
|
+
|
6
|
+
extend self
|
7
|
+
|
8
|
+
def installer(*args)
|
9
|
+
Installer.new(*args)
|
10
|
+
end
|
11
|
+
|
12
|
+
def configuration
|
13
|
+
Compass::Configuration::Data.new('staticmatic').extend(ConfigurationDefaults)
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Compass
|
2
|
+
module AppIntegration
|
3
|
+
module Staticmatic
|
4
|
+
module ConfigurationDefaults
|
5
|
+
def project_type_without_default
|
6
|
+
:staticmatic
|
7
|
+
end
|
8
|
+
|
9
|
+
def http_path
|
10
|
+
"/"
|
11
|
+
end
|
12
|
+
|
13
|
+
def sass_dir_without_default
|
14
|
+
"src/stylesheets"
|
15
|
+
end
|
16
|
+
|
17
|
+
def javascripts_dir_without_default
|
18
|
+
"site/javascripts"
|
19
|
+
end
|
20
|
+
|
21
|
+
def css_dir_without_default
|
22
|
+
"site/stylesheets"
|
23
|
+
end
|
24
|
+
|
25
|
+
def images_dir_without_default
|
26
|
+
"site/images"
|
27
|
+
end
|
28
|
+
|
29
|
+
def default_http_images_path
|
30
|
+
"images"
|
31
|
+
end
|
32
|
+
|
33
|
+
def default_http_javascripts_path
|
34
|
+
"javascripts"
|
35
|
+
end
|
36
|
+
|
37
|
+
def default_cache_dir
|
38
|
+
".sass-cache"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Compass
|
2
|
+
module AppIntegration
|
3
|
+
module Staticmatic
|
4
|
+
class Installer < Compass::Installers::ManifestInstaller
|
5
|
+
def completed_configuration
|
6
|
+
nil
|
7
|
+
end
|
8
|
+
|
9
|
+
def finalize(options = {})
|
10
|
+
puts manifest.welcome_message if manifest.welcome_message
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module StaticMatic
|
2
|
+
class Configuration
|
3
|
+
attr_accessor :preview_server_port
|
4
|
+
|
5
|
+
attr_accessor :preview_server_host
|
6
|
+
|
7
|
+
attr_accessor :use_extensions_for_page_links
|
8
|
+
attr_accessor :sass_options
|
9
|
+
attr_accessor :haml_options
|
10
|
+
attr_accessor :coffee_options
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
self.preview_server_port = 3000
|
14
|
+
self.use_extensions_for_page_links = true
|
15
|
+
self.sass_options = {}
|
16
|
+
self.haml_options = {}
|
17
|
+
self.coffee_options = ''
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'aws/s3'
|
2
|
+
require 'yaml'
|
3
|
+
|
4
|
+
class StaticExe < Thor
|
5
|
+
|
6
|
+
desc "s3_deploy DIRECTORY", "Deploys your static website an Amazon's S3 bucket"
|
7
|
+
method_option :env, :type => :string, :aliases => "-e"
|
8
|
+
method_option :skip_build, :type => :boolean, :aliases => "-k"
|
9
|
+
def s3_deploy(directory = '.')
|
10
|
+
return if needs_setup? directory
|
11
|
+
|
12
|
+
invoke :build, directory unless options[:skip_build]
|
13
|
+
|
14
|
+
if Dir[site_path(directory,'*')].empty?
|
15
|
+
say 'Your build/ folder is empty', :red
|
16
|
+
say 'Nothing to do.'
|
17
|
+
return
|
18
|
+
end
|
19
|
+
|
20
|
+
say 'Uploading to Amazon S3...', :cyan
|
21
|
+
say 'Establishing connection to Amazon S3...'
|
22
|
+
amazon_config = YAML::load File.read(amazon_config_path directory)
|
23
|
+
AWS::S3::Base.establish_connection!(amazon_config['AccessKeys'])
|
24
|
+
|
25
|
+
env = options[:env] || 'development'
|
26
|
+
bucket_name = amazon_config['Buckets'][env]
|
27
|
+
|
28
|
+
say "Grabbing #{env} bucket '#{bucket_name}'"
|
29
|
+
buckets = AWS::S3::Service.buckets
|
30
|
+
unless buckets.map {|b| b.name}.include? bucket_name
|
31
|
+
say 'The bucket ', :red
|
32
|
+
say "'#{bucket_name}' "
|
33
|
+
say 'does not exist!', :red
|
34
|
+
say 'Nothing to do.'
|
35
|
+
return
|
36
|
+
end
|
37
|
+
|
38
|
+
Dir[site_path(directory,'*')].each do |file|
|
39
|
+
contents = File.read file
|
40
|
+
s3path = file.sub(%r{^\./build/},'')
|
41
|
+
|
42
|
+
say " upload ", :cyan; say s3path
|
43
|
+
AWS::S3::S3Object.store(s3path, contents, bucket_name, :access => :public_read)
|
44
|
+
end
|
45
|
+
say 'Done.'
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def amazon_config_path(directory)
|
51
|
+
File.join(directory, 'config','amazon.yml')
|
52
|
+
end
|
53
|
+
|
54
|
+
def needs_setup?(directory)
|
55
|
+
config_file = amazon_config_path(directory)
|
56
|
+
|
57
|
+
unless File.exists? config_file
|
58
|
+
say 'You need an Amazon S3 config file.', :red
|
59
|
+
response = ask 'Would you like to generate one now? [Y/n]'
|
60
|
+
|
61
|
+
if response == '' || response.downcase == 'y'
|
62
|
+
copy_file lib_path('deployers/config/amazon.yml'), config_file
|
63
|
+
say 'Done.'
|
64
|
+
say 'Edit this config file to specify your Amazon S3 access keys, ' +
|
65
|
+
'and then try again.'
|
66
|
+
say 'For more information, visit http://aws.amazon.com/s3/'
|
67
|
+
end
|
68
|
+
return true
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module StaticMatic
|
2
|
+
class Error < StandardError
|
3
|
+
attr_reader :line
|
4
|
+
|
5
|
+
attr_reader :filename
|
6
|
+
|
7
|
+
def initialize(lineno, filename, message)
|
8
|
+
@line = lineno
|
9
|
+
@filename = filename
|
10
|
+
@message = message
|
11
|
+
end
|
12
|
+
|
13
|
+
def message
|
14
|
+
"#{@filename}, line #{@line}: #{@message}"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
["assets", "form", "current_path", "render", "tag", "url"].each do |helper|
|
2
|
+
require File.join(File.dirname(__FILE__), "helpers", "#{helper}_helper")
|
3
|
+
end
|
4
|
+
|
5
|
+
module StaticMatic::Helpers
|
6
|
+
include TagHelper
|
7
|
+
include UrlHelper
|
8
|
+
include AssetsHelper
|
9
|
+
include FormHelper
|
10
|
+
include RenderHelper
|
11
|
+
include CurrentPathHelper
|
12
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
module StaticMatic
|
2
|
+
module Helpers
|
3
|
+
module AssetsHelper
|
4
|
+
self.extend self
|
5
|
+
|
6
|
+
# Generates links to all stylesheets in the source directory
|
7
|
+
# = stylesheets
|
8
|
+
# or specific stylesheets in a specific order
|
9
|
+
# = stylesheets :reset, :application
|
10
|
+
# Can also pass options hash in at the end so you can specify :media => :print
|
11
|
+
def stylesheets(*params)
|
12
|
+
options = if params.last.is_a? Hash; params.pop else {} end # clean up
|
13
|
+
|
14
|
+
options[:media] = 'all' unless options.has_key?(:media)
|
15
|
+
options[:rel] = 'stylesheet'; options[:type] = 'text/css'
|
16
|
+
|
17
|
+
src_files = @staticmatic.src_file_paths('sass','scss','css')
|
18
|
+
output = ""
|
19
|
+
|
20
|
+
if params.length == 0
|
21
|
+
# no specified files; include them all!
|
22
|
+
src_files.each {|path| output << format_output(:link,path,options) }
|
23
|
+
else
|
24
|
+
# specific files requested and in a specific order
|
25
|
+
params.each do |file|
|
26
|
+
|
27
|
+
if file.to_s.match %r{^https?://}
|
28
|
+
output << format_output(:link,file,options)
|
29
|
+
else
|
30
|
+
idx = src_files.index do |src|
|
31
|
+
%w{sass scss css}.map {|t| src.match /#{file}\.#{t}$/ }.any?
|
32
|
+
end
|
33
|
+
output << format_output(:link,src_files[idx],options) unless idx.nil?
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
output
|
38
|
+
end
|
39
|
+
|
40
|
+
# Generate javascript source tags for the specified files
|
41
|
+
#
|
42
|
+
# javascripts('test') -> <script language="javascript" src="javascripts/test.js"></script>
|
43
|
+
#
|
44
|
+
def javascripts(*files)
|
45
|
+
options = if files.last.is_a? Hash; files.pop else {} end # clean up
|
46
|
+
|
47
|
+
options[:language] = 'javascript'
|
48
|
+
options[:type] = 'text/javascript'
|
49
|
+
|
50
|
+
src_files = @staticmatic.src_file_paths('js','coffee')
|
51
|
+
output = ""
|
52
|
+
|
53
|
+
files.each do |path|
|
54
|
+
puts "path: #{path}"
|
55
|
+
if path.to_s.match %r{^https?://}
|
56
|
+
output << format_output(:script,path,options)
|
57
|
+
else
|
58
|
+
idx = src_files.index do |src|
|
59
|
+
%w{coffee js}.map {|t| src.match /#{path.to_s}\.#{t}$/ }.any?
|
60
|
+
end
|
61
|
+
output << format_output(:script,src_files[idx],options) unless idx.nil?
|
62
|
+
end
|
63
|
+
end
|
64
|
+
output
|
65
|
+
end
|
66
|
+
|
67
|
+
# Generates an image tag always relative to the current page unless absolute path or http url specified.
|
68
|
+
#
|
69
|
+
# img('test_image.gif') -> <img src="/images/test_image.gif" alt="Test image"/>
|
70
|
+
# img('contact/test_image.gif') -> <img src="/images/contact/test_image.gif" alt="Test image"/>
|
71
|
+
# img('http://localhost/test_image.gif') -> <img src="http://localhost/test_image.gif" alt="Test image"/>
|
72
|
+
def img(name, options = {})
|
73
|
+
options[:src] = name.match(%r{^((\.\.?)?/|https?://)}) ? name : "#{current_page_relative_path}images/#{name}"
|
74
|
+
options[:alt] ||= name.split('/').last.split('.').first.capitalize.gsub(/_|-/, ' ')
|
75
|
+
tag :img, options
|
76
|
+
end
|
77
|
+
|
78
|
+
def format_output(tag_type,path,options)
|
79
|
+
external_url = !!path.match(%r{^https?://})
|
80
|
+
|
81
|
+
if external_url
|
82
|
+
src = path
|
83
|
+
else
|
84
|
+
filename_without_extension = File.basename(path).chomp(File.extname(path))
|
85
|
+
|
86
|
+
path = path.gsub(/#{@staticmatic.src_dir}/, "").
|
87
|
+
gsub(/#{@staticmatic.site_dir}/, "").
|
88
|
+
gsub(/#{filename_without_extension}\.(sass|scss|css|js|coffee)/, "")
|
89
|
+
|
90
|
+
src = File.join(current_page_relative_path, path, "#{filename_without_extension}")
|
91
|
+
end
|
92
|
+
|
93
|
+
if tag_type == :link
|
94
|
+
src += '.css' if !external_url
|
95
|
+
options[:href] = qstring(src, options[:qstring]); options.delete :qstring
|
96
|
+
tag(tag_type,options)
|
97
|
+
elsif tag_type == :script
|
98
|
+
src += '.js' if !external_url
|
99
|
+
options[:src] = qstring(src, options[:qstring]); options.delete :qstring
|
100
|
+
tag(tag_type,options) { '' }
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
|
105
|
+
# Prepares a query string based on the given qstr.
|
106
|
+
# If qstr is true, it generates a query string based on the current time.
|
107
|
+
# If qstr is a string, it uses it as the query string itself.
|
108
|
+
#
|
109
|
+
def qstring(src,qstr)
|
110
|
+
src += '?_=' + Time.now.to_i.to_s if qstr == true
|
111
|
+
src += '?_=' + qstr if qstr.is_a? String
|
112
|
+
src
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module StaticMatic
|
2
|
+
module Helpers
|
3
|
+
module CurrentPathHelper
|
4
|
+
self.extend self
|
5
|
+
|
6
|
+
def current_page
|
7
|
+
@staticmatic.current_page
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def current_page_relative_path(current_path = nil)
|
13
|
+
if current_path.nil? || current_path.match(/^((\.\.?)?\/|\#|.+?\:)/) == nil
|
14
|
+
current_page_depth = current_page.split('/').length - 2;
|
15
|
+
(current_page_depth > 0) ? ([ '..' ] * current_page_depth).join('/') + '/' : ''
|
16
|
+
else
|
17
|
+
''
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
|
2
|
+
module StaticMatic
|
3
|
+
module Helpers
|
4
|
+
module FormHelper
|
5
|
+
self.extend self
|
6
|
+
|
7
|
+
# Generates a form text field
|
8
|
+
#
|
9
|
+
def text_field(name, value, options = {})
|
10
|
+
options.merge!(:type => "text", :name => name, :value => value)
|
11
|
+
tag(:input, options)
|
12
|
+
end
|
13
|
+
|
14
|
+
|
15
|
+
# Generate a form textarea
|
16
|
+
#
|
17
|
+
def text_area(name, value, options = {})
|
18
|
+
options.merge!(:name => name)
|
19
|
+
tag(:textarea, options) { value }
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module StaticMatic
|
2
|
+
module Helpers
|
3
|
+
module TagHelper
|
4
|
+
self.extend self
|
5
|
+
|
6
|
+
# Generates HTML tags:
|
7
|
+
#
|
8
|
+
# tag(:br) -> <br/>
|
9
|
+
# tag(:a, :href => 'test.html') { "Test" } -> <a href="test.html">Test</a>
|
10
|
+
#
|
11
|
+
def tag(name, options = {}, &block)
|
12
|
+
options[:id] ||= options[:name] if options[:name]
|
13
|
+
output = "<#{name}"
|
14
|
+
options.keys.sort { |a, b| a.to_s <=> b.to_s }.each do |key|
|
15
|
+
output << " #{key}=\"#{options[key]}\"" if options[key]
|
16
|
+
end
|
17
|
+
|
18
|
+
if block_given?
|
19
|
+
output << ">"
|
20
|
+
output << yield
|
21
|
+
output << "</#{name}>"
|
22
|
+
else
|
23
|
+
format = @staticmatic.configuration.haml_options[:format]
|
24
|
+
|
25
|
+
if format.nil? || format == :xhtml
|
26
|
+
output << "/>"
|
27
|
+
else
|
28
|
+
output << ">"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
output
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module StaticMatic
|
2
|
+
module Helpers
|
3
|
+
module UrlHelper
|
4
|
+
self.extend self
|
5
|
+
|
6
|
+
# Generate an HTML link
|
7
|
+
#
|
8
|
+
# If only the title is passed, it will automatically
|
9
|
+
# create a link from this value:
|
10
|
+
#
|
11
|
+
# link('Test') -> <a href="test.html">Test</a>
|
12
|
+
#
|
13
|
+
def link(title, href = "", options = {})
|
14
|
+
if href.is_a?(Hash)
|
15
|
+
options = href
|
16
|
+
href = ""
|
17
|
+
end
|
18
|
+
|
19
|
+
if href.nil? || href.strip.length < 1
|
20
|
+
path_prefix = ''
|
21
|
+
if title.match(/^(\.\.?)?\//)
|
22
|
+
# starts with relative path so strip it off and prepend it to the urlified title
|
23
|
+
path_prefix_match = title.match(/^[^\s]*\//)
|
24
|
+
path_prefix = path_prefix_match[0] if path_prefix_match
|
25
|
+
title = title[path_prefix.length, title.length]
|
26
|
+
end
|
27
|
+
href = path_prefix + urlify(title) + ".html"
|
28
|
+
end
|
29
|
+
|
30
|
+
options[:href] = "#{current_page_relative_path(href)}#{href}"
|
31
|
+
|
32
|
+
local_page = (options[:href].match(/^(\#|.+?\:)/) == nil)
|
33
|
+
unless @staticmatic.configuration.use_extensions_for_page_links || !local_page
|
34
|
+
options[:href].chomp!(".html")
|
35
|
+
options[:href].chomp!("index") if options[:href][-5, 5] == 'index'
|
36
|
+
end
|
37
|
+
|
38
|
+
tag(:a, options) { title }
|
39
|
+
end
|
40
|
+
alias link_to link
|
41
|
+
|
42
|
+
# Generates a URL friendly string from the value passed:
|
43
|
+
#
|
44
|
+
# "We love Haml" -> "we_love_haml"
|
45
|
+
# "Elf & Ham" -> "elf_and_ham"
|
46
|
+
# "Stephen's gem" -> "stephens_gem"
|
47
|
+
#
|
48
|
+
def urlify(string)
|
49
|
+
string.tr(" ", "_").
|
50
|
+
sub("&", "and").
|
51
|
+
sub("@", "at").
|
52
|
+
tr("^A-Za-z0-9_", "").
|
53
|
+
sub(/_{2,}/, "_").
|
54
|
+
downcase
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|