dugway 0.10.3 → 0.10.4
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 +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
|
[](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:
|