dugway 0.10.3 → 0.10.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +1 -1
- data/README.md +107 -41
- data/lib/dugway/application.rb +41 -67
- data/lib/dugway/cli/build.rb +16 -16
- data/lib/dugway/cli/templates/source/product.html +1 -1
- data/lib/dugway/contact_form_validator.rb +39 -0
- data/lib/dugway/controller.rb +3 -24
- data/lib/dugway/liquid/filters/default_pagination.rb +2 -2
- data/lib/dugway/liquid/filters/url_filters.rb +15 -48
- data/lib/dugway/path_interpreter.rb +45 -0
- data/lib/dugway/store.rb +8 -8
- data/lib/dugway/theme.rb +18 -18
- data/lib/dugway/version.rb +1 -1
- data/spec/fixtures/store/products.json +1 -1
- data/spec/units/dugway/contact_form_validator_spec.rb +60 -0
- data/spec/units/dugway/liquid/drops/image_drop_spec.rb +1 -1
- data/spec/units/dugway/liquid/drops/product_drop_spec.rb +2 -2
- data/spec/units/dugway/liquid/filters/url_filters_spec.rb +8 -14
- data/spec/units/dugway/path_interpreter_spec.rb +41 -0
- metadata +9 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c7dcecd0162a10e803937e86ecc97601bf6ee155
|
4
|
+
data.tar.gz: 2586fa50d420763edfea6fe51effea36382efd50
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 41f5dc95f6de48a0617e8cb684cb5a017d0780e872d670ef1f9da81c186cd968ccf1599dc4a5796eff931b3cb70bd5abc00484ee6503b4b33ae90adde4f69477
|
7
|
+
data.tar.gz: 8da215f70a623699c2907b8cf1a08efae0b5b0114650621310ea4534519f70d3eccfe49f9a38c4ae8df640da70307c515f799f866e934b99c014859054e9ad9b
|
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -2,23 +2,33 @@
|
|
2
2
|
|
3
3
|
**_The easy way to build Big Cartel themes._**
|
4
4
|
|
5
|
-
Dugway allows you to run your Big Cartel theme on your computer, test it in any
|
5
|
+
Dugway allows you to run your Big Cartel theme on your computer, test it in any
|
6
|
+
browser, write code in your favorite editor, and use fancy new tools like
|
7
|
+
CoffeeScript, Sass, and LESS. It's awesome.
|
6
8
|
|
7
9
|
[![Walkthrough](http://cl.ly/image/101e1z3Y3B1w/Screen%20Shot%202013-04-01%20at%205.04.40%20PM.png)](https://vimeo.com/bigcartel/dugway)
|
8
10
|
|
9
|
-
##
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
* *
|
16
|
-
|
17
|
-
|
11
|
+
## Known Issues & Limitations
|
12
|
+
|
13
|
+
* *You can't currently upload a Dugway build/zip to Big Cartel.* This is next
|
14
|
+
on our list, and is what we built Dugway in preparation for. For now you'll
|
15
|
+
still need to copy/paste theme pages individually in the Big Cartel admin,
|
16
|
+
and host images, fonts, and JavaScript assets separately.
|
17
|
+
* *Big Cartel doesn't currently support custom settings.json.* Since we don't
|
18
|
+
support fully uploadable themes yet (as mentioned above), you can't currently
|
19
|
+
use a custom settings.json. For now you'll need to base your theme off of one
|
20
|
+
of our [default themes](https://github.com/bigcartel-themes) and its
|
21
|
+
settings.json.
|
22
|
+
* *Dugway doesn't currently support all discounts and shipping features.* For
|
23
|
+
now it's best to test those with a live store so it can interact with actual
|
24
|
+
discount and shipping information.
|
18
25
|
|
19
26
|
## Install
|
20
27
|
|
21
|
-
Dugway is Ruby gem so you'll need to have Ruby
|
28
|
+
Dugway is Ruby gem so you'll need to have Ruby 2.0+ installed. Ruby is
|
29
|
+
usually pre-installed on Mac OS X and Linux, and Windows users can install it
|
30
|
+
using [RubyInstaller](http://rubyinstaller.org). From there, simply install the
|
31
|
+
**dugway** gem from the terminal.
|
22
32
|
|
23
33
|
```
|
24
34
|
gem install dugway
|
@@ -32,7 +42,8 @@ With Dugway installed, you can now create a new theme, simply give it a name.
|
|
32
42
|
dugway create mytheme
|
33
43
|
```
|
34
44
|
|
35
|
-
This will create a new directory named *mytheme* that contains a few
|
45
|
+
This will create a new directory named *mytheme* that contains a few
|
46
|
+
configuration files and a starter theme to get you going.
|
36
47
|
|
37
48
|
```
|
38
49
|
mytheme
|
@@ -67,15 +78,30 @@ All of the assets and source code for your theme goes in the **source** director
|
|
67
78
|
|
68
79
|
### HTML
|
69
80
|
|
70
|
-
Develop the HTML for your theme using our [Theme
|
81
|
+
Develop the HTML for your theme using our [Theme
|
82
|
+
API](http://help.bigcartel.com/developers/themes/). Barebones versions of all
|
83
|
+
of the required HTML pages for your theme are provided by default, so feel free
|
84
|
+
to expand on those or replace them entirely. Note that the **checkout.html**
|
85
|
+
and **success.html** pages are only used when
|
86
|
+
[PayPal Standard checkout](https://help.bigcartel.com/basics/settings/#paypal-standard) is enabled.
|
71
87
|
|
72
88
|
### CSS & JavaScript
|
73
89
|
|
74
|
-
All CSS for your theme is handled by the **theme.css** file, and all JavaScript
|
90
|
+
All CSS for your theme is handled by the **theme.css** file, and all JavaScript
|
91
|
+
by **theme.js**. If you don't have much CSS or JavaScript, or you're just a
|
92
|
+
glutton for punishment, you could simply put all of your code in these two
|
93
|
+
files. However, we recommend you use [Sprockets](#using-sprockets) to break
|
94
|
+
your code into multiple files in separate directories.
|
75
95
|
|
76
96
|
#### Using Sprockets
|
77
97
|
|
78
|
-
[Sprockets](https://github.com/sstephenson/sprockets) allows you to bring in
|
98
|
+
[Sprockets](https://github.com/sstephenson/sprockets) allows you to bring in
|
99
|
+
CSS and JavaScript from different directories into a single file. We've created
|
100
|
+
**stylesheets** and **javascripts** directories by default that you can put
|
101
|
+
your code in, but you could delete those and put files anywhere you'd like.
|
102
|
+
After that, use [Sprockets
|
103
|
+
directives](https://github.com/sstephenson/sprockets#the-directive-processor)
|
104
|
+
to package them into **theme.css** and **theme.js**.
|
79
105
|
|
80
106
|
##### theme.css
|
81
107
|
|
@@ -95,39 +121,59 @@ All CSS for your theme is handled by the **theme.css** file, and all JavaScript
|
|
95
121
|
|
96
122
|
#### Using Sass, Compass, LESS, and CoffeeScript
|
97
123
|
|
98
|
-
Dugway also allows you to use [Sass](http://sass-lang.com) in your separate
|
124
|
+
Dugway also allows you to use [Sass](http://sass-lang.com) in your separate
|
125
|
+
files by appending the **.sass** or **.scss** extension after **.css**. You can
|
126
|
+
even use [Compass](http://compass-style.org/) right out of the box to help
|
127
|
+
author your stylesheets by utilizing its mixins for CSS3, typography, and its
|
128
|
+
utilities.
|
99
129
|
|
100
|
-
Prefer [LESS](http://lesscss.org)? No problem, you'll just need to create a
|
130
|
+
Prefer [LESS](http://lesscss.org)? No problem, you'll just need to create a
|
131
|
+
[Gemfile like this one](https://gist.github.com/mattwigham/5569898) in the
|
132
|
+
root directory of your theme, run ```bundle install```, and append the
|
133
|
+
**.less** extension to your CSS files.
|
101
134
|
|
102
|
-
And finally, for you JavaScript folks, we've baked
|
135
|
+
And finally, for you JavaScript folks, we've baked
|
136
|
+
[CoffeeScript](http://coffeescript.org) support right in. Just append the
|
137
|
+
**.coffee** extension after **.js** to your separate JS files.
|
103
138
|
|
104
139
|
#### Embedding CSS & JavaScript
|
105
140
|
|
106
|
-
You can embed the CSS and JavaScript into your theme by passing the theme
|
141
|
+
You can embed the CSS and JavaScript into your theme by passing the theme
|
142
|
+
variable to the
|
143
|
+
[theme_css_url](http://help.bigcartel.com/developers/themes/#themecssurltheme)
|
144
|
+
and [theme_js_url](http://help.bigcartel.com/developers/themes/#themejsurlname)
|
145
|
+
filters.
|
107
146
|
|
108
147
|
##### CSS (theme.css)
|
109
148
|
|
110
|
-
```html
|
111
|
-
|
112
|
-
```
|
149
|
+
```html <link href="{{ theme | theme_css_url }}" media="screen"
|
150
|
+
rel="stylesheet" type="text/css"> ```
|
113
151
|
|
114
152
|
##### JavaScript (theme.js)
|
115
153
|
|
116
|
-
```html
|
117
|
-
|
118
|
-
```
|
154
|
+
```html <script src="{{ theme | theme_js_url }}"
|
155
|
+
type="text/javascript"></script> ```
|
119
156
|
|
120
157
|
### Images
|
121
158
|
|
122
|
-
And as you've probably guessed by now, all images for your theme go in the
|
159
|
+
And as you've probably guessed by now, all images for your theme go in the
|
160
|
+
**images** directory. You can reference an image in your code by passing its
|
161
|
+
name to the
|
162
|
+
[theme_image_url](http://help.bigcartel.com/developers/themes/#themeimageurlname)
|
163
|
+
filter.
|
123
164
|
|
124
|
-
```
|
125
|
-
{{ 'sample.png' | theme_image_url }}
|
126
|
-
```
|
165
|
+
``` {{ 'sample.png' | theme_image_url }} ```
|
127
166
|
|
128
167
|
### Fonts
|
129
168
|
|
130
|
-
Fonts work more or less the same as images. Place font files (say if you have
|
169
|
+
Fonts work more or less the same as images. Place font files (say if you have
|
170
|
+
created a custom icon font) in the **fonts** directory. Reference them by
|
171
|
+
passing its name to the `theme_font_url` filter. Please be aware of licensing
|
172
|
+
restrictions. If you're using a font from a forge and don't have permission to
|
173
|
+
host the files directly or have restrictions about only making them available
|
174
|
+
to certain domains, you will need to use another mechanism for hosting your
|
175
|
+
fonts. Any font uploaded as part of a Dugway bundle will essentialy be publicly
|
176
|
+
available and not CORS-restricted to specific domains.
|
131
177
|
|
132
178
|
```
|
133
179
|
{{ 'myfont.woff' | theme_font_url }}
|
@@ -135,31 +181,46 @@ Fonts work more or less the same as images. Place font files (say if you have cr
|
|
135
181
|
|
136
182
|
### Settings
|
137
183
|
|
138
|
-
Set your theme's name, version, and customizable options in the
|
184
|
+
Set your theme's name, version, and customizable options in the
|
185
|
+
**settings.json** file. We'll be documenting more about this soon, but for now
|
186
|
+
see the starter file generated for you, and check out our [default
|
187
|
+
themes](https://github.com/bigcartel-themes).
|
139
188
|
|
140
189
|
## Running your theme
|
141
190
|
|
142
191
|
Run your theme in any browser by starting the Dugway server:
|
143
192
|
|
144
|
-
```
|
145
|
-
dugway server
|
146
|
-
```
|
193
|
+
``` dugway server ```
|
147
194
|
|
148
|
-
By default this will serve your theme at http://0.0.0.0:9292. You can then stop
|
195
|
+
By default this will serve your theme at http://0.0.0.0:9292. You can then stop
|
196
|
+
the server by hitting CTRL+C.
|
149
197
|
|
150
198
|
### Pow
|
151
199
|
|
152
|
-
Tired of all the manual starting and stopping? Good news, Dugway is built on
|
200
|
+
Tired of all the manual starting and stopping? Good news, Dugway is built on
|
201
|
+
top of Rack, which means you can use [Pow](http://pow.cx) on Mac. This also
|
202
|
+
allows you to access your theme at a pretty URL like _mytheme.dev_.
|
153
203
|
|
154
204
|
## Testing your theme
|
155
205
|
|
156
|
-
Part of building a great theme is making sure it works well in a variety of
|
206
|
+
Part of building a great theme is making sure it works well in a variety of
|
207
|
+
contexts and with a variety of content. Dugway makes it easy to test your
|
208
|
+
theme's versatility by utilizing the **.dugway.json** file. This file will be
|
209
|
+
specific to your computer for your own testing, and shouldn't be checked into
|
210
|
+
source control.
|
157
211
|
|
158
|
-
*Note:* changing **.dugway.json** will require you to restart the
|
212
|
+
*Note:* changing **.dugway.json** will require you to restart the
|
213
|
+
[server](#running-your-theme).
|
159
214
|
|
160
215
|
### Store content
|
161
216
|
|
162
|
-
The best way to see your theme under a different light is by previewing it with
|
217
|
+
The best way to see your theme under a different light is by previewing it with
|
218
|
+
a different store's products, categories, pages, currency, and other content.
|
219
|
+
To do this, simply set the **store.subdomain** variable in **.dugway.json** to
|
220
|
+
any Big Cartel store's subdomain, and Dugway will bring in their content using
|
221
|
+
the standard [Big Cartel API](http://help.bigcartel.com/developers/api/). By
|
222
|
+
default we use **dugway** for
|
223
|
+
[dugway.bigcartel.com](http://dugway.bigcartel.com).
|
163
224
|
|
164
225
|
```json
|
165
226
|
"store": {
|
@@ -171,7 +232,11 @@ The best way to see your theme under a different light is by previewing it with
|
|
171
232
|
|
172
233
|
### Store customization
|
173
234
|
|
174
|
-
Another important thing to consider is how store owners will customize your
|
235
|
+
Another important thing to consider is how store owners will customize your
|
236
|
+
theme. You establish what can be customized in your [settings.json](#settings)
|
237
|
+
file, and Dugway allows you to simulate potential values people could choose by
|
238
|
+
setting them in the **customization** variable in **.dugway.json**. By default
|
239
|
+
we use the **default** values from your **[settings.json](#settings)** file.
|
175
240
|
|
176
241
|
```json
|
177
242
|
"customization": {
|
@@ -194,4 +259,5 @@ When you're finished with a new version of your theme, it's time to build it.
|
|
194
259
|
dugway build
|
195
260
|
```
|
196
261
|
|
197
|
-
This will create a zip file for the current version in your **build** directory
|
262
|
+
This will create a zip file for the current version in your **build** directory
|
263
|
+
containing all HTML, images, fonts, and packaged JS and CSS.
|
data/lib/dugway/application.rb
CHANGED
@@ -1,15 +1,13 @@
|
|
1
1
|
require 'dugway/controller'
|
2
|
+
require 'dugway/contact_form_validator'
|
2
3
|
|
3
4
|
module Dugway
|
4
5
|
class Application < Controller
|
5
|
-
# Home
|
6
6
|
|
7
7
|
get '/' do
|
8
8
|
render_page
|
9
9
|
end
|
10
10
|
|
11
|
-
# Products
|
12
|
-
|
13
11
|
get '/products(.js)' do
|
14
12
|
if request.html?
|
15
13
|
render_page
|
@@ -19,66 +17,35 @@ module Dugway
|
|
19
17
|
end
|
20
18
|
|
21
19
|
get '/category/:category(.js)' do
|
22
|
-
|
23
|
-
|
24
|
-
page['name'] = category['name']
|
25
|
-
render_page(:category => category)
|
26
|
-
elsif request.js?
|
27
|
-
render_json(store.category_products(params[:category]))
|
28
|
-
end
|
29
|
-
else
|
30
|
-
render_not_found
|
31
|
-
end
|
20
|
+
render_not_found unless category = store.category(params[:category])
|
21
|
+
render_artist_category_response(category, :category)
|
32
22
|
end
|
33
23
|
|
34
24
|
get '/artist/:artist(.js)' do
|
35
|
-
|
36
|
-
|
37
|
-
page['name'] = artist['name']
|
38
|
-
render_page(:artist => artist)
|
39
|
-
elsif request.js?
|
40
|
-
render_json(store.artist_products(params[:artist]))
|
41
|
-
end
|
42
|
-
else
|
43
|
-
render_not_found
|
44
|
-
end
|
25
|
+
render_not_found unless artist = store.artist(params[:artist])
|
26
|
+
render_artist_category_response(artist, :artist)
|
45
27
|
end
|
46
28
|
|
47
|
-
# Product
|
48
|
-
|
49
29
|
get '/product/:product(.js)' do
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
render_json(product)
|
56
|
-
end
|
57
|
-
else
|
58
|
-
render_not_found
|
30
|
+
render_not_found unless product = store.product(params[:product])
|
31
|
+
if request.html?
|
32
|
+
set_page_name_and_render_page(product, :product)
|
33
|
+
elsif request.js?
|
34
|
+
render_json(product)
|
59
35
|
end
|
60
36
|
end
|
61
37
|
|
62
|
-
# Cart
|
63
|
-
|
64
38
|
any '/cart(.js)' do
|
65
|
-
|
66
|
-
|
67
|
-
end
|
39
|
+
cart.update(cart_params) if cart_params
|
40
|
+
redirect_to('/checkout') if params[:checkout]
|
68
41
|
|
69
|
-
if
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
render_page
|
74
|
-
elsif request.js?
|
75
|
-
render_json(cart)
|
76
|
-
end
|
42
|
+
if request.html?
|
43
|
+
render_page
|
44
|
+
elsif request.js?
|
45
|
+
render_json(cart)
|
77
46
|
end
|
78
47
|
end
|
79
48
|
|
80
|
-
# Checkout
|
81
|
-
|
82
49
|
any '/checkout' do
|
83
50
|
if cart.empty?
|
84
51
|
error('Must have at least one product to checkout')
|
@@ -88,8 +55,6 @@ module Dugway
|
|
88
55
|
end
|
89
56
|
end
|
90
57
|
|
91
|
-
# Success
|
92
|
-
|
93
58
|
get '/success' do
|
94
59
|
render_page
|
95
60
|
end
|
@@ -100,38 +65,23 @@ module Dugway
|
|
100
65
|
render_page
|
101
66
|
end
|
102
67
|
|
103
|
-
# Contact
|
104
|
-
|
105
68
|
get '/contact' do
|
106
69
|
render_page
|
107
70
|
end
|
108
71
|
|
109
72
|
post '/contact' do
|
110
|
-
if
|
111
|
-
error('All fields are required')
|
112
|
-
elsif !(params[:email] =~ /^([^@\s]+)@((?:[-a-zA-Z0-9]+\.)+[a-zA-Z]{2,})$/)
|
113
|
-
error('Invalid email address')
|
114
|
-
elsif !(params[:captcha] =~ /^rQ9pC$/i)
|
115
|
-
error('Spam check was incorrect')
|
116
|
-
end
|
117
|
-
|
73
|
+
error(contact_form_error) if contact_form_error
|
118
74
|
render_page
|
119
75
|
end
|
120
76
|
|
121
|
-
# Maintenance
|
122
|
-
|
123
77
|
get '/maintenance' do
|
124
78
|
render_page
|
125
79
|
end
|
126
80
|
|
127
|
-
# Custom page
|
128
|
-
|
129
81
|
get '/:permalink' do
|
130
82
|
render_page
|
131
83
|
end
|
132
84
|
|
133
|
-
# Assets
|
134
|
-
|
135
85
|
get '/theme.css' do
|
136
86
|
render_file('theme.css')
|
137
87
|
end
|
@@ -143,5 +93,29 @@ module Dugway
|
|
143
93
|
get %r{^/images|fonts/.+$} do
|
144
94
|
Rack::File.new(Dugway.source_dir).call(request.env)
|
145
95
|
end
|
96
|
+
|
97
|
+
private
|
98
|
+
|
99
|
+
def self.cart_params
|
100
|
+
params[:cart].try(:with_indifferent_access)
|
101
|
+
end
|
102
|
+
|
103
|
+
def self.contact_form_error
|
104
|
+
ContactFormValidator.new(params).error_message
|
105
|
+
end
|
106
|
+
|
107
|
+
def self.render_artist_category_response(object, type)
|
108
|
+
if request.html?
|
109
|
+
set_page_name_and_render_page(object, type)
|
110
|
+
elsif request.js?
|
111
|
+
render_json(store.send("#{type}_products", params[type]))
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def self.set_page_name_and_render_page(object, type)
|
116
|
+
page['name'] = object['name']
|
117
|
+
render_page(type => object)
|
118
|
+
end
|
119
|
+
|
146
120
|
end
|
147
121
|
end
|
data/lib/dugway/cli/build.rb
CHANGED
@@ -4,50 +4,50 @@ module Dugway
|
|
4
4
|
module Cli
|
5
5
|
class Build < Thor::Group
|
6
6
|
include Thor::Actions
|
7
|
-
|
7
|
+
|
8
8
|
def self.source_root
|
9
9
|
File.join(Dir.pwd, 'source')
|
10
10
|
end
|
11
|
-
|
11
|
+
|
12
12
|
def self.destination_root
|
13
13
|
File.join(Dir.pwd, 'build')
|
14
14
|
end
|
15
|
-
|
15
|
+
|
16
16
|
def validate
|
17
17
|
unless theme.valid?
|
18
18
|
theme.errors.each { |error| say(error, :red) }
|
19
19
|
raise "Theme is invalid"
|
20
20
|
end
|
21
21
|
end
|
22
|
-
|
22
|
+
|
23
23
|
def create_destination
|
24
24
|
empty_directory self.class.destination_root
|
25
25
|
end
|
26
|
-
|
26
|
+
|
27
27
|
def build
|
28
|
-
Zip::ZipFile.open(build_file, Zip::ZipFile::CREATE)
|
29
|
-
theme.files.each
|
30
|
-
zipfile.get_output_stream(file)
|
28
|
+
Zip::ZipFile.open(build_file, Zip::ZipFile::CREATE) do |zipfile|
|
29
|
+
theme.files.each do |file|
|
30
|
+
zipfile.get_output_stream(file) do |f|
|
31
31
|
f << theme.build_file(file)
|
32
|
-
|
33
|
-
|
34
|
-
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
35
|
end
|
36
|
-
|
36
|
+
|
37
37
|
def success
|
38
38
|
say_status(:create, "build/#{ build_name }")
|
39
39
|
end
|
40
|
-
|
40
|
+
|
41
41
|
private
|
42
|
-
|
42
|
+
|
43
43
|
def theme
|
44
44
|
@theme ||= Dugway.theme
|
45
45
|
end
|
46
|
-
|
46
|
+
|
47
47
|
def build_name
|
48
48
|
@build_name ||= "#{ theme.name.parameterize }-#{ theme.version }.zip"
|
49
49
|
end
|
50
|
-
|
50
|
+
|
51
51
|
def build_file
|
52
52
|
@build_file ||= File.join(self.class.destination_root, build_name)
|
53
53
|
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Dugway
|
2
|
+
class ContactFormValidator
|
3
|
+
|
4
|
+
attr_accessor :params
|
5
|
+
|
6
|
+
def initialize(params)
|
7
|
+
@params = params
|
8
|
+
end
|
9
|
+
|
10
|
+
def error_message
|
11
|
+
if required_fields.any? { |f| params[f].blank? }
|
12
|
+
'All fields are required'
|
13
|
+
elsif param_does_not_match(:email, email_format)
|
14
|
+
'Invalid email address'
|
15
|
+
elsif param_does_not_match(:captcha, captcha_format)
|
16
|
+
'Spam check was incorrect'
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def required_fields
|
23
|
+
[ :name, :email, :subject, :message, :captcha ]
|
24
|
+
end
|
25
|
+
|
26
|
+
def email_format
|
27
|
+
/^([^@\s]+)@((?:[-a-zA-Z0-9]+\.)+[a-zA-Z]{2,})$/
|
28
|
+
end
|
29
|
+
|
30
|
+
def captcha_format
|
31
|
+
/^rQ9pC$/i
|
32
|
+
end
|
33
|
+
|
34
|
+
def param_does_not_match(param_name, regex)
|
35
|
+
!(params[param_name.to_sym] =~ regex)
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
data/lib/dugway/controller.rb
CHANGED
@@ -1,9 +1,8 @@
|
|
1
1
|
require 'rack/mount'
|
2
|
+
require 'dugway/path_interpreter'
|
2
3
|
|
3
4
|
module Dugway
|
4
5
|
class Controller
|
5
|
-
PERMALINK_REGEX = %r{[a-z0-9\-_]+}
|
6
|
-
FORMAT_REGEX = %r{(\.(?<format>js))?}
|
7
6
|
|
8
7
|
class << self
|
9
8
|
def routes
|
@@ -25,33 +24,12 @@ module Dugway
|
|
25
24
|
end
|
26
25
|
}, {
|
27
26
|
:request_method => method,
|
28
|
-
:path_info =>
|
27
|
+
:path_info => PathInterpreter.new(path).call
|
29
28
|
})
|
30
29
|
|
31
30
|
routes.rehash
|
32
31
|
end
|
33
32
|
|
34
|
-
def interpret_path(path)
|
35
|
-
if path.is_a?(String)
|
36
|
-
case path
|
37
|
-
# category/artist/product
|
38
|
-
when %r{^/(\w+)/:(#{ PERMALINK_REGEX })\(\.js\)}
|
39
|
-
%r{^/#{ $1 }/(?<#{ $2 }>#{ PERMALINK_REGEX })#{ FORMAT_REGEX }$}
|
40
|
-
# products/cart
|
41
|
-
when %r{^/(\w+)\(\.js\)$}
|
42
|
-
%r{^/#{ $1 }#{ FORMAT_REGEX }$}
|
43
|
-
# custom pages
|
44
|
-
when %r{^/:(#{ PERMALINK_REGEX })}
|
45
|
-
%r{^/(?<#{ $1 }>#{ PERMALINK_REGEX })$}
|
46
|
-
# everything else
|
47
|
-
else
|
48
|
-
%r{^#{ path }$}
|
49
|
-
end
|
50
|
-
else
|
51
|
-
path
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
33
|
def get(path, &block)
|
56
34
|
route('GET', path, &block)
|
57
35
|
end
|
@@ -142,4 +120,5 @@ module Dugway
|
|
142
120
|
self.class.routes.call(env)
|
143
121
|
end
|
144
122
|
end
|
123
|
+
|
145
124
|
end
|
@@ -12,13 +12,13 @@ module Dugway
|
|
12
12
|
html << %(<span class="previous disabled">#{ prev_label }</span>)
|
13
13
|
end
|
14
14
|
|
15
|
-
paginate['parts'].each
|
15
|
+
paginate['parts'].each do |part|
|
16
16
|
if part['is_link']
|
17
17
|
html << %(<a href="#{ part['url'] }">#{ part['title'] }</a>)
|
18
18
|
else
|
19
19
|
html << %(<span class="#{ part['title'] == paginate['current_page'].to_s ? 'current' : 'gap' }">#{ part['title'] }</span>)
|
20
20
|
end
|
21
|
-
|
21
|
+
end
|
22
22
|
|
23
23
|
next_label = next_label.blank? ? paginate['next']['title'] : next_label
|
24
24
|
if paginate['next']['is_link']
|
@@ -8,47 +8,14 @@ module Dugway
|
|
8
8
|
content_tag :a, text, options
|
9
9
|
end
|
10
10
|
|
11
|
-
# To get max_w-100
|
12
|
-
# Eg product.primary_image | product_image_url | constrain : '100'
|
13
|
-
# To get max_h-100
|
14
|
-
# Eg product.primary_image | product_image_url | constrain : '-', '100'
|
15
|
-
# To get max_h-100+max_w-100
|
16
|
-
# Eg product.primary_image | product_image_url | constrain : '100', '100'
|
17
11
|
def constrain(url = nil, width = 0, height = 0)
|
18
|
-
if url
|
19
|
-
parsed_url = URI.parse(url)
|
20
|
-
path_parts = parsed_url.path.split('/')
|
21
|
-
|
22
|
-
width = width.to_i
|
23
|
-
height = height.to_i
|
24
|
-
|
25
|
-
path_parts.slice(-2).tap do |size|
|
26
|
-
unless width == 0 && height == 0
|
27
|
-
size.gsub!(/(max_w-)\d+/) do |match|
|
28
|
-
width == 0 ? '' : "#{ $1 }#{ width }"
|
29
|
-
end
|
30
|
-
|
31
|
-
size.gsub!(/(max_h-)\d+/) do |match|
|
32
|
-
height == 0 ? '' : "#{ $1 }#{ height }"
|
33
|
-
end
|
34
|
-
|
35
|
-
size.gsub!(/\+/, '') if width == 0 || height == 0
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
parsed_url.path = path_parts.join('/')
|
40
|
-
parsed_url.to_s
|
41
|
-
end
|
12
|
+
image_url url, width, height if url
|
42
13
|
end
|
43
14
|
|
44
15
|
def product_image_url(image = nil, size = nil)
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
image_url_hash('http://images.cdn.bigcartel.com/missing/-/missing.png', height, width)
|
49
|
-
else
|
50
|
-
image_url_hash(image['url'], height, width)
|
51
|
-
end
|
16
|
+
url = image ? image['url'] : 'http://images.bigcartel.com/missing.png'
|
17
|
+
size = legacy_size_for(size)
|
18
|
+
image_url url, size, size
|
52
19
|
end
|
53
20
|
|
54
21
|
def theme_js_url(name)
|
@@ -85,20 +52,20 @@ module Dugway
|
|
85
52
|
options
|
86
53
|
end
|
87
54
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
55
|
+
def image_url(url, width, height)
|
56
|
+
uri = URI.parse(url)
|
57
|
+
query_hash = Rack::Utils.parse_nested_query uri.query
|
58
|
+
uri.query = query_hash.update('w' => width, 'h' => height).to_query
|
59
|
+
uri.to_s
|
92
60
|
end
|
93
61
|
|
94
62
|
def legacy_size_for(size)
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
})[size.to_sym]
|
63
|
+
case size
|
64
|
+
when 'large' then 300
|
65
|
+
when 'medium' then 175
|
66
|
+
when 'thumb' then 75
|
67
|
+
else 1000
|
68
|
+
end
|
102
69
|
end
|
103
70
|
end
|
104
71
|
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Dugway
|
2
|
+
class PathInterpreter
|
3
|
+
attr_accessor :path
|
4
|
+
|
5
|
+
def initialize(path)
|
6
|
+
@path = path
|
7
|
+
end
|
8
|
+
|
9
|
+
def call
|
10
|
+
return path unless path.is_a?(String)
|
11
|
+
case path
|
12
|
+
when category_artist_or_product_path
|
13
|
+
%r{^/#{$1}/(?<#{$2}>#{permalink_regex})#{format_regex}$}
|
14
|
+
when product_or_cart_path
|
15
|
+
%r{^/#{$1}#{format_regex}$}
|
16
|
+
when custom_page_path
|
17
|
+
%r{^/(?<#{$1}>#{permalink_regex})$}
|
18
|
+
else
|
19
|
+
%r{^#{path}$}
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def permalink_regex
|
26
|
+
%r{[a-z0-9\-_]+}
|
27
|
+
end
|
28
|
+
|
29
|
+
def format_regex
|
30
|
+
%r{(\.(?<format>js))?}
|
31
|
+
end
|
32
|
+
|
33
|
+
def category_artist_or_product_path
|
34
|
+
%r{^/(\w+)/:(#{permalink_regex})\(\.js\)}
|
35
|
+
end
|
36
|
+
|
37
|
+
def product_or_cart_path
|
38
|
+
%r{^/(\w+)\(\.js\)$}
|
39
|
+
end
|
40
|
+
|
41
|
+
def custom_page_path
|
42
|
+
%r{^/:(#{permalink_regex})}
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
data/lib/dugway/store.rb
CHANGED
@@ -78,33 +78,33 @@ module Dugway
|
|
78
78
|
end
|
79
79
|
|
80
80
|
def product_and_option(option_id)
|
81
|
-
products.each
|
82
|
-
product['options'].each
|
81
|
+
products.each do |product|
|
82
|
+
product['options'].each do |option|
|
83
83
|
if option['id'] == option_id
|
84
84
|
return product, option
|
85
85
|
end
|
86
|
-
|
87
|
-
|
86
|
+
end
|
87
|
+
end
|
88
88
|
|
89
89
|
nil
|
90
90
|
end
|
91
91
|
|
92
92
|
def previous_product(permalink)
|
93
|
-
products.each_with_index
|
93
|
+
products.each_with_index do |product, index|
|
94
94
|
if product['permalink'] == permalink && index > 0 && previous_product = products[index - 1]
|
95
95
|
return previous_product
|
96
96
|
end
|
97
|
-
|
97
|
+
end
|
98
98
|
|
99
99
|
nil
|
100
100
|
end
|
101
101
|
|
102
102
|
def next_product(permalink)
|
103
|
-
products.each_with_index
|
103
|
+
products.each_with_index do |product, index|
|
104
104
|
if product['permalink'] == permalink && (index + 1) < products.size && next_product = products[index + 1]
|
105
105
|
return next_product
|
106
106
|
end
|
107
|
-
|
107
|
+
end
|
108
108
|
|
109
109
|
nil
|
110
110
|
end
|
data/lib/dugway/theme.rb
CHANGED
@@ -36,13 +36,13 @@ module Dugway
|
|
36
36
|
end
|
37
37
|
|
38
38
|
def customization
|
39
|
-
Hash.new.tap
|
40
|
-
%w( fonts colors options images image_sets ).each
|
39
|
+
Hash.new.tap do |customization|
|
40
|
+
%w( fonts colors options images image_sets ).each do |type|
|
41
41
|
customization.update(customization_for_type(type))
|
42
|
-
|
42
|
+
end
|
43
43
|
|
44
44
|
customization.update(@overridden_customization)
|
45
|
-
|
45
|
+
end
|
46
46
|
end
|
47
47
|
|
48
48
|
def name
|
@@ -78,23 +78,23 @@ module Dugway
|
|
78
78
|
end
|
79
79
|
|
80
80
|
def image_files
|
81
|
-
Dir.glob(File.join(source_dir, 'images', '**', '*.{png,jpg,jpeg,gif,ico,svg}')).map
|
81
|
+
Dir.glob(File.join(source_dir, 'images', '**', '*.{png,jpg,jpeg,gif,ico,svg}')).map do |i|
|
82
82
|
i.gsub(source_dir, '')[1..-1]
|
83
|
-
|
83
|
+
end
|
84
84
|
end
|
85
85
|
|
86
86
|
def font_files
|
87
|
-
Dir.glob(File.join(source_dir, 'fonts', '**', '*.{eot,ttf,otf,woff,svg}')).map
|
87
|
+
Dir.glob(File.join(source_dir, 'fonts', '**', '*.{eot,ttf,otf,woff,svg}')).map do |i|
|
88
88
|
i.gsub(source_dir, '')[1..-1]
|
89
|
-
|
89
|
+
end
|
90
90
|
end
|
91
91
|
|
92
92
|
def valid?
|
93
93
|
@errors = []
|
94
94
|
|
95
|
-
REQUIRED_FILES.each
|
95
|
+
REQUIRED_FILES.each do |file|
|
96
96
|
@errors << "Missing source/#{ file }" if read_source_file(file).nil?
|
97
|
-
|
97
|
+
end
|
98
98
|
|
99
99
|
@errors << 'Missing theme name in source/settings.json' if name.blank?
|
100
100
|
@errors << 'Invalid theme version in source/settings.json (ex: 1.0.3)' unless !!(version =~ /\d+\.\d+\.\d+/)
|
@@ -135,31 +135,31 @@ module Dugway
|
|
135
135
|
end
|
136
136
|
|
137
137
|
def customization_for_type(type)
|
138
|
-
Hash.new.tap
|
138
|
+
Hash.new.tap do |hash|
|
139
139
|
if settings.has_key?(type)
|
140
140
|
case type
|
141
141
|
when 'images'
|
142
|
-
settings[type].each
|
142
|
+
settings[type].each do |setting|
|
143
143
|
if name = setting['default']
|
144
144
|
hash[setting['variable']] = { :url => image_path_from_setting_name(name), :width => 1, :height => 1 }
|
145
145
|
end
|
146
|
-
|
146
|
+
end
|
147
147
|
when 'image_sets'
|
148
|
-
settings[type].each
|
148
|
+
settings[type].each do |setting|
|
149
149
|
if defaults = setting['default'] || setting['defaults']
|
150
150
|
hash[setting['variable']] ||= []
|
151
151
|
defaults.each do |name|
|
152
152
|
hash[setting['variable']] << { :url => image_path_from_setting_name(name), :width => 1, :height => 1 }
|
153
153
|
end
|
154
154
|
end
|
155
|
-
|
155
|
+
end
|
156
156
|
else
|
157
|
-
settings[type].each
|
157
|
+
settings[type].each do |setting|
|
158
158
|
hash[setting['variable']] = setting['default']
|
159
|
-
|
159
|
+
end
|
160
160
|
end
|
161
161
|
end
|
162
|
-
|
162
|
+
end
|
163
163
|
end
|
164
164
|
|
165
165
|
def image_path_from_setting_name(name)
|
data/lib/dugway/version.rb
CHANGED
@@ -1 +1 @@
|
|
1
|
-
[{"price":10.0,"status":"active","created_at":"2013-02-10T19:28:11-07:00","tax":0.0,"position":1,"artists":[{"permalink":"artist-one","name":"Artist One","id":176141,"url":"/artist/artist-one"}],"shipping":[{"amount_with_others":5.0,"country":{"name":"United States","id":43,"code":"US"},"amount_alone":10.0},{"amount_with_others":10.0,"amount_alone":20.0}],"images":[{"width":475,"height":500,"secure_url":"https://
|
1
|
+
[{"price":10.0,"status":"active","created_at":"2013-02-10T19:28:11-07:00","tax":0.0,"position":1,"artists":[{"permalink":"artist-one","name":"Artist One","id":176141,"url":"/artist/artist-one"}],"shipping":[{"amount_with_others":5.0,"country":{"name":"United States","id":43,"code":"US"},"amount_alone":10.0},{"amount_with_others":10.0,"amount_alone":20.0}],"images":[{"width":475,"height":500,"secure_url":"https://images.bigcartel.com/product_images/92599166/mens_tee_1.jpg","url":"http://images.bigcartel.com/product_images/92599166/mens_tee_1.jpg"},{"width":475,"height":475,"secure_url":"https://images.bigcartel.com/product_images/92599178/mens_tee_2.jpg","url":"http://images.bigcartel.com/product_images/92599178/mens_tee_2.jpg"},{"width":475,"height":475,"secure_url":"https://images.bigcartel.com/product_images/92599196/mens_tee_3.jpg","url":"http://images.bigcartel.com/product_images/92599196/mens_tee_3.jpg"},{"width":475,"height":475,"secure_url":"https://images.bigcartel.com/product_images/92599214/mens_tee_4.jpg","url":"http://images.bigcartel.com/product_images/92599214/mens_tee_4.jpg"},{"width":475,"height":475,"secure_url":"https://images.bigcartel.com/product_images/92599226/mens_tee_5.jpg","url":"http://images.bigcartel.com/product_images/92599226/mens_tee_5.jpg"}],"categories":[{"permalink":"tees","name":"Tees","id":4615193,"url":"/category/tees"}],"on_sale":false,"permalink":"my-product","name":"My Product","default_price":10.0,"id":9422939,"description":"This is a description of my product.","options":[{"price":10.0,"sold_out":false,"has_custom_price":false,"name":"Small","id":29474321},{"price":10.0,"sold_out":false,"has_custom_price":false,"name":"Medium","id":29474324},{"price":10.0,"sold_out":true,"has_custom_price":false,"name":"Large","id":29474327},{"price":15.0,"sold_out":false,"has_custom_price":true,"name":"X-Large","id":29474330}],"url":"/product/my-product"},{"price":10.0,"status":"active","created_at":"2013-03-02T10:05:34-07:00","tax":0.0,"position":2,"artists":[{"permalink":"artist-two","name":"Artist Two","id":176144,"url":"/artist/artist-two"}],"images":[{"width":475,"height":475,"secure_url":"https://images.bigcartel.com/product_images/95272745/mens_tee_8.jpg","url":"http://images.bigcartel.com/product_images/95272745/mens_tee_8.jpg"}],"categories":[{"permalink":"tees","name":"Tees","id":4615193,"url":"/category/tees"}],"on_sale":false,"permalink":"my-tee","name":"My Tee","default_price":10.0,"id":9696017,"description":"This is my cool tee shirt.","options":[{"price":10.0,"sold_out":false,"has_custom_price":false,"name":"Small","id":30344519},{"price":10.0,"sold_out":false,"has_custom_price":false,"name":"Medium","id":30344522},{"price":15.0,"sold_out":false,"has_custom_price":true,"name":"Large","id":30344525}],"url":"/product/my-tee"},{"price":20.0,"status":"active","created_at":"2013-03-02T10:06:22-07:00","tax":0.0,"position":3,"artists":[],"categories":[{"permalink":"prints","name":"Prints","id":4615190,"url":"/category/prints"}],"on_sale":true,"permalink":"print","name":"Print","default_price":20.0,"id":9696032,"description":"This is my print.","options":[{"price":20.0,"sold_out":false,"has_custom_price":false,"name":"Default","id":30344567}],"url":"/product/print"}]
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'dugway/contact_form_validator'
|
3
|
+
|
4
|
+
describe Dugway::ContactFormValidator do
|
5
|
+
|
6
|
+
let(:validator) { described_class.new(params) }
|
7
|
+
|
8
|
+
let(:params) do
|
9
|
+
{
|
10
|
+
:name => "name",
|
11
|
+
:email => "name@example.com",
|
12
|
+
:subject => "subject",
|
13
|
+
:message => "message",
|
14
|
+
:captcha => "rQ9pc",
|
15
|
+
}
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "#error_message" do
|
19
|
+
it "returns an error for a missing name" do
|
20
|
+
validator.params[:name] = " "
|
21
|
+
assert_required_fields_error
|
22
|
+
end
|
23
|
+
|
24
|
+
it "returns an error for a missing email" do
|
25
|
+
validator.params[:email] = ""
|
26
|
+
assert_required_fields_error
|
27
|
+
end
|
28
|
+
|
29
|
+
it "returns an error for a missing subject" do
|
30
|
+
validator.params[:subject] = nil
|
31
|
+
assert_required_fields_error
|
32
|
+
end
|
33
|
+
|
34
|
+
it "returns an error for a missing message" do
|
35
|
+
validator.params[:message] = nil
|
36
|
+
assert_required_fields_error
|
37
|
+
end
|
38
|
+
|
39
|
+
it "returns an error for a missing captcha" do
|
40
|
+
validator.params[:captcha] = " "
|
41
|
+
assert_required_fields_error
|
42
|
+
end
|
43
|
+
|
44
|
+
it "returns an error for invalid email format" do
|
45
|
+
validator.params[:email] = "foo-at-foo-dot-net"
|
46
|
+
expect(validator.error_message).to eq "Invalid email address"
|
47
|
+
end
|
48
|
+
|
49
|
+
it "returns an error for incorrect captcha" do
|
50
|
+
validator.params[:captcha] = "oops"
|
51
|
+
expect(validator.error_message).to eq "Spam check was incorrect"
|
52
|
+
end
|
53
|
+
|
54
|
+
def assert_required_fields_error
|
55
|
+
expect(validator.error_message).to eql "All fields are required"
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
@@ -5,7 +5,7 @@ describe Dugway::Drops::ImageDrop do
|
|
5
5
|
|
6
6
|
describe "#url" do
|
7
7
|
it "should return the image's url" do
|
8
|
-
image.url.should == 'http://
|
8
|
+
image.url.should == 'http://images.bigcartel.com/product_images/92599166/mens_tee_1.jpg'
|
9
9
|
end
|
10
10
|
end
|
11
11
|
|
@@ -213,7 +213,7 @@ describe Dugway::Drops::ProductDrop do
|
|
213
213
|
it "should return the product's first image" do
|
214
214
|
image = product.image
|
215
215
|
image.should be_an_instance_of(Dugway::Drops::ImageDrop)
|
216
|
-
image.url.should == 'http://
|
216
|
+
image.url.should == 'http://images.bigcartel.com/product_images/92599166/mens_tee_1.jpg'
|
217
217
|
end
|
218
218
|
end
|
219
219
|
|
@@ -225,7 +225,7 @@ describe Dugway::Drops::ProductDrop do
|
|
225
225
|
|
226
226
|
image = images.first
|
227
227
|
image.should be_an_instance_of(Dugway::Drops::ImageDrop)
|
228
|
-
image.url.should == 'http://
|
228
|
+
image.url.should == 'http://images.bigcartel.com/product_images/92599166/mens_tee_1.jpg'
|
229
229
|
end
|
230
230
|
end
|
231
231
|
|
@@ -10,48 +10,42 @@ describe Dugway::Filters::UrlFilters do
|
|
10
10
|
describe "when image is not missing" do
|
11
11
|
it "should show image with default size" do
|
12
12
|
template = rendered_template("{{ image | product_image_url }}", 'image' => product_image)
|
13
|
-
template.should
|
14
|
-
template.should =~ /#{Regexp.escape(File.basename(image_url))}/
|
13
|
+
template.should include("#{image_url}?h=1000&w=1000")
|
15
14
|
end
|
16
15
|
|
17
16
|
it "should show a image with custom size" do
|
18
17
|
template = rendered_template("{{ image | product_image_url: 'thumb' }}", 'image' => product_image)
|
19
|
-
template.should
|
20
|
-
template.should =~ /#{Regexp.escape(File.basename(image_url))}/
|
18
|
+
template.should include("#{image_url}?h=75&w=75")
|
21
19
|
end
|
22
20
|
|
23
21
|
it "should show image with default size when its random crap" do
|
24
22
|
template = rendered_template("{{ image | product_image_url: 'snarble' }}", 'image' => product_image)
|
25
|
-
template.should
|
26
|
-
template.should =~ /#{Regexp.escape(File.basename(image_url))}/
|
23
|
+
template.should include("#{image_url}?h=1000&w=1000")
|
27
24
|
end
|
28
25
|
end
|
29
26
|
|
30
27
|
describe "when image is missing" do
|
31
28
|
it "should show missing image with default 1000x1000" do
|
32
29
|
template = rendered_template("{{ image | product_image_url }}", 'image' => nil)
|
33
|
-
template.should
|
34
|
-
template.should =~ /missing\.png/
|
30
|
+
template.should include("http://images.bigcartel.com/missing.png?h=1000&w=1000")
|
35
31
|
end
|
36
32
|
|
37
33
|
it "should show missing image with custom size" do
|
38
34
|
template = rendered_template("{{ image | product_image_url: 'thumb' }}", 'image' => nil)
|
39
|
-
template.should
|
40
|
-
template.should =~ /missing\.png/
|
35
|
+
template.should include("http://images.bigcartel.com/missing.png?h=75&w=75")
|
41
36
|
end
|
42
37
|
|
43
38
|
it "should show missing image with default 1000x1000 when its random crap" do
|
44
39
|
template = rendered_template("{{ image | product_image_url: 'snarble' }}", 'image' => nil)
|
45
|
-
template.should
|
46
|
-
template.should =~ /missing\.png/
|
40
|
+
template.should include("http://images.bigcartel.com/missing.png?h=1000&w=1000")
|
47
41
|
end
|
48
42
|
end
|
49
43
|
end
|
50
44
|
|
51
45
|
describe "#constrain" do
|
52
46
|
it 'should constrain the image to the specified size' do
|
53
|
-
template = rendered_template("{{ image | product_image_url | constrain: '
|
54
|
-
template.should
|
47
|
+
template = rendered_template("{{ image | product_image_url | constrain: '123', '456' }}", 'image' => product_image)
|
48
|
+
template.should include("#{image_url}?h=456&w=123")
|
55
49
|
end
|
56
50
|
end
|
57
51
|
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'dugway/path_interpreter'
|
3
|
+
|
4
|
+
describe Dugway::PathInterpreter do
|
5
|
+
let(:path) { double 'path' }
|
6
|
+
let(:interpreter) { described_class.new(path) }
|
7
|
+
|
8
|
+
it "initializes with arguements" do
|
9
|
+
expect(interpreter.path).to eq path
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "#call" do
|
13
|
+
it "handles non-string paths" do
|
14
|
+
expect(described_class.new(/regex/).call).to eql /regex/
|
15
|
+
end
|
16
|
+
|
17
|
+
it "handles category, artist, and product type paths" do
|
18
|
+
expect(described_class.new("/product/:product(.js)").call).to eq(
|
19
|
+
%r{^/product/(?<product>(?-mix:[a-z0-9\-_]+))(?-mix:(\.(?<format>js))?)$}
|
20
|
+
)
|
21
|
+
end
|
22
|
+
|
23
|
+
it "handles products and cart type paths" do
|
24
|
+
expect(described_class.new("/products(.js)").call).to eq(
|
25
|
+
%r{^/products(?-mix:(\.(?<format>js))?)$}
|
26
|
+
)
|
27
|
+
end
|
28
|
+
|
29
|
+
it "handles custom pages" do
|
30
|
+
expect(described_class.new("/:custom-page").call).to eq(
|
31
|
+
%r{^/(?<custom-page>(?-mix:[a-z0-9\-_]+))$}
|
32
|
+
)
|
33
|
+
end
|
34
|
+
|
35
|
+
it "handles everything else" do
|
36
|
+
expect(described_class.new("/checkout").call).to eq(
|
37
|
+
%r{^/checkout$}
|
38
|
+
)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dugway
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.10.
|
4
|
+
version: 0.10.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Big Cartel
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-06-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -440,6 +440,7 @@ files:
|
|
440
440
|
- lib/dugway/cli/templates/source/success.html
|
441
441
|
- lib/dugway/cli/templates/source/theme.css
|
442
442
|
- lib/dugway/cli/templates/source/theme.js
|
443
|
+
- lib/dugway/contact_form_validator.rb
|
443
444
|
- lib/dugway/controller.rb
|
444
445
|
- lib/dugway/extensions/time.rb
|
445
446
|
- lib/dugway/liquid/drops/account_drop.rb
|
@@ -474,6 +475,7 @@ files:
|
|
474
475
|
- lib/dugway/liquid/tags/paginate.rb
|
475
476
|
- lib/dugway/liquifier.rb
|
476
477
|
- lib/dugway/logger.rb
|
478
|
+
- lib/dugway/path_interpreter.rb
|
477
479
|
- lib/dugway/request.rb
|
478
480
|
- lib/dugway/store.rb
|
479
481
|
- lib/dugway/template.rb
|
@@ -515,6 +517,7 @@ files:
|
|
515
517
|
- spec/fixtures/theme/theme.js
|
516
518
|
- spec/spec_helper.rb
|
517
519
|
- spec/units/dugway/cart_spec.rb
|
520
|
+
- spec/units/dugway/contact_form_validator_spec.rb
|
518
521
|
- spec/units/dugway/liquid/drops/account_drop_spec.rb
|
519
522
|
- spec/units/dugway/liquid/drops/artist_drop_spec.rb
|
520
523
|
- spec/units/dugway/liquid/drops/artists_drop_spec.rb
|
@@ -537,6 +540,7 @@ files:
|
|
537
540
|
- spec/units/dugway/liquid/filters/core_filters_spec.rb
|
538
541
|
- spec/units/dugway/liquid/filters/url_filters_spec.rb
|
539
542
|
- spec/units/dugway/liquid/misc/for_loop_spec.rb
|
543
|
+
- spec/units/dugway/path_interpreter_spec.rb
|
540
544
|
- spec/units/dugway/request_spec.rb
|
541
545
|
- spec/units/dugway/store_spec.rb
|
542
546
|
- spec/units/dugway/template_spec.rb
|
@@ -602,6 +606,7 @@ test_files:
|
|
602
606
|
- spec/fixtures/theme/theme.js
|
603
607
|
- spec/spec_helper.rb
|
604
608
|
- spec/units/dugway/cart_spec.rb
|
609
|
+
- spec/units/dugway/contact_form_validator_spec.rb
|
605
610
|
- spec/units/dugway/liquid/drops/account_drop_spec.rb
|
606
611
|
- spec/units/dugway/liquid/drops/artist_drop_spec.rb
|
607
612
|
- spec/units/dugway/liquid/drops/artists_drop_spec.rb
|
@@ -624,7 +629,9 @@ test_files:
|
|
624
629
|
- spec/units/dugway/liquid/filters/core_filters_spec.rb
|
625
630
|
- spec/units/dugway/liquid/filters/url_filters_spec.rb
|
626
631
|
- spec/units/dugway/liquid/misc/for_loop_spec.rb
|
632
|
+
- spec/units/dugway/path_interpreter_spec.rb
|
627
633
|
- spec/units/dugway/request_spec.rb
|
628
634
|
- spec/units/dugway/store_spec.rb
|
629
635
|
- spec/units/dugway/template_spec.rb
|
630
636
|
- spec/units/dugway/theme_spec.rb
|
637
|
+
has_rdoc:
|