sitemap_generator 2.2.1 → 3.0.0
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.
- data/Gemfile +9 -24
- data/Gemfile.lock +23 -58
- data/README.md +56 -75
- data/Rakefile +29 -117
- data/VERSION +1 -1
- data/lib/sitemap_generator.rb +24 -8
- data/lib/sitemap_generator/application.rb +31 -4
- data/lib/sitemap_generator/builder.rb +0 -6
- data/lib/sitemap_generator/builder/sitemap_file.rb +16 -6
- data/lib/sitemap_generator/builder/sitemap_index_file.rb +4 -3
- data/lib/sitemap_generator/builder/sitemap_index_url.rb +1 -1
- data/lib/sitemap_generator/builder/sitemap_url.rb +6 -8
- data/lib/sitemap_generator/core_ext.rb +3 -0
- data/lib/sitemap_generator/core_ext/big_decimal.rb +45 -0
- data/lib/sitemap_generator/core_ext/numeric.rb +48 -0
- data/lib/sitemap_generator/helpers/number_helper.rb +237 -0
- data/lib/sitemap_generator/interpreter.rb +1 -1
- data/lib/sitemap_generator/link_set.rb +39 -18
- data/lib/sitemap_generator/railtie.rb +2 -2
- data/lib/sitemap_generator/sitemap_namer.rb +1 -1
- data/lib/sitemap_generator/tasks.rb +53 -1
- data/lib/sitemap_generator/utilities.rb +107 -1
- data/lib/tasks/sitemap_generator_tasks.rake +1 -0
- data/spec/blueprint.rb +15 -0
- data/spec/files/sitemap.create.rb +12 -0
- data/spec/files/sitemap.deprecated.rb +13 -0
- data/spec/files/sitemap.groups.rb +37 -0
- data/spec/sitemap_generator/application_spec.rb +69 -0
- data/spec/sitemap_generator/builder/sitemap_file_spec.rb +77 -0
- data/spec/sitemap_generator/builder/sitemap_index_file_spec.rb +38 -0
- data/spec/sitemap_generator/builder/sitemap_index_url_spec.rb +16 -0
- data/spec/sitemap_generator/builder/sitemap_url_spec.rb +152 -0
- data/spec/sitemap_generator/core_ext/bigdecimal_spec.rb +20 -0
- data/spec/sitemap_generator/core_ext/numeric_spec.rb +43 -0
- data/spec/sitemap_generator/geo_sitemap_spec.rb +30 -0
- data/spec/sitemap_generator/helpers/number_helper_spec.rb +191 -0
- data/spec/sitemap_generator/interpreter_spec.rb +24 -0
- data/spec/sitemap_generator/link_set_spec.rb +606 -0
- data/spec/sitemap_generator/news_sitemap_spec.rb +42 -0
- data/spec/sitemap_generator/sitemap_generator_spec.rb +232 -0
- data/spec/sitemap_generator/sitemap_groups_spec.rb +133 -0
- data/spec/sitemap_generator/sitemap_location_spec.rb +124 -0
- data/spec/sitemap_generator/sitemap_namer_spec.rb +61 -0
- data/spec/sitemap_generator/templates_spec.rb +24 -0
- data/spec/sitemap_generator/utilities/existence_spec.rb +26 -0
- data/spec/sitemap_generator/utilities/hash_spec.rb +57 -0
- data/spec/sitemap_generator/utilities/rounding_spec.rb +31 -0
- data/spec/sitemap_generator/utilities_spec.rb +50 -0
- data/spec/sitemap_generator/video_sitemap_spec.rb +103 -0
- data/spec/spec_helper.rb +20 -0
- data/spec/support/file_macros.rb +39 -0
- data/spec/support/schemas/siteindex.xsd +73 -0
- data/spec/support/schemas/sitemap-geo.xsd +41 -0
- data/spec/support/schemas/sitemap-news.xsd +159 -0
- data/spec/support/schemas/sitemap-video.xsd +409 -0
- data/spec/support/schemas/sitemap.xsd +115 -0
- data/spec/support/xml_macros.rb +55 -0
- metadata +141 -122
- data/tasks/sitemap_generator_tasks.rake +0 -43
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
3.0.0
|
data/lib/sitemap_generator.rb
CHANGED
@@ -6,24 +6,25 @@ require 'sitemap_generator/utilities'
|
|
6
6
|
require 'sitemap_generator/application'
|
7
7
|
require 'sitemap_generator/adapters'
|
8
8
|
require 'sitemap_generator/sitemap_location'
|
9
|
-
require 'active_support/core_ext/numeric'
|
10
9
|
|
11
10
|
module SitemapGenerator
|
12
11
|
autoload(:Interpreter, 'sitemap_generator/interpreter')
|
13
12
|
autoload(:FileAdapter, 'sitemap_generator/adapters/file_adapter')
|
14
13
|
autoload(:WaveAdapter, 'sitemap_generator/adapters/wave_adapter')
|
14
|
+
autoload(:BigDecimal, 'sitemap_generator/core_ext/big_decimal')
|
15
|
+
autoload(:Numeric, 'sitemap_generator/core_ext/numeric')
|
15
16
|
|
16
|
-
SitemapError
|
17
|
-
SitemapFullError
|
17
|
+
SitemapError = Class.new(StandardError)
|
18
|
+
SitemapFullError = Class.new(SitemapError)
|
18
19
|
SitemapFinalizedError = Class.new(SitemapError)
|
19
20
|
|
20
|
-
|
21
|
+
Utilities.with_warnings(nil) do
|
21
22
|
VERSION = File.read(File.dirname(__FILE__) + "/../VERSION").strip
|
22
23
|
MAX_SITEMAP_FILES = 50_000 # max sitemap links per index file
|
23
24
|
MAX_SITEMAP_LINKS = 50_000 # max links per sitemap
|
24
25
|
MAX_SITEMAP_IMAGES = 1_000 # max images per url
|
25
26
|
MAX_SITEMAP_NEWS = 1_000 # max news sitemap per index_file
|
26
|
-
MAX_SITEMAP_FILESIZE = 10.megabytes # bytes
|
27
|
+
MAX_SITEMAP_FILESIZE = SitemapGenerator::Numeric.new(10).megabytes # bytes
|
27
28
|
|
28
29
|
# Lazy-initialize the LinkSet instance
|
29
30
|
Sitemap = (Class.new do
|
@@ -40,7 +41,22 @@ module SitemapGenerator
|
|
40
41
|
|
41
42
|
class << self
|
42
43
|
attr_accessor :root, :app, :templates
|
43
|
-
attr_writer :yield_sitemap
|
44
|
+
attr_writer :yield_sitemap, :verbose
|
45
|
+
end
|
46
|
+
|
47
|
+
# Global default for the verbose setting.
|
48
|
+
def self.verbose
|
49
|
+
if @verbose.nil?
|
50
|
+
@verbose = if SitemapGenerator::Utilities.truthy?(ENV['VERBOSE'])
|
51
|
+
true
|
52
|
+
elsif SitemapGenerator::Utilities.falsy?(ENV['VERBOSE'])
|
53
|
+
false
|
54
|
+
else
|
55
|
+
nil
|
56
|
+
end
|
57
|
+
else
|
58
|
+
@verbose
|
59
|
+
end
|
44
60
|
end
|
45
61
|
|
46
62
|
# Returns true if we should yield the sitemap instance to the block, false otherwise.
|
@@ -48,9 +64,9 @@ module SitemapGenerator
|
|
48
64
|
!!@yeild_sitemap
|
49
65
|
end
|
50
66
|
|
51
|
-
self.root
|
67
|
+
self.root = File.expand_path(File.join(File.dirname(__FILE__), '../')) # Root of the install dir, not the Rails app
|
52
68
|
self.templates = SitemapGenerator::Templates.new(self.root)
|
53
|
-
self.app
|
69
|
+
self.app = SitemapGenerator::Application.new
|
54
70
|
end
|
55
71
|
|
56
72
|
require 'sitemap_generator/railtie' if SitemapGenerator.app.rails3?
|
@@ -8,15 +8,42 @@ module SitemapGenerator
|
|
8
8
|
|
9
9
|
# Returns a boolean indicating whether this environment is Rails 3
|
10
10
|
#
|
11
|
-
# @return [Boolean]
|
11
|
+
# @return [Boolean]
|
12
12
|
def rails3?
|
13
13
|
rails? && Rails.version.to_f >= 3
|
14
14
|
rescue
|
15
15
|
false # Rails.version defined in 2.1.0
|
16
16
|
end
|
17
|
-
|
17
|
+
|
18
18
|
def root
|
19
|
-
Pathname.new(
|
19
|
+
Pathname.new(rails_root || Dir.getwd)
|
20
|
+
end
|
21
|
+
|
22
|
+
protected
|
23
|
+
|
24
|
+
# Returns the root of the Rails application,
|
25
|
+
# if this is running in a Rails context.
|
26
|
+
# Returns `nil` if no such root is defined.
|
27
|
+
#
|
28
|
+
# @return [String, nil]
|
29
|
+
def rails_root
|
30
|
+
if defined?(::Rails.root)
|
31
|
+
return ::Rails.root.to_s if ::Rails.root
|
32
|
+
raise "ERROR: Rails.root is nil!"
|
33
|
+
end
|
34
|
+
return RAILS_ROOT.to_s if defined?(RAILS_ROOT)
|
35
|
+
return nil
|
36
|
+
end
|
37
|
+
|
38
|
+
# Returns the environment of the Rails application,
|
39
|
+
# if this is running in a Rails context.
|
40
|
+
# Returns `nil` if no such environment is defined.
|
41
|
+
#
|
42
|
+
# @return [String, nil]
|
43
|
+
def rails_env
|
44
|
+
return ::Rails.env.to_s if defined?(::Rails.env)
|
45
|
+
return RAILS_ENV.to_s if defined?(RAILS_ENV)
|
46
|
+
return nil
|
20
47
|
end
|
21
48
|
end
|
22
|
-
end
|
49
|
+
end
|
@@ -2,9 +2,3 @@ require 'sitemap_generator/builder/sitemap_file'
|
|
2
2
|
require 'sitemap_generator/builder/sitemap_index_file'
|
3
3
|
require 'sitemap_generator/builder/sitemap_url'
|
4
4
|
require 'sitemap_generator/builder/sitemap_index_url'
|
5
|
-
|
6
|
-
module SitemapGenerator
|
7
|
-
module Builder
|
8
|
-
|
9
|
-
end
|
10
|
-
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'zlib'
|
2
|
-
require 'action_view' # for number_to_human_size
|
3
2
|
require 'fileutils'
|
3
|
+
require 'sitemap_generator/helpers/number_helper'
|
4
4
|
|
5
5
|
module SitemapGenerator
|
6
6
|
module Builder
|
@@ -12,8 +12,7 @@ module SitemapGenerator
|
|
12
12
|
# sitemap.finalize! <- write the sitemap file and freeze the object to protect it from further modification
|
13
13
|
#
|
14
14
|
class SitemapFile
|
15
|
-
include
|
16
|
-
include ActionView::Helpers::TextHelper # Rails 2.2.2 fails with missing 'pluralize' otherwise
|
15
|
+
include SitemapGenerator::Helpers::NumberHelper
|
17
16
|
attr_reader :link_count, :filesize, :location, :news_count
|
18
17
|
|
19
18
|
# === Options
|
@@ -125,13 +124,24 @@ module SitemapGenerator
|
|
125
124
|
|
126
125
|
# Return a summary string
|
127
126
|
def summary(opts={})
|
128
|
-
uncompressed_size = number_to_human_size(@filesize)
|
129
|
-
compressed_size
|
130
|
-
|
127
|
+
uncompressed_size = number_to_human_size(@filesize)
|
128
|
+
compressed_size = number_to_human_size(@location.filesize)
|
129
|
+
path = ellipsis(@location.path_in_public, 47)
|
130
|
+
"+ #{'%-47s' % path} #{'%10s' % @link_count} links / #{'%10s' % compressed_size}"
|
131
131
|
end
|
132
132
|
|
133
133
|
protected
|
134
134
|
|
135
|
+
# Replace the last 3 characters of string with ... if the string is as big
|
136
|
+
# or bigger than max.
|
137
|
+
def ellipsis(string, max)
|
138
|
+
if string.size >= max
|
139
|
+
string[0, max - 3] + '...'
|
140
|
+
else
|
141
|
+
string
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
135
145
|
# Return the bytesize length of the string. Ruby 1.8.6 compatible.
|
136
146
|
def bytesize(string)
|
137
147
|
string.respond_to?(:bytesize) ? string.bytesize : string.length
|
@@ -49,9 +49,10 @@ module SitemapGenerator
|
|
49
49
|
|
50
50
|
# Return a summary string
|
51
51
|
def summary(opts={})
|
52
|
-
uncompressed_size = number_to_human_size(@filesize)
|
53
|
-
compressed_size = number_to_human_size(@location.filesize)
|
54
|
-
|
52
|
+
uncompressed_size = number_to_human_size(@filesize)
|
53
|
+
compressed_size = number_to_human_size(@location.filesize)
|
54
|
+
path = ellipsis(@location.path_in_public, 44) # 47 - 3
|
55
|
+
"+ #{'%-44s' % path} #{'%10s' % @link_count} sitemaps / #{'%10s' % compressed_size}"
|
55
56
|
end
|
56
57
|
|
57
58
|
def stats_summary(opts={})
|
@@ -6,7 +6,7 @@ module SitemapGenerator
|
|
6
6
|
|
7
7
|
def initialize(path, options={})
|
8
8
|
if index = path.is_a?(SitemapGenerator::Builder::SitemapIndexFile) && path
|
9
|
-
|
9
|
+
SitemapGenerator::Utilities.reverse_merge!(options, :host => index.location.host, :lastmod => Time.now, :changefreq => 'always', :priority => 1.0)
|
10
10
|
path = index.location.path_in_public
|
11
11
|
super(path, options)
|
12
12
|
else
|
@@ -28,15 +28,13 @@ module SitemapGenerator
|
|
28
28
|
# * +news+
|
29
29
|
def initialize(path, options={})
|
30
30
|
if sitemap = path.is_a?(SitemapGenerator::Builder::SitemapFile) && path
|
31
|
-
|
31
|
+
SitemapGenerator::Utilities.reverse_merge!(options, :host => sitemap.location.host, :lastmod => sitemap.lastmod)
|
32
32
|
path = sitemap.location.path_in_public
|
33
33
|
end
|
34
34
|
|
35
35
|
SitemapGenerator::Utilities.assert_valid_keys(options, :priority, :changefreq, :lastmod, :host, :images, :video, :geo, :news, :videos)
|
36
|
-
|
37
|
-
|
38
|
-
raise "Cannot generate a url without a host"
|
39
|
-
end
|
36
|
+
SitemapGenerator::Utilities.reverse_merge!(options, :priority => 0.5, :changefreq => 'weekly', :lastmod => Time.now, :images => [], :news => {}, :videos => [])
|
37
|
+
raise "Cannot generate a url without a host" unless SitemapGenerator::Utilities.present?(options[:host])
|
40
38
|
if video = options.delete(:video)
|
41
39
|
options[:videos] = video.is_a?(Array) ? options[:videos].concat(video) : options[:videos] << video
|
42
40
|
end
|
@@ -65,7 +63,7 @@ module SitemapGenerator
|
|
65
63
|
builder.changefreq self[:changefreq] if self[:changefreq]
|
66
64
|
builder.priority format_float(self[:priority]) if self[:priority]
|
67
65
|
|
68
|
-
unless self[:news]
|
66
|
+
unless SitemapGenerator::Utilities.blank?(self[:news])
|
69
67
|
news_data = self[:news]
|
70
68
|
builder.news:news do
|
71
69
|
builder.news:publication do
|
@@ -117,7 +115,7 @@ module SitemapGenerator
|
|
117
115
|
end
|
118
116
|
end
|
119
117
|
|
120
|
-
unless self[:geo]
|
118
|
+
unless SitemapGenerator::Utilities.blank?(self[:geo])
|
121
119
|
geo = self[:geo]
|
122
120
|
builder.geo :geo do
|
123
121
|
builder.geo :format, geo[:format] if geo[:format]
|
@@ -128,7 +126,7 @@ module SitemapGenerator
|
|
128
126
|
end
|
129
127
|
|
130
128
|
def news?
|
131
|
-
self[:news]
|
129
|
+
SitemapGenerator::Utilities.present?(self[:news])
|
132
130
|
end
|
133
131
|
|
134
132
|
protected
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'bigdecimal'
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'psych'
|
5
|
+
rescue LoadError
|
6
|
+
end
|
7
|
+
|
8
|
+
require 'yaml'
|
9
|
+
|
10
|
+
# Define our own class rather than modify the global class
|
11
|
+
class SitemapGenerator::BigDecimal < BigDecimal
|
12
|
+
YAML_TAG = 'tag:yaml.org,2002:float'
|
13
|
+
YAML_MAPPING = { 'Infinity' => '.Inf', '-Infinity' => '-.Inf', 'NaN' => '.NaN' }
|
14
|
+
|
15
|
+
yaml_as YAML_TAG
|
16
|
+
|
17
|
+
# This emits the number without any scientific notation.
|
18
|
+
# This is better than self.to_f.to_s since it doesn't lose precision.
|
19
|
+
#
|
20
|
+
# Note that reconstituting YAML floats to native floats may lose precision.
|
21
|
+
def to_yaml(opts = {})
|
22
|
+
return super if defined?(YAML::ENGINE) && !YAML::ENGINE.syck?
|
23
|
+
|
24
|
+
YAML.quick_emit(nil, opts) do |out|
|
25
|
+
string = to_s
|
26
|
+
out.scalar(YAML_TAG, YAML_MAPPING[string] || string, :plain)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def encode_with(coder)
|
31
|
+
string = to_s
|
32
|
+
coder.represent_scalar(nil, YAML_MAPPING[string] || string)
|
33
|
+
end
|
34
|
+
|
35
|
+
def to_d
|
36
|
+
self
|
37
|
+
end
|
38
|
+
|
39
|
+
DEFAULT_STRING_FORMAT = 'F'
|
40
|
+
def to_formatted_s(format = DEFAULT_STRING_FORMAT)
|
41
|
+
_original_to_s(format)
|
42
|
+
end
|
43
|
+
alias_method :_original_to_s, :to_s
|
44
|
+
alias_method :to_s, :to_formatted_s
|
45
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
class SitemapGenerator::Numeric
|
2
|
+
KILOBYTE = 1024
|
3
|
+
MEGABYTE = KILOBYTE * 1024
|
4
|
+
GIGABYTE = MEGABYTE * 1024
|
5
|
+
TERABYTE = GIGABYTE * 1024
|
6
|
+
PETABYTE = TERABYTE * 1024
|
7
|
+
EXABYTE = PETABYTE * 1024
|
8
|
+
|
9
|
+
def initialize(number)
|
10
|
+
@number = number
|
11
|
+
end
|
12
|
+
|
13
|
+
# Enables the use of byte calculations and declarations, like 45.bytes + 2.6.megabytes
|
14
|
+
def bytes
|
15
|
+
@number
|
16
|
+
end
|
17
|
+
alias :byte :bytes
|
18
|
+
|
19
|
+
def kilobytes
|
20
|
+
@number * KILOBYTE
|
21
|
+
end
|
22
|
+
alias :kilobyte :kilobytes
|
23
|
+
|
24
|
+
def megabytes
|
25
|
+
@number * MEGABYTE
|
26
|
+
end
|
27
|
+
alias :megabyte :megabytes
|
28
|
+
|
29
|
+
def gigabytes
|
30
|
+
@number * GIGABYTE
|
31
|
+
end
|
32
|
+
alias :gigabyte :gigabytes
|
33
|
+
|
34
|
+
def terabytes
|
35
|
+
@number * TERABYTE
|
36
|
+
end
|
37
|
+
alias :terabyte :terabytes
|
38
|
+
|
39
|
+
def petabytes
|
40
|
+
@number * PETABYTE
|
41
|
+
end
|
42
|
+
alias :petabyte :petabytes
|
43
|
+
|
44
|
+
def exabytes
|
45
|
+
@number * EXABYTE
|
46
|
+
end
|
47
|
+
alias :exabyte :exabytes
|
48
|
+
end
|
@@ -0,0 +1,237 @@
|
|
1
|
+
# require "sitemap_generator/core_ext/big_decimal/conversions"
|
2
|
+
require "sitemap_generator/utilities"
|
3
|
+
|
4
|
+
module SitemapGenerator
|
5
|
+
# = SitemapGenerator Number Helpers
|
6
|
+
module Helpers #:nodoc:
|
7
|
+
|
8
|
+
# Provides methods for converting numbers into formatted strings.
|
9
|
+
# Methods are provided for precision, positional notation and file size
|
10
|
+
# and pretty printing.
|
11
|
+
#
|
12
|
+
# Most methods expect a +number+ argument, and will return it
|
13
|
+
# unchanged if can't be converted into a valid number.
|
14
|
+
module NumberHelper
|
15
|
+
|
16
|
+
# Raised when argument +number+ param given to the helpers is invalid and
|
17
|
+
# the option :raise is set to +true+.
|
18
|
+
class InvalidNumberError < StandardError
|
19
|
+
attr_accessor :number
|
20
|
+
def initialize(number)
|
21
|
+
@number = number
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# Formats a +number+ with grouped thousands using +delimiter+ (e.g., 12,324). You can
|
26
|
+
# customize the format in the +options+ hash.
|
27
|
+
#
|
28
|
+
# ==== Options
|
29
|
+
# * <tt>:locale</tt> - Sets the locale to be used for formatting (defaults to current locale).
|
30
|
+
# * <tt>:delimiter</tt> - Sets the thousands delimiter (defaults to ",").
|
31
|
+
# * <tt>:separator</tt> - Sets the separator between the fractional and integer digits (defaults to ".").
|
32
|
+
#
|
33
|
+
# ==== Examples
|
34
|
+
# number_with_delimiter(12345678) # => 12,345,678
|
35
|
+
# number_with_delimiter(12345678.05) # => 12,345,678.05
|
36
|
+
# number_with_delimiter(12345678, :delimiter => ".") # => 12.345.678
|
37
|
+
# number_with_delimiter(12345678, :separator => ",") # => 12,345,678
|
38
|
+
# number_with_delimiter(12345678.05, :locale => :fr) # => 12 345 678,05
|
39
|
+
# number_with_delimiter(98765432.98, :delimiter => " ", :separator => ",")
|
40
|
+
# # => 98 765 432,98
|
41
|
+
def number_with_delimiter(number, options = {})
|
42
|
+
SitemapGenerator::Utilities.symbolize_keys!(options)
|
43
|
+
|
44
|
+
begin
|
45
|
+
Float(number)
|
46
|
+
rescue ArgumentError, TypeError
|
47
|
+
if options[:raise]
|
48
|
+
raise InvalidNumberError, number
|
49
|
+
else
|
50
|
+
return number
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
defaults = {
|
55
|
+
:separator => ".",
|
56
|
+
:delimiter => ",",
|
57
|
+
:precision => 3,
|
58
|
+
:significant => false,
|
59
|
+
:strip_insignificant_zeros => false
|
60
|
+
}
|
61
|
+
options = SitemapGenerator::Utilities.reverse_merge(options, defaults)
|
62
|
+
|
63
|
+
parts = number.to_s.to_str.split('.')
|
64
|
+
parts[0].gsub!(/(\d)(?=(\d\d\d)+(?!\d))/, "\\1#{options[:delimiter]}")
|
65
|
+
parts.join(options[:separator])
|
66
|
+
end
|
67
|
+
|
68
|
+
# Formats a +number+ with the specified level of <tt>:precision</tt> (e.g., 112.32 has a precision
|
69
|
+
# of 2 if +:significant+ is +false+, and 5 if +:significant+ is +true+).
|
70
|
+
# You can customize the format in the +options+ hash.
|
71
|
+
#
|
72
|
+
# ==== Options
|
73
|
+
# * <tt>:locale</tt> - Sets the locale to be used for formatting (defaults to current locale).
|
74
|
+
# * <tt>:precision</tt> - Sets the precision of the number (defaults to 3).
|
75
|
+
# * <tt>:significant</tt> - If +true+, precision will be the # of significant_digits. If +false+, the # of fractional digits (defaults to +false+)
|
76
|
+
# * <tt>:separator</tt> - Sets the separator between the fractional and integer digits (defaults to ".").
|
77
|
+
# * <tt>:delimiter</tt> - Sets the thousands delimiter (defaults to "").
|
78
|
+
# * <tt>:strip_insignificant_zeros</tt> - If +true+ removes insignificant zeros after the decimal separator (defaults to +false+)
|
79
|
+
#
|
80
|
+
# ==== Examples
|
81
|
+
# number_with_precision(111.2345) # => 111.235
|
82
|
+
# number_with_precision(111.2345, :precision => 2) # => 111.23
|
83
|
+
# number_with_precision(13, :precision => 5) # => 13.00000
|
84
|
+
# number_with_precision(389.32314, :precision => 0) # => 389
|
85
|
+
# number_with_precision(111.2345, :significant => true) # => 111
|
86
|
+
# number_with_precision(111.2345, :precision => 1, :significant => true) # => 100
|
87
|
+
# number_with_precision(13, :precision => 5, :significant => true) # => 13.000
|
88
|
+
# number_with_precision(111.234, :locale => :fr) # => 111,234
|
89
|
+
# number_with_precision(13, :precision => 5, :significant => true, strip_insignificant_zeros => true)
|
90
|
+
# # => 13
|
91
|
+
# number_with_precision(389.32314, :precision => 4, :significant => true) # => 389.3
|
92
|
+
# number_with_precision(1111.2345, :precision => 2, :separator => ',', :delimiter => '.')
|
93
|
+
# # => 1.111,23
|
94
|
+
def number_with_precision(number, options = {})
|
95
|
+
SitemapGenerator::Utilities.symbolize_keys!(options)
|
96
|
+
|
97
|
+
number = begin
|
98
|
+
Float(number)
|
99
|
+
rescue ArgumentError, TypeError
|
100
|
+
if options[:raise]
|
101
|
+
raise InvalidNumberError, number
|
102
|
+
else
|
103
|
+
return number
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
defaults = {
|
108
|
+
:separator => ".",
|
109
|
+
:delimiter => ",",
|
110
|
+
:precision => 3,
|
111
|
+
:significant => false,
|
112
|
+
:strip_insignificant_zeros => false
|
113
|
+
}
|
114
|
+
precision_defaults = {
|
115
|
+
:delimiter => ""
|
116
|
+
}
|
117
|
+
defaults = defaults.merge(precision_defaults)
|
118
|
+
|
119
|
+
options = SitemapGenerator::Utilities.reverse_merge(options, defaults) # Allow the user to unset default values: Eg.: :significant => false
|
120
|
+
precision = options.delete :precision
|
121
|
+
significant = options.delete :significant
|
122
|
+
strip_insignificant_zeros = options.delete :strip_insignificant_zeros
|
123
|
+
|
124
|
+
if significant and precision > 0
|
125
|
+
if number == 0
|
126
|
+
digits, rounded_number = 1, 0
|
127
|
+
else
|
128
|
+
digits = (Math.log10(number.abs) + 1).floor
|
129
|
+
rounded_number = (SitemapGenerator::BigDecimal.new(number.to_s) / SitemapGenerator::BigDecimal.new((10 ** (digits - precision)).to_f.to_s)).round.to_f * 10 ** (digits - precision)
|
130
|
+
digits = (Math.log10(rounded_number.abs) + 1).floor # After rounding, the number of digits may have changed
|
131
|
+
end
|
132
|
+
precision = precision - digits
|
133
|
+
precision = precision > 0 ? precision : 0 #don't let it be negative
|
134
|
+
else
|
135
|
+
rounded_number = SitemapGenerator::Utilities.round(SitemapGenerator::BigDecimal.new(number.to_s), precision).to_f
|
136
|
+
end
|
137
|
+
formatted_number = number_with_delimiter("%01.#{precision}f" % rounded_number, options)
|
138
|
+
if strip_insignificant_zeros
|
139
|
+
escaped_separator = Regexp.escape(options[:separator])
|
140
|
+
formatted_number.sub(/(#{escaped_separator})(\d*[1-9])?0+\z/, '\1\2').sub(/#{escaped_separator}\z/, '')
|
141
|
+
else
|
142
|
+
formatted_number
|
143
|
+
end
|
144
|
+
|
145
|
+
end
|
146
|
+
|
147
|
+
STORAGE_UNITS = [:byte, :kb, :mb, :gb, :tb].freeze
|
148
|
+
DECIMAL_UNITS = {0 => :unit, 1 => :ten, 2 => :hundred, 3 => :thousand, 6 => :million, 9 => :billion, 12 => :trillion, 15 => :quadrillion,
|
149
|
+
-1 => :deci, -2 => :centi, -3 => :mili, -6 => :micro, -9 => :nano, -12 => :pico, -15 => :femto}.freeze
|
150
|
+
|
151
|
+
# Formats the bytes in +number+ into a more understandable representation
|
152
|
+
# (e.g., giving it 1500 yields 1.5 KB). This method is useful for
|
153
|
+
# reporting file sizes to users. You can customize the
|
154
|
+
# format in the +options+ hash.
|
155
|
+
#
|
156
|
+
# See <tt>number_to_human</tt> if you want to pretty-print a generic number.
|
157
|
+
#
|
158
|
+
# ==== Options
|
159
|
+
# * <tt>:locale</tt> - Sets the locale to be used for formatting (defaults to current locale).
|
160
|
+
# * <tt>:precision</tt> - Sets the precision of the number (defaults to 3).
|
161
|
+
# * <tt>:significant</tt> - If +true+, precision will be the # of significant_digits. If +false+, the # of fractional digits (defaults to +true+)
|
162
|
+
# * <tt>:separator</tt> - Sets the separator between the fractional and integer digits (defaults to ".").
|
163
|
+
# * <tt>:delimiter</tt> - Sets the thousands delimiter (defaults to "").
|
164
|
+
# * <tt>:strip_insignificant_zeros</tt> - If +true+ removes insignificant zeros after the decimal separator (defaults to +true+)
|
165
|
+
# ==== Examples
|
166
|
+
# number_to_human_size(123) # => 123 Bytes
|
167
|
+
# number_to_human_size(1234) # => 1.21 KB
|
168
|
+
# number_to_human_size(12345) # => 12.1 KB
|
169
|
+
# number_to_human_size(1234567) # => 1.18 MB
|
170
|
+
# number_to_human_size(1234567890) # => 1.15 GB
|
171
|
+
# number_to_human_size(1234567890123) # => 1.12 TB
|
172
|
+
# number_to_human_size(1234567, :precision => 2) # => 1.2 MB
|
173
|
+
# number_to_human_size(483989, :precision => 2) # => 470 KB
|
174
|
+
# number_to_human_size(1234567, :precision => 2, :separator => ',') # => 1,2 MB
|
175
|
+
#
|
176
|
+
# Non-significant zeros after the fractional separator are stripped out by default (set
|
177
|
+
# <tt>:strip_insignificant_zeros</tt> to +false+ to change that):
|
178
|
+
# number_to_human_size(1234567890123, :precision => 5) # => "1.1229 TB"
|
179
|
+
# number_to_human_size(524288000, :precision=>5) # => "500 MB"
|
180
|
+
def number_to_human_size(number, options = {})
|
181
|
+
SitemapGenerator::Utilities.symbolize_keys!(options)
|
182
|
+
|
183
|
+
number = begin
|
184
|
+
Float(number)
|
185
|
+
rescue ArgumentError, TypeError
|
186
|
+
if options[:raise]
|
187
|
+
raise InvalidNumberError, number
|
188
|
+
else
|
189
|
+
return number
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
defaults = {
|
194
|
+
:separator => ".",
|
195
|
+
:delimiter => ",",
|
196
|
+
:precision => 3,
|
197
|
+
:significant => false,
|
198
|
+
:strip_insignificant_zeros => false
|
199
|
+
}
|
200
|
+
human = {
|
201
|
+
:delimiter => "",
|
202
|
+
:precision => 3,
|
203
|
+
:significant => true,
|
204
|
+
:strip_insignificant_zeros => true
|
205
|
+
}
|
206
|
+
defaults = defaults.merge(human)
|
207
|
+
options = SitemapGenerator::Utilities.reverse_merge(options, defaults)
|
208
|
+
#for backwards compatibility with those that didn't add strip_insignificant_zeros to their locale files
|
209
|
+
options[:strip_insignificant_zeros] = true if not options.key?(:strip_insignificant_zeros)
|
210
|
+
|
211
|
+
storage_units_format = "%n %u"
|
212
|
+
|
213
|
+
if number.to_i < 1024
|
214
|
+
unit = number.to_i > 1 || number.to_i == 0 ? 'Bytes' : 'Byte'
|
215
|
+
storage_units_format.gsub(/%n/, number.to_i.to_s).gsub(/%u/, unit)
|
216
|
+
else
|
217
|
+
max_exp = STORAGE_UNITS.size - 1
|
218
|
+
exponent = (Math.log(number) / Math.log(1024)).to_i # Convert to base 1024
|
219
|
+
exponent = max_exp if exponent > max_exp # we need this to avoid overflow for the highest unit
|
220
|
+
number /= 1024 ** exponent
|
221
|
+
|
222
|
+
unit_key = STORAGE_UNITS[exponent]
|
223
|
+
units = {
|
224
|
+
:byte => "Bytes",
|
225
|
+
:kb => "KB",
|
226
|
+
:mb => "MB",
|
227
|
+
:gb => "GB",
|
228
|
+
:tb => "TB"
|
229
|
+
}
|
230
|
+
unit = units[unit_key]
|
231
|
+
formatted_number = number_with_precision(number, options)
|
232
|
+
storage_units_format.gsub(/%n/, formatted_number).gsub(/%u/, unit)
|
233
|
+
end
|
234
|
+
end
|
235
|
+
end
|
236
|
+
end
|
237
|
+
end
|