joosy 1.2.0.alpha.64 → 1.2.0.alpha.65

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0823adf3077e02d1d72bf7dda25eca2619f6af2b
4
- data.tar.gz: 93a63a4a7a5ddb792667df29374155773fd28ea9
3
+ metadata.gz: 7b17df9ece3872cfea75fb7a050d5258691fe806
4
+ data.tar.gz: 9d1a40dcd0816133a7f7b7b4a292b381d8850d8b
5
5
  SHA512:
6
- metadata.gz: 1307d42fe3cbb35e2a14b072c735122dfadcbdb3027384b1e63c692f61ec4860704c2ae3a4d0c8be500175c41c65b752540a6416b21320c1497802200f5e542d
7
- data.tar.gz: b0610530a29bcd99bf4abfeda87f4cbb670011b137ecbc7e5b7c6076d4e095d8f125bc0a51a751646cccb9a785e4e61bac0bcc94d2fcdf911673975c7336f0d3
6
+ metadata.gz: f25cc66bcc9c37df768236f01cfde7d426938755aa84d6708d4c15cab770cf37d3ee450062b7d763f23ffc8fe057a060000ecba28a53f8e169130d36285739b4
7
+ data.tar.gz: 30b5ec47a529211643b2f599e68cf13e9506026e0b0b375585009422fb596c66a262669fd2100a6fa985d08d4c62b2fb99edc8a6b7650f3cc215f698ac7f7f4b
data/Gruntfile.coffee CHANGED
@@ -1,101 +1,93 @@
1
1
  require 'sugar'
2
2
 
3
- Mincer = require 'mincer'
4
3
  semver = require 'semver'
5
4
 
6
5
  module.exports = (grunt) ->
7
6
  #
8
7
  # Common settings
9
8
  #
10
- locations =
11
-
12
- source:
13
- root: 'joosy.coffee'
14
- path: 'source'
15
- build: 'build/joosy.js'
16
-
17
- extensions: (name) ->
18
- root: "joosy/extensions/#{name || '*'}"
19
- build: "build/joosy/extensions/#{name || '**/*'}.js"
20
-
21
- specs: [
22
- 'bower_components/sinonjs/sinon.js',
23
- 'bower_components/sugar/release/sugar-full.min.js',
24
- 'spec/helpers/*.coffee'
25
- ]
26
-
27
- testem =
28
- parallel: 8
29
- launch_in_dev: ['PhantomJS'],
30
- launch_in_ci: ['PhantomJS', 'Chrome', 'Firefox', 'Safari', 'IE7', 'IE8', 'IE9']
9
+ testemOptions = (vendor, specs) ->
10
+ return {
11
+ src: Array.create([
12
+ 'bower_components/sinonjs/sinon.js',
13
+ 'bower_components/sugar/release/sugar-full.min.js',
14
+ 'spec/helpers/*.coffee'
15
+ ], vendor, 'joosy.coffee', specs)
16
+ assets:
17
+ setup: ->
18
+ grunt.grill.assetter('development').environment
19
+ options:
20
+ parallel: 8
21
+ launch_in_dev: ['PhantomJS'],
22
+ launch_in_ci: ['PhantomJS', 'Chrome', 'Firefox', 'Safari', 'IE7', 'IE8', 'IE9']
23
+ }
31
24
 
32
25
  #
33
26
  # Grunt extensions
34
27
  #
28
+ grunt.loadNpmTasks 'grill'
35
29
  grunt.loadNpmTasks 'grunt-contrib-testem'
36
30
  grunt.loadNpmTasks 'grunt-coffeelint'
37
31
  grunt.loadNpmTasks 'grunt-release'
32
+ grunt.loadNpmTasks 'grunt-gh-pages'
38
33
 
39
34
  #
40
35
  # Config
41
36
  #
42
37
  grunt.initConfig
43
- mince:
44
- core:
45
- include: [locations.source.path]
46
- src: locations.source.root
47
- dest: locations.source.build
48
- resources:
49
- include: [locations.source.path]
50
- src: locations.source.extensions('resources').root
51
- dest: locations.source.extensions('resources').build
52
- form:
53
- include: [locations.source.path]
54
- src: locations.source.extensions('resources-form').root
55
- dest: locations.source.extensions('resources-form').build
38
+ grill:
39
+ assets:
40
+ destination: 'build'
41
+ paths: 'source'
42
+ root: ['joosy.coffee', 'joosy/extensions/*']
56
43
 
57
44
  coffeelint:
58
45
  source:
59
46
  files:
60
- src: [locations.source.path + '/joosy/**/*.coffee']
47
+ src: 'source/joosy/**/*.coffee'
61
48
  options:
62
49
  'max_line_length':
63
50
  level: 'ignore'
64
51
 
52
+ 'gh-pages':
53
+ docs:
54
+ options:
55
+ add: true
56
+ clone: 'doc'
57
+ command:
58
+ cmd: 'grunt'
59
+ args: ['doc']
60
+
65
61
  testem:
66
- core:
67
- src: locations.specs
68
- .include('bower_components/jquery/jquery.js')
69
- .include(locations.source.build)
70
- .include('spec/joosy/core/**/*_spec.coffee')
71
- options: testem
72
- zepto:
73
- src: locations.specs
74
- .include('bower_components/zepto/zepto.js')
75
- .include(locations.source.build)
76
- .include('spec/joosy/core/**/*_spec.coffee')
77
- options: testem
78
- 'environments-global':
79
- src: locations.specs
80
- .include('bower_components/jquery/jquery.js')
81
- .include(locations.source.build)
82
- .include('spec/joosy/environments/global_spec.coffee')
83
- options: testem
84
- 'environments-amd':
85
- src: locations.specs
86
- .include('bower_components/jquery/jquery.js')
87
- .include('bower_components/requirejs/require.js')
88
- .include(locations.source.build)
89
- .include('spec/joosy/environments/amd_spec.coffee')
90
- options: testem
91
- extensions:
92
- src: locations.specs
93
- .include('bower_components/jquery/jquery.js')
94
- .include(locations.source.build)
95
- .include('bower_components/jquery-form/jquery.form.js')
96
- .include(locations.source.extensions().build)
97
- .include('spec/joosy/extensions/**/*_spec.coffee')
98
- options: testem
62
+ core: testemOptions(
63
+ 'bower_components/jquery/jquery.js',
64
+ 'spec/joosy/core/**/*_spec.coffee'
65
+ )
66
+ zepto: testemOptions(
67
+ 'bower_components/zepto/zepto.js',
68
+ 'spec/joosy/core/**/*_spec.coffee'
69
+ )
70
+ 'environments-global': testemOptions(
71
+ 'bower_components/jquery/jquery.js',
72
+ 'spec/joosy/environments/global_spec.coffee'
73
+ )
74
+ 'environments-amd': testemOptions(
75
+ [
76
+ 'bower_components/jquery/jquery.js',
77
+ 'bower_components/requirejs/require.js'
78
+ ],
79
+ 'spec/joosy/environments/amd_spec.coffee'
80
+ )
81
+ extensions: testemOptions(
82
+ [
83
+ 'bower_components/jquery/jquery.js',
84
+ 'bower_components/jquery-form/jquery.form.js'
85
+ ],
86
+ [
87
+ 'joosy/extensions/*',
88
+ 'spec/joosy/extensions/**/*_spec.coffee'
89
+ ]
90
+ )
99
91
 
100
92
  release:
101
93
  options:
@@ -109,21 +101,24 @@ module.exports = (grunt) ->
109
101
  #
110
102
  grunt.registerTask 'default', 'testem'
111
103
 
104
+ grunt.registerTask 'build', 'grill:compile'
105
+
112
106
  grunt.registerTask 'test', ->
107
+ grunt.task.run 'coffeelint'
113
108
  grunt.task.run if @args[0] then "testem:run:#{@args[0]}" else 'testem'
114
109
 
115
- grunt.registerTask 'publish', ['testem', 'publish:ensureCommits', 'doc', 'release', 'publish:gem']
116
-
110
+ grunt.registerTask 'publish', [
111
+ 'test',
112
+ 'build',
113
+ 'ensureCommits',
114
+ 'gh-pages',
115
+ 'release',
116
+ 'gemify'
117
+ ]
117
118
 
118
119
  #
119
120
  # Building
120
121
  #
121
- grunt.registerMultiTask 'mince', ->
122
- Mincer.CoffeeEngine.configure bare: false
123
- environment = new Mincer.Environment
124
- environment.appendPath x for x in @data.include
125
- grunt.file.write @data.dest, environment.findAsset(@data.src).toString()
126
-
127
122
  grunt.registerTask 'bowerize', ->
128
123
  bower = require './bower.json'
129
124
  meta = require './package.json'
@@ -134,7 +129,7 @@ module.exports = (grunt) ->
134
129
  #
135
130
  # Publishing
136
131
  #
137
- grunt.registerTask 'publish:ensureCommits', ->
132
+ grunt.registerTask 'ensureCommits', ->
138
133
  complete = @async()
139
134
 
140
135
  grunt.util.spawn {cmd: "git", args: ["status", "--porcelain" ]}, (error, result) ->
@@ -146,7 +141,7 @@ module.exports = (grunt) ->
146
141
  else
147
142
  complete true
148
143
 
149
- grunt.registerTask 'publish:gem', ->
144
+ grunt.registerTask 'gemify', ->
150
145
  meta = require './package.json'
151
146
  complete = @async()
152
147
 
@@ -165,79 +160,40 @@ module.exports = (grunt) ->
165
160
  #
166
161
  # Documentation
167
162
  #
168
- grunt.registerTask 'doc', ['doc:prepare', 'doc:generate']
169
-
170
- grunt.registerTask 'doc:generate', ->
163
+ grunt.registerTask 'doc', ->
171
164
  complete = @async()
172
- version = JSON.parse(grunt.file.read 'package.json').version.split('-')
173
- version = version[0]+'-'+version[1]?.split('.')[0]
174
- destination = "doc/#{version}"
175
- args = ['source', '--output-dir', destination]
176
165
 
177
- git = (args, callback) ->
178
- grunt.util.spawn {cmd: "git", args: args, opts: {stdio: [0,1,2], cwd: 'doc'}}, callback
166
+ version = require('./package.json').version.split('-')
167
+ version = version[0]+'-'+version[1]?.split('.')[0]
168
+ destination = "doc/#{version}"
179
169
 
180
170
  date = (version) ->
181
171
  return undefined unless version
182
172
  Date.create(grunt.file.read "doc/#{version}/DATE").format "{d} {Month} {yyyy}"
183
173
 
184
- git ['pull'], (error, result) ->
185
- grunt.fatal "Error pulling from git" if error
186
-
187
- grunt.file.delete destination if grunt.file.exists destination
188
- grunt.util.spawn {cmd: "codo", args: args, opts: {stdio: [0,1,2]}}, (error, result) ->
189
- grunt.fatal "Error generating docs" if error
190
- grunt.file.write "#{destination}/DATE", (new Date).toISOString()
191
-
192
- versions = []
193
- for version in grunt.file.expand({cwd: 'doc'}, '*')
194
- versions.push version if semver.valid(version)
195
-
196
- versions = versions.sort(semver.rcompare)
197
- edge = versions.find (x) -> x.has('-')
198
- stable = versions.find (x) -> !x.has('-')
199
- versions = versions.remove edge, stable
200
-
201
- versions = {
202
- edge:
203
- version: edge
204
- date: date(edge)
205
- stable:
206
- version: stable
207
- date: date(stable)
208
- versions: versions.map (x) -> { version: x, date: date(x) }
209
- }
210
- grunt.file.write 'doc/versions.js', "window.versions = #{JSON.stringify(versions)}"
211
-
212
- git ['add', '-A'], (error, result) ->
213
- grunt.fatal "Error adding files" if error
214
-
215
- git ['commit', '-m', "Updated at #{(new Date).toISOString()}"], (error, result) ->
216
- grunt.fatal "Error commiting" if error
217
-
218
- git ['push', 'origin', 'gh-pages'], (error, result) ->
219
- grunt.fatal "Error pushing" if error
220
- complete()
221
-
222
- grunt.registerTask 'doc:prepare', ->
223
- if grunt.file.exists 'doc'
224
- unless grunt.file.exists 'doc/.git'
225
- grunt.fatal "Documentation directory exists. Please remove it"
226
- else
227
- return
228
-
229
- complete = @async()
230
-
231
- base = process.cwd()
232
- git = (args, callback) ->
233
- grunt.util.spawn {cmd: "git", args: args, opts: {stdio: [0,1,2]}}, callback
234
-
235
- git ["clone", "git@github.com:joosy/joosy.git", "doc"], (error, result) ->
236
- grunt.fatal "Erorr cloning repo" if error
237
- process.chdir 'doc'
238
-
239
- git ["checkout", "gh-pages"], (error, result) ->
240
- grunt.fatal "Erorr checking branch out" if error
241
-
242
- process.chdir base
243
- complete()
174
+ args = ['source', '--output-dir', destination]
175
+ grunt.file.delete destination if grunt.file.exists destination
176
+
177
+ grunt.util.spawn {cmd: "codo", args: args, opts: {stdio: [0,1,2]}}, (error, result) ->
178
+ grunt.fatal "Error generating docs" if error
179
+ grunt.file.write "#{destination}/DATE", (new Date).toISOString()
180
+
181
+ versions = []
182
+ for version in grunt.file.expand({cwd: 'doc'}, '*')
183
+ versions.push version if semver.valid(version)
184
+
185
+ versions = versions.sort(semver.rcompare)
186
+ edge = versions.filter((x) -> x.has('-')).first()
187
+ stable = versions.filter((x) -> !x.has('-')).first()
188
+ versions = versions.remove edge, stable
189
+
190
+ versions = {
191
+ edge:
192
+ version: edge
193
+ date: date(edge)
194
+ stable:
195
+ version: stable
196
+ date: date(stable)
197
+ versions: versions.map (x) -> { version: x, date: date(x) }
198
+ }
199
+ grunt.file.write 'doc/versions.js', "window.versions = #{JSON.stringify(versions)}"
data/README.md CHANGED
@@ -87,8 +87,8 @@ You assets are at `public/` directory, enjoy!
87
87
  * Clone the project
88
88
  * Run `npm install` to get required Node modules
89
89
  * Run `bower install` to get required JS components
90
- * Run `grunt test` to run specs once
91
- * Run `grunt` to watch sources (automatic changes compilations) and run test-server (get your browser to http://localhost:8888/)
90
+ * Run `grunt test` to run all specs in all available browsers
91
+ * Run `grunt test:*` where `*` is then name of an environment to run the environment in the development mode. Check `Gruntfile.coffee` (section **testem**) for the list of existing environments.
92
92
 
93
93
  While current repository is at the same time NPM package, Ruby gem and Bower component, – the main Core
94
94
  environment is Node.js.
data/bower.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "joosy",
3
- "version": "1.2.0-alpha.64",
3
+ "version": "1.2.0-alpha.65",
4
4
  "main": "build/joosy.js",
5
5
  "ignore": [
6
6
  "lib",
@@ -370,6 +370,58 @@
370
370
 
371
371
  })(Joosy.Module);
372
372
 
373
+ }).call(this);
374
+ (function() {
375
+ var _ref,
376
+ __hasProp = {}.hasOwnProperty,
377
+ __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
378
+ __slice = [].slice;
379
+
380
+ Joosy.Resources.RESTCollection = (function(_super) {
381
+ __extends(RESTCollection, _super);
382
+
383
+ function RESTCollection() {
384
+ _ref = RESTCollection.__super__.constructor.apply(this, arguments);
385
+ return _ref;
386
+ }
387
+
388
+ RESTCollection.include(Joosy.Modules.Log);
389
+
390
+ RESTCollection.include(Joosy.Modules.Events);
391
+
392
+ RESTCollection.prototype.reload = function(options, callback) {
393
+ var _this = this;
394
+ if (options == null) {
395
+ options = {};
396
+ }
397
+ if (callback == null) {
398
+ callback = false;
399
+ }
400
+ if (Object.isFunction(options)) {
401
+ callback = options;
402
+ options = {};
403
+ }
404
+ return this.model.__query(this.model.collectionPath(options, this.__source), 'GET', options.params, function(data) {
405
+ _this.load(data);
406
+ return typeof callback === "function" ? callback(data) : void 0;
407
+ });
408
+ };
409
+
410
+ RESTCollection.prototype.load = function() {
411
+ var args, res,
412
+ _this = this;
413
+ args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
414
+ res = RESTCollection.__super__.load.apply(this, args);
415
+ this.data.each(function(x) {
416
+ return x.__source = _this.__source;
417
+ });
418
+ return res;
419
+ };
420
+
421
+ return RESTCollection;
422
+
423
+ })(Joosy.Resources.Collection);
424
+
373
425
  }).call(this);
374
426
  (function() {
375
427
  var _ref,
@@ -651,58 +703,6 @@
651
703
 
652
704
  })(Joosy.Resources.Base);
653
705
 
654
- }).call(this);
655
- (function() {
656
- var _ref,
657
- __hasProp = {}.hasOwnProperty,
658
- __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
659
- __slice = [].slice;
660
-
661
- Joosy.Resources.RESTCollection = (function(_super) {
662
- __extends(RESTCollection, _super);
663
-
664
- function RESTCollection() {
665
- _ref = RESTCollection.__super__.constructor.apply(this, arguments);
666
- return _ref;
667
- }
668
-
669
- RESTCollection.include(Joosy.Modules.Log);
670
-
671
- RESTCollection.include(Joosy.Modules.Events);
672
-
673
- RESTCollection.prototype.reload = function(options, callback) {
674
- var _this = this;
675
- if (options == null) {
676
- options = {};
677
- }
678
- if (callback == null) {
679
- callback = false;
680
- }
681
- if (Object.isFunction(options)) {
682
- callback = options;
683
- options = {};
684
- }
685
- return this.model.__query(this.model.collectionPath(options, this.__source), 'GET', options.params, function(data) {
686
- _this.load(data);
687
- return typeof callback === "function" ? callback(data) : void 0;
688
- });
689
- };
690
-
691
- RESTCollection.prototype.load = function() {
692
- var args, res,
693
- _this = this;
694
- args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
695
- res = RESTCollection.__super__.load.apply(this, args);
696
- this.data.each(function(x) {
697
- return x.__source = _this.__source;
698
- });
699
- return res;
700
- };
701
-
702
- return RESTCollection;
703
-
704
- })(Joosy.Resources.Collection);
705
-
706
706
  }).call(this);
707
707
  (function() {
708
708
 
data/build/joosy.js CHANGED
@@ -1959,17 +1959,20 @@
1959
1959
  respond = true;
1960
1960
  }
1961
1961
  if (!history.pushState) {
1962
+ this.config.prefix = this.config.hashSuffix;
1962
1963
  this.config.html5 = false;
1963
1964
  }
1965
+ if (!this.config.html5) {
1966
+ this.config.prefix = this.config.hashSuffix;
1967
+ }
1964
1968
  (_base = this.config).prefix || (_base.prefix = '');
1965
1969
  if (this.config.html5) {
1966
1970
  this.config.prefix = ('/' + this.config.prefix + '/').replace(/\/{2,}/g, '/');
1967
- }
1968
- if (this.config.html5) {
1969
1971
  this.listener = this.bind('popstate pushstate', function() {
1970
1972
  return _this.respond(_this.canonizeLocation());
1971
1973
  });
1972
1974
  } else {
1975
+ this.config.prefix = this.config.prefix.replace(/^\#?\/?/, '').replace(/\/?$/, '');
1973
1976
  $(window).bind('hashchange.JoosyRouter', function() {
1974
1977
  return _this.respond(_this.canonizeLocation());
1975
1978
  });
@@ -1997,31 +2000,24 @@
1997
2000
  }
1998
2001
  path = to;
1999
2002
  if (this.config.html5) {
2000
- if (path[0] === '/') {
2001
- path = path.substr(1);
2002
- }
2003
- path = this.config.prefix + path;
2004
- } else {
2005
- if (path[0] === '#') {
2006
- path = path.substr(1);
2003
+ if (this.config.prefix && path[0] === '/' && !path.match(RegExp("^" + (this.config.prefix.replace(/\/$/, '')) + "(/|$)"))) {
2004
+ path = path.replace(/^\//, this.config.prefix);
2007
2005
  }
2008
- if (this.config.prefix && !path.startsWith(this.config.prefix)) {
2009
- path = this.config.prefix + path;
2010
- }
2011
- }
2012
- if (this.config.html5) {
2013
2006
  history.pushState({}, '', path);
2014
2007
  this.trigger('pushstate');
2015
2008
  } else {
2009
+ if (this.config.prefix && !path.match(RegExp("^#?/?" + this.config.prefix + "(/|$)"))) {
2010
+ path = path.replace(/^\#?\/?/, "" + this.config.prefix + "/");
2011
+ }
2016
2012
  location.hash = path;
2017
2013
  }
2018
2014
  };
2019
2015
 
2020
2016
  Router.canonizeLocation = function() {
2021
2017
  if (this.config.html5) {
2022
- return location.pathname.replace(RegExp("^" + (RegExp.escape(this.config.prefix)) + "?"), '/') + location.search;
2018
+ return location.pathname.replace(RegExp("^(" + this.config.prefix + "?)?/?"), '/') + location.search;
2023
2019
  } else {
2024
- return location.hash.replace(RegExp("^\\#(" + this.config.prefix + ")?\\/?"), '/');
2020
+ return location.hash.replace(RegExp("^#?/?(" + this.config.prefix + "(/|$))?"), '/');
2025
2021
  }
2026
2022
  };
2027
2023
 
data/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "keywords": [
5
5
  "joosy"
6
6
  ],
7
- "version": "1.2.0-alpha.64",
7
+ "version": "1.2.0-alpha.65",
8
8
  "author": "Boris Staal <boris@staal.io>",
9
9
  "homepage": "http://joosy.ws/",
10
10
  "repository": {
@@ -20,11 +20,11 @@
20
20
  "devDependencies": {
21
21
  "coffee-script": "~1.6.3",
22
22
  "sugar": "~1.3.8",
23
- "bower": "~1.1.2",
24
- "mincer": ">= 0.5.5",
23
+ "bower": "~1.2.1",
25
24
  "semver": "~2.1.0",
26
25
  "grunt-coffeelint": "0.0.6",
27
26
  "grunt-release": "~0.3.5",
28
- "grunt-contrib-testem": ">=0.2.0"
27
+ "grunt-contrib-testem": ">=0.4.0",
28
+ "grunt-gh-pages": "git+https://github.com/inossidabile/grunt-gh-pages.git"
29
29
  }
30
30
  }
@@ -1,5 +1,5 @@
1
1
  #= require ./base
2
- #= require ./collection
2
+ #= require ./rest_collection
3
3
 
4
4
  #
5
5
  # Resource with REST/JSON backend
@@ -125,15 +125,28 @@ class Joosy.Router extends Joosy.Module
125
125
  # Inits the routing system and loads the current route
126
126
  #
127
127
  @setup: (@config, @responder, respond=true) ->
128
- @config.html5 = false unless history.pushState
128
+ # Fallback to hashchange if we are unlucky
129
+ # enough to work in IE...
130
+ unless history.pushState
131
+ @config.prefix = @config.hashSuffix
132
+ @config.html5 = false
133
+
134
+ # ... or for some reason it was explicitly turned off
135
+ unless @config.html5
136
+ @config.prefix = @config.hashSuffix
137
+
129
138
  @config.prefix ||= ''
130
- @config.prefix = ('/'+@config.prefix+'/').replace(/\/{2,}/g, '/') if @config.html5
131
139
 
132
140
  if @config.html5
141
+ # Canonical form of HTML5 prefix is '/any/thing/'
142
+ @config.prefix = ('/'+@config.prefix+'/').replace /\/{2,}/g, '/'
143
+
133
144
  @listener = @bind 'popstate pushstate', =>
134
145
  @respond @canonizeLocation()
135
-
136
146
  else
147
+ # Canonical form of hash suffix is 'any/thing'
148
+ @config.prefix = @config.prefix.replace(/^\#?\/?/, '').replace /\/?$/, ''
149
+
137
150
  $(window).bind 'hashchange.JoosyRouter', =>
138
151
  @respond @canonizeLocation()
139
152
 
@@ -169,19 +182,16 @@ class Joosy.Router extends Joosy.Module
169
182
  path = to
170
183
 
171
184
  if @config.html5
172
- path = path.substr(1) if path[0] == '/'
173
- path = @config.prefix+path
174
- else
175
- path = path.substr(1) if path[0] == '#'
176
-
177
- if @config.prefix && !path.startsWith(@config.prefix)
178
- path = @config.prefix + path
179
-
180
- if @config.html5
185
+ # omit html5 relative links
186
+ if @config.prefix && path[0] == '/' && !path.match(RegExp("^#{@config.prefix.replace(/\/$/, '')}(/|$)"))
187
+ path = path.replace /^\//, @config.prefix
181
188
  history.pushState {}, '', path
182
189
  @trigger 'pushstate'
183
190
  else
191
+ if @config.prefix && !path.match(RegExp("^#?/?#{@config.prefix}(/|$)"))
192
+ path = path.replace /^\#?\/?/, "#{@config.prefix}/"
184
193
  location.hash = path
194
+
185
195
  return
186
196
 
187
197
  #
@@ -191,9 +201,9 @@ class Joosy.Router extends Joosy.Module
191
201
  #
192
202
  @canonizeLocation: ->
193
203
  if @config.html5
194
- location.pathname.replace(///^#{RegExp.escape @config.prefix}?///, '/')+location.search
204
+ location.pathname.replace(RegExp("^(#{@config.prefix}?)?/?"), '/')+location.search
195
205
  else
196
- location.hash.replace ///^\#(#{@config.prefix})?\/?///, '/'
206
+ location.hash.replace RegExp("^#?/?(#{@config.prefix}(/|$))?"), '/'
197
207
 
198
208
  #
199
209
  # Compiles one single route
@@ -277,6 +277,41 @@ describe "Joosy.Router", ->
277
277
  expect(Joosy.Helpers.Routes.sectionPagePath(id: 1)).toEqual '/section/page/1'
278
278
  expect(Joosy.Helpers.Routes.sectionPageUrl(id: 1)).toEqual "http://#{location.host}/section/page/1"
279
279
 
280
+ for name, val of { html5: true, hash: false }
281
+ do(name, val) ->
282
+ describe "#{name} prefix", ->
283
+ afterEach ->
284
+ Joosy.Router.reset()
285
+ location.hash = ''
286
+ history.pushState {}, '', pathname
287
+ waits 0
288
+
289
+ beforeEach ->
290
+ Joosy.Router.setup {html5: val, prefix: 'admin', hashSuffix: 'admin'}, @spies.responder, false
291
+ Joosy.Router.map @map
292
+
293
+ it "is considered in path without prefix", ->
294
+ runs -> Joosy.Router.navigate '/base'
295
+ waits 0
296
+ runs ->
297
+ expect(@spies.responder.callCount).toEqual 1
298
+ expect(@spies.responder.args[0][0]).toEqual @spies.base
299
+
300
+ it "is considered in path with prefix", ->
301
+ runs -> Joosy.Router.navigate '/admin/base'
302
+ waits 0
303
+ runs ->
304
+ expect(@spies.responder.callCount).toEqual 1
305
+ expect(@spies.responder.args[0][0]).toEqual @spies.base
306
+
307
+ it "is considered in root path", ->
308
+ runs -> Joosy.Router.navigate '/admin'
309
+ waits 0
310
+ runs ->
311
+ expect(@spies.responder.callCount).toEqual 1
312
+ expect(@spies.responder.args[0][0]).toEqual @spies.root
313
+
314
+
280
315
  describe 'linker', ->
281
316
  it 'defines helper', ->
282
317
  tag = Joosy.Helpers.Routes.linkTo 'test', '/base', class: 'zomg!'
@@ -1,9 +1,11 @@
1
1
  {
2
2
  "dependencies": {
3
3
  "joosy": "<%= joosy %>",
4
- "haml-coffee": "~1.11.1",
5
- "stylus": "~0.32.1",
6
- "nib": "~0.9.1",
4
+
5
+ "haml-coffee": "~1.11.4",
6
+ "stylus": "~0.37.0",
7
+ "nib": "~1.0.0",
8
+
7
9
  "grunt": "~0.4.1",
8
10
  "grunt-cli": "~0.1.9",
9
11
  "grunt-contrib-uglify": "~0.2.2",
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: joosy
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0.alpha.64
4
+ version: 1.2.0.alpha.65
5
5
  platform: ruby
6
6
  authors:
7
7
  - Boris Staal
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2013-08-21 00:00:00.000000000 Z
13
+ date: 2013-08-27 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: sprockets