js-routes-zigexn 1.3.3

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.
@@ -0,0 +1,2 @@
1
+ <%# encoding: UTF-8 %>
2
+ <%= JsRoutes.assert_usable_configuration! && JsRoutes.generate %>
@@ -0,0 +1,8 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "http://rubygems.org"
4
+
5
+ gem "railties", "~> 3.2.22.5"
6
+ gem "tzinfo"
7
+
8
+ gemspec :path => "../"
@@ -0,0 +1,8 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "http://rubygems.org"
4
+
5
+ gem "railties", "~> 4.0.13"
6
+ gem "sprockets", "< 3"
7
+
8
+ gemspec :path => "../"
@@ -0,0 +1,8 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "http://rubygems.org"
4
+
5
+ gem "railties", "~> 4.0.13"
6
+ gem "sprockets", "~> 3.0"
7
+
8
+ gemspec :path => "../"
@@ -0,0 +1,8 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "http://rubygems.org"
4
+
5
+ gem "railties", "~> 4.1.16"
6
+ gem "sprockets", "< 3"
7
+
8
+ gemspec :path => "../"
@@ -0,0 +1,8 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "http://rubygems.org"
4
+
5
+ gem "railties", "~> 4.1.16"
6
+ gem "sprockets", "~> 3.0"
7
+
8
+ gemspec :path => "../"
@@ -0,0 +1,8 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "http://rubygems.org"
4
+
5
+ gem "railties", "~> 4.2.8"
6
+ gem "sprockets", "< 3"
7
+
8
+ gemspec :path => "../"
@@ -0,0 +1,8 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "http://rubygems.org"
4
+
5
+ gem "railties", "~> 4.2.8"
6
+ gem "sprockets", "~> 3.0"
7
+
8
+ gemspec :path => "../"
@@ -0,0 +1,8 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "http://rubygems.org"
4
+
5
+ gem "railties", "~> 5.0.2"
6
+ gem "sprockets", "< 3"
7
+
8
+ gemspec :path => "../"
@@ -0,0 +1,8 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "http://rubygems.org"
4
+
5
+ gem "railties", "~> 5.0.2"
6
+ gem "sprockets", "~> 3.0"
7
+
8
+ gemspec :path => "../"
@@ -0,0 +1,36 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'js_routes/version'
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{js-routes-zigexn}
8
+ s.version = JsRoutes::VERSION
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["VietTH"]
12
+ s.description = %q{Generates javascript file that defines all Rails named routes as javascript helpers}
13
+ s.email = %q{vietth@zigexn.vn}
14
+ s.extra_rdoc_files = [
15
+ "LICENSE.txt"
16
+ ]
17
+ s.files = `git ls-files`.split("\n")
18
+ s.homepage = %q{https://github.com/vietthventura/js-routes}
19
+ s.licenses = ["MIT"]
20
+ s.require_paths = ["lib"]
21
+ s.summary = %q{Brings Rails named routes to javascript}
22
+
23
+ s.add_runtime_dependency(%q<railties>, [">= 3.2"])
24
+ s.add_runtime_dependency(%q<sprockets-rails>)
25
+ s.add_development_dependency(%q<rspec>, [">= 3.0.0"])
26
+ s.add_development_dependency(%q<bundler>, [">= 1.1.0"])
27
+ s.add_development_dependency(%q<coffee-script>, [">= 0"])
28
+ s.add_development_dependency(%q<appraisal>, [">= 0.5.2"])
29
+ if defined?(JRUBY_VERSION)
30
+ s.add_development_dependency(%q<therubyrhino>, [">= 2.0.4"])
31
+ else
32
+ s.add_development_dependency(%q<byebug>)
33
+ s.add_development_dependency(%q<pry-byebug>)
34
+ s.add_development_dependency(%q<therubyracer>, [">= 0.12.3"])
35
+ end
36
+ end
data/lib/js-routes.rb ADDED
@@ -0,0 +1 @@
1
+ require 'js_routes'
@@ -0,0 +1,73 @@
1
+ class JsRoutesSprocketsExtension
2
+ def initialize(filename, &block)
3
+ @filename = filename
4
+ @source = block.call
5
+ end
6
+
7
+ def render(context, empty_hash_wtf)
8
+ self.class.run(@filename, @source, context)
9
+ end
10
+
11
+ def self.run(filename, source, context)
12
+ if context.logical_path == 'js-routes'
13
+ routes = Rails.root.join('config', 'routes.rb').to_s
14
+ context.depend_on(routes)
15
+ end
16
+ source
17
+ end
18
+
19
+ def self.call(input)
20
+ filename = input[:filename]
21
+ source = input[:data]
22
+ context = input[:environment].context_class.new(input)
23
+
24
+ result = run(filename, source, context)
25
+ context.metadata.merge(data: result)
26
+ end
27
+ end
28
+
29
+
30
+ class Engine < ::Rails::Engine
31
+ require 'sprockets/version'
32
+ v2 = Gem::Dependency.new('', ' ~> 2')
33
+ vgte3 = Gem::Dependency.new('', ' >= 3')
34
+ sprockets_version = Gem::Version.new(::Sprockets::VERSION).release
35
+ initializer_args = case sprockets_version
36
+ when -> (v) { v2.match?('', v) }
37
+ { after: "sprockets.environment" }
38
+ when -> (v) { vgte3.match?('', v) }
39
+ { after: :engines_blank_point, before: :finisher_hook }
40
+ else
41
+ raise StandardError, "Sprockets version #{sprockets_version} is not supported"
42
+ end
43
+
44
+ is_running_rails = defined?(Rails) && Rails.respond_to?(:version)
45
+ is_running_rails_32 = is_running_rails && Rails.version.match(/3\.2/)
46
+
47
+ initializer 'js-routes.dependent_on_routes', initializer_args do
48
+ case sprockets_version
49
+ when -> (v) { v2.match?('', v) },
50
+ -> (v) { vgte3.match?('', v) }
51
+
52
+ # It seems rails 3.2 is not working if
53
+ # `Rails.application.config.assets.configure` is used for
54
+ # registering preprocessor
55
+ if is_running_rails_32
56
+ Rails.application.assets.register_preprocessor(
57
+ "application/javascript",
58
+ JsRoutesSprocketsExtension,
59
+ )
60
+ else
61
+ # Other rails version, assumed newer
62
+ Rails.application.config.assets.configure do |config|
63
+ config.register_preprocessor(
64
+ "application/javascript",
65
+ JsRoutesSprocketsExtension,
66
+ )
67
+ end
68
+ end
69
+ else
70
+ raise StandardError, "Sprockets version #{sprockets_version} is not supported"
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,3 @@
1
+ class JsRoutes
2
+ VERSION = "1.3.3"
3
+ end
data/lib/js_routes.rb ADDED
@@ -0,0 +1,293 @@
1
+ require 'uri'
2
+ require 'js_routes/engine' if defined?(Rails)
3
+ require 'js_routes/version'
4
+
5
+ class JsRoutes
6
+
7
+ #
8
+ # OPTIONS
9
+ #
10
+
11
+ DEFAULT_PATH = File.join('app','assets','javascripts','routes.js')
12
+
13
+ DEFAULTS = {
14
+ namespace: "Routes",
15
+ exclude: [],
16
+ include: //,
17
+ file: DEFAULT_PATH,
18
+ prefix: -> { Rails.application.config.relative_url_root || "" },
19
+ url_links: false,
20
+ camel_case: false,
21
+ default_url_options: {},
22
+ compact: false,
23
+ serializer: nil,
24
+ special_options_key: "_options",
25
+ application: -> { Rails.application }
26
+ }
27
+
28
+ NODE_TYPES = {
29
+ GROUP: 1,
30
+ CAT: 2,
31
+ SYMBOL: 3,
32
+ OR: 4,
33
+ STAR: 5,
34
+ LITERAL: 6,
35
+ SLASH: 7,
36
+ DOT: 8
37
+ }
38
+
39
+ LAST_OPTIONS_KEY = "options".freeze
40
+ FILTERED_DEFAULT_PARTS = [:controller, :action, :subdomain]
41
+ URL_OPTIONS = [:protocol, :domain, :host, :port, :subdomain]
42
+
43
+ class Configuration < Struct.new(*DEFAULTS.keys)
44
+ def initialize(attributes = nil)
45
+ assign(DEFAULTS)
46
+ return unless attributes
47
+ assign(attributes)
48
+ end
49
+
50
+ def assign(attributes)
51
+ attributes.each do |attribute, value|
52
+ value = value.call if value.is_a?(Proc)
53
+ send(:"#{attribute}=", value)
54
+ end
55
+ self
56
+ end
57
+
58
+ def [](attribute)
59
+ send(attribute)
60
+ end
61
+
62
+ def merge(attributes)
63
+ clone.assign(attributes)
64
+ end
65
+
66
+ def to_hash
67
+ Hash[*members.zip(values).flatten(1)].symbolize_keys
68
+ end
69
+ end
70
+
71
+ #
72
+ # API
73
+ #
74
+
75
+ class << self
76
+ def setup(&block)
77
+ configuration.tap(&block) if block
78
+ end
79
+
80
+ def options
81
+ ActiveSupport::Deprecation.warn('JsRoutes.options method is deprecated use JsRoutes.configuration instead')
82
+ configuration
83
+ end
84
+
85
+ def configuration
86
+ @configuration ||= Configuration.new
87
+ end
88
+
89
+ def generate(opts = {})
90
+ new(opts).generate
91
+ end
92
+
93
+ def generate!(file_name=nil, opts = {})
94
+ if file_name.is_a?(Hash)
95
+ opts = file_name
96
+ file_name = opts[:file]
97
+ end
98
+ new(opts).generate!(file_name)
99
+ end
100
+
101
+ # Under rails 3.1.1 and higher, perform a check to ensure that the
102
+ # full environment will be available during asset compilation.
103
+ # This is required to ensure routes are loaded.
104
+ def assert_usable_configuration!
105
+ if 3 == Rails::VERSION::MAJOR && !Rails.application.config.assets.initialize_on_precompile
106
+ raise("Cannot precompile js-routes unless environment is initialized. Please set config.assets.initialize_on_precompile to true.")
107
+ end
108
+ true
109
+ end
110
+
111
+ def json(string)
112
+ ActiveSupport::JSON.encode(string)
113
+ end
114
+ end
115
+
116
+ #
117
+ # Implementation
118
+ #
119
+
120
+ def initialize(options = {})
121
+ @configuration = self.class.configuration.merge(options)
122
+ end
123
+
124
+ def generate
125
+ # Ensure routes are loaded. If they're not, load them.
126
+ if named_routes.to_a.empty? && application.respond_to?(:reload_routes!)
127
+ application.reload_routes!
128
+ end
129
+
130
+ {
131
+ "GEM_VERSION" => JsRoutes::VERSION,
132
+ "ROUTES" => js_routes,
133
+ "DEPRECATED_BEHAVIOR" => Rails.version < "4",
134
+ "NODE_TYPES" => json(NODE_TYPES),
135
+
136
+ "APP_CLASS" => application.class.to_s,
137
+ "NAMESPACE" => json(@configuration.namespace),
138
+ "DEFAULT_URL_OPTIONS" => json(@configuration.default_url_options),
139
+ "PREFIX" => json(@configuration.prefix),
140
+ "SPECIAL_OPTIONS_KEY" => json(@configuration.special_options_key),
141
+ "SERIALIZER" => @configuration.serializer || json(nil),
142
+ }.inject(File.read(File.dirname(__FILE__) + "/routes.js")) do |js, (key, value)|
143
+ js.gsub!(key, value.to_s)
144
+ end
145
+ end
146
+
147
+ def generate!(file_name = nil)
148
+ # Some libraries like Devise do not yet loaded their routes so we will wait
149
+ # until initialization process finish
150
+ # https://github.com/railsware/js-routes/issues/7
151
+ Rails.configuration.after_initialize do
152
+ file_name ||= self.class.configuration['file']
153
+ File.open(Rails.root.join(file_name), 'w') do |f|
154
+ f.write generate
155
+ end
156
+ end
157
+ end
158
+
159
+ protected
160
+
161
+ def application
162
+ @configuration.application
163
+ end
164
+
165
+ def named_routes
166
+ application.routes.named_routes.to_a
167
+ end
168
+
169
+ def js_routes
170
+ js_routes = named_routes.sort_by(&:first).flat_map do |_, route|
171
+ [build_route_if_match(route)] + mounted_app_routes(route)
172
+ end.compact
173
+ "{\n" + js_routes.join(",\n") + "}\n"
174
+ end
175
+
176
+ def mounted_app_routes(route)
177
+ rails_engine_app = get_app_from_route(route)
178
+ if rails_engine_app.respond_to?(:superclass) && rails_engine_app.superclass == Rails::Engine && !route.path.anchored
179
+ rails_engine_app.routes.named_routes.map do |_, engine_route|
180
+ build_route_if_match(engine_route, route)
181
+ end
182
+ else
183
+ []
184
+ end
185
+ end
186
+
187
+ def get_app_from_route(route)
188
+ # rails engine in Rails 4.2 use additional ActionDispatch::Routing::Mapper::Constraints, which contain app
189
+ if route.app.respond_to?(:app) && route.app.respond_to?(:constraints)
190
+ route.app.app
191
+ else
192
+ route.app
193
+ end
194
+ end
195
+
196
+ def build_route_if_match(route, parent_route=nil)
197
+ if any_match?(route, parent_route, @configuration[:exclude]) || !any_match?(route, parent_route, @configuration[:include])
198
+ nil
199
+ else
200
+ build_js(route, parent_route)
201
+ end
202
+ end
203
+
204
+ def any_match?(route, parent_route, matchers)
205
+ full_route = [parent_route.try(:name), route.name].compact.join('_')
206
+
207
+ matchers = Array(matchers)
208
+ matchers.any? {|regex| full_route =~ regex}
209
+ end
210
+
211
+ def build_js(route, parent_route)
212
+ name = [parent_route.try(:name), route.name].compact
213
+ route_name = generate_route_name(name, (:path unless @configuration[:compact]))
214
+ parent_spec = parent_route.try(:path).try(:spec)
215
+ route_arguments = route_js_arguments(route, parent_spec)
216
+ url_link = generate_url_link(name, route_name, route_arguments, route)
217
+ _ = <<-JS.strip!
218
+ // #{name.join('.')} => #{parent_spec}#{route.path.spec}
219
+ // function(#{build_params(route.required_parts)})
220
+ #{route_name}: Utils.route(#{route_arguments})#{",\n" + url_link if url_link.length > 0}
221
+ JS
222
+ end
223
+
224
+ def route_js_arguments(route, parent_spec)
225
+ required_parts = route.required_parts
226
+ parts_table = route.parts.each_with_object({}) do |part, hash|
227
+ hash[part] = required_parts.include?(part)
228
+ end
229
+ default_options = route.defaults.select do |part, _|
230
+ FILTERED_DEFAULT_PARTS.exclude?(part) && URL_OPTIONS.include?(part) || parts_table[part]
231
+ end
232
+ [
233
+ # JS objects don't preserve the order of properties which is crucial,
234
+ # so array is a better choice.
235
+ parts_table.to_a,
236
+ default_options,
237
+ serialize(route.path.spec, parent_spec)
238
+ ].map do |argument|
239
+ json(argument)
240
+ end.join(", ")
241
+ end
242
+
243
+ def generate_url_link(name, route_name, route_arguments, route)
244
+ return "" unless @configuration[:url_links]
245
+ <<-JS.strip!
246
+ #{generate_route_name(name, :url)}: Utils.route(#{route_arguments}, true)
247
+ JS
248
+ end
249
+
250
+ def generate_route_name(name, suffix)
251
+ route_name = name.join('_')
252
+ route_name << "_#{ suffix }" if suffix
253
+ @configuration[:camel_case] ? route_name.camelize(:lower) : route_name
254
+ end
255
+
256
+ def json(string)
257
+ self.class.json(string)
258
+ end
259
+
260
+ def build_params(required_parts)
261
+ params = required_parts + [LAST_OPTIONS_KEY]
262
+ params.join(", ")
263
+ end
264
+
265
+ # This function serializes Journey route into JSON structure
266
+ # We do not use Hash for human readable serialization
267
+ # And preffer Array serialization because it is shorter.
268
+ # Routes.js file will be smaller.
269
+ def serialize(spec, parent_spec=nil)
270
+ return nil unless spec
271
+ return spec.tr(':', '') if spec.is_a?(String)
272
+ result = serialize_spec(spec, parent_spec)
273
+ if parent_spec && result[1].is_a?(String)
274
+ result = [
275
+ # We encode node symbols as integer
276
+ # to reduce the routes.js file size
277
+ NODE_TYPES[:CAT],
278
+ serialize_spec(parent_spec),
279
+ result
280
+ ]
281
+ end
282
+ result
283
+ end
284
+
285
+ def serialize_spec(spec, parent_spec=nil)
286
+ [
287
+ NODE_TYPES[spec.type],
288
+ serialize(spec.left, parent_spec),
289
+ spec.respond_to?(:right) && serialize(spec.right)
290
+ ]
291
+ end
292
+ end
293
+