dugway 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (125) hide show
  1. data/.gitignore +7 -0
  2. data/.travis.yml +3 -0
  3. data/Gemfile +2 -0
  4. data/README.md +151 -0
  5. data/Rakefile +12 -0
  6. data/bin/dugway +7 -0
  7. data/dugway.gemspec +43 -0
  8. data/lib/dugway.rb +66 -0
  9. data/lib/dugway/application.rb +147 -0
  10. data/lib/dugway/cart.rb +144 -0
  11. data/lib/dugway/cli.rb +22 -0
  12. data/lib/dugway/cli/build.rb +56 -0
  13. data/lib/dugway/cli/create.rb +71 -0
  14. data/lib/dugway/cli/server.rb +37 -0
  15. data/lib/dugway/cli/templates/Gemfile.tt +2 -0
  16. data/lib/dugway/cli/templates/config.tt +24 -0
  17. data/lib/dugway/cli/templates/gitignore.tt +9 -0
  18. data/lib/dugway/cli/templates/source/cart.html +40 -0
  19. data/lib/dugway/cli/templates/source/checkout.html +33 -0
  20. data/lib/dugway/cli/templates/source/contact.html +37 -0
  21. data/lib/dugway/cli/templates/source/home.html +25 -0
  22. data/lib/dugway/cli/templates/source/images/badge.png +0 -0
  23. data/lib/dugway/cli/templates/source/javascripts/cart.js.coffee +7 -0
  24. data/lib/dugway/cli/templates/source/javascripts/product.js.coffee +7 -0
  25. data/lib/dugway/cli/templates/source/layout.html +101 -0
  26. data/lib/dugway/cli/templates/source/maintenance.html +20 -0
  27. data/lib/dugway/cli/templates/source/product.html +65 -0
  28. data/lib/dugway/cli/templates/source/products.html +25 -0
  29. data/lib/dugway/cli/templates/source/screenshot.jpg +0 -0
  30. data/lib/dugway/cli/templates/source/scripts.js +19 -0
  31. data/lib/dugway/cli/templates/source/settings.json +71 -0
  32. data/lib/dugway/cli/templates/source/styles.css +27 -0
  33. data/lib/dugway/cli/templates/source/stylesheets/cart.css.sass +38 -0
  34. data/lib/dugway/cli/templates/source/stylesheets/layout.css.sass +103 -0
  35. data/lib/dugway/cli/templates/source/stylesheets/product.css.sass +19 -0
  36. data/lib/dugway/cli/templates/source/stylesheets/products.css.sass +20 -0
  37. data/lib/dugway/cli/templates/source/stylesheets/vendor/normalize.css +396 -0
  38. data/lib/dugway/cli/templates/source/success.html +5 -0
  39. data/lib/dugway/controller.rb +148 -0
  40. data/lib/dugway/data/locales/cs.yml +26 -0
  41. data/lib/dugway/data/locales/da.yml +26 -0
  42. data/lib/dugway/data/locales/en-AU.yml +26 -0
  43. data/lib/dugway/data/locales/en-GB.yml +26 -0
  44. data/lib/dugway/data/locales/en-PH.yml +27 -0
  45. data/lib/dugway/data/locales/en-US.yml +26 -0
  46. data/lib/dugway/data/locales/es-MX.yml +26 -0
  47. data/lib/dugway/data/locales/eu.yml +26 -0
  48. data/lib/dugway/data/locales/gsw-CH.yml +26 -0
  49. data/lib/dugway/data/locales/hu.yml +26 -0
  50. data/lib/dugway/data/locales/il.yml +26 -0
  51. data/lib/dugway/data/locales/ja.yml +30 -0
  52. data/lib/dugway/data/locales/ms-MY.yml +26 -0
  53. data/lib/dugway/data/locales/nb.yml +22 -0
  54. data/lib/dugway/data/locales/pl.yml +27 -0
  55. data/lib/dugway/data/locales/pt-BR.yml +26 -0
  56. data/lib/dugway/data/locales/sv-SE.yml +26 -0
  57. data/lib/dugway/data/locales/th.yml +26 -0
  58. data/lib/dugway/data/locales/tr.yml +29 -0
  59. data/lib/dugway/data/locales/zh-TW.yml +30 -0
  60. data/lib/dugway/data/theme_fonts.yml +151 -0
  61. data/lib/dugway/extensions/time.rb +15 -0
  62. data/lib/dugway/liquid/drops/account_drop.rb +17 -0
  63. data/lib/dugway/liquid/drops/artist_drop.rb +9 -0
  64. data/lib/dugway/liquid/drops/artists_drop.rb +13 -0
  65. data/lib/dugway/liquid/drops/base_drop.rb +59 -0
  66. data/lib/dugway/liquid/drops/cart_drop.rb +13 -0
  67. data/lib/dugway/liquid/drops/cart_item_drop.rb +21 -0
  68. data/lib/dugway/liquid/drops/categories_drop.rb +13 -0
  69. data/lib/dugway/liquid/drops/category_drop.rb +9 -0
  70. data/lib/dugway/liquid/drops/contact_drop.rb +29 -0
  71. data/lib/dugway/liquid/drops/country_drop.rb +6 -0
  72. data/lib/dugway/liquid/drops/currency_drop.rb +6 -0
  73. data/lib/dugway/liquid/drops/image_drop.rb +6 -0
  74. data/lib/dugway/liquid/drops/page_drop.rb +13 -0
  75. data/lib/dugway/liquid/drops/pages_drop.rb +9 -0
  76. data/lib/dugway/liquid/drops/product_drop.rb +101 -0
  77. data/lib/dugway/liquid/drops/product_option_drop.rb +27 -0
  78. data/lib/dugway/liquid/drops/products_drop.rb +75 -0
  79. data/lib/dugway/liquid/drops/shipping_option_drop.rb +13 -0
  80. data/lib/dugway/liquid/drops/theme_drop.rb +23 -0
  81. data/lib/dugway/liquid/filters/comparison_filters.rb +48 -0
  82. data/lib/dugway/liquid/filters/core_filters.rb +138 -0
  83. data/lib/dugway/liquid/filters/default_pagination.rb +35 -0
  84. data/lib/dugway/liquid/filters/font_filters.rb +9 -0
  85. data/lib/dugway/liquid/filters/url_filters.rb +66 -0
  86. data/lib/dugway/liquid/filters/util_filters.rb +119 -0
  87. data/lib/dugway/liquid/tags/checkout_form.rb +9 -0
  88. data/lib/dugway/liquid/tags/get.rb +58 -0
  89. data/lib/dugway/liquid/tags/paginate.rb +129 -0
  90. data/lib/dugway/liquifier.rb +122 -0
  91. data/lib/dugway/logger.rb +16 -0
  92. data/lib/dugway/request.rb +36 -0
  93. data/lib/dugway/store.rb +166 -0
  94. data/lib/dugway/template.rb +44 -0
  95. data/lib/dugway/theme.rb +145 -0
  96. data/lib/dugway/theme_font.rb +68 -0
  97. data/lib/dugway/version.rb +3 -0
  98. data/spec/fixtures/store/page/about-us.js +1 -0
  99. data/spec/fixtures/store/products.js +1 -0
  100. data/spec/fixtures/store/store.js +1 -0
  101. data/spec/fixtures/theme/cart.html +33 -0
  102. data/spec/fixtures/theme/checkout.html +31 -0
  103. data/spec/fixtures/theme/contact.html +37 -0
  104. data/spec/fixtures/theme/home.html +38 -0
  105. data/spec/fixtures/theme/images/bc_badge.png +0 -0
  106. data/spec/fixtures/theme/javascripts/one.js +3 -0
  107. data/spec/fixtures/theme/javascripts/two.js.coffee +2 -0
  108. data/spec/fixtures/theme/layout.html +77 -0
  109. data/spec/fixtures/theme/maintenance.html +17 -0
  110. data/spec/fixtures/theme/product.html +73 -0
  111. data/spec/fixtures/theme/products.html +41 -0
  112. data/spec/fixtures/theme/screenshot.jpg +0 -0
  113. data/spec/fixtures/theme/scripts.js +2 -0
  114. data/spec/fixtures/theme/settings.json +55 -0
  115. data/spec/fixtures/theme/styles.css +4 -0
  116. data/spec/fixtures/theme/stylesheets/one.css +3 -0
  117. data/spec/fixtures/theme/stylesheets/two.css.sass +4 -0
  118. data/spec/fixtures/theme/success.html +5 -0
  119. data/spec/spec_helper.rb +24 -0
  120. data/spec/units/dugway/request_spec.rb +206 -0
  121. data/spec/units/dugway/store_spec.rb +194 -0
  122. data/spec/units/dugway/template_spec.rb +145 -0
  123. data/spec/units/dugway/theme_font_spec.rb +136 -0
  124. data/spec/units/dugway_spec.rb +9 -0
  125. metadata +549 -0
@@ -0,0 +1,144 @@
1
+ module Dugway
2
+ class Cart
3
+ attr_accessor :items
4
+
5
+ def initialize
6
+ reset
7
+ end
8
+
9
+ def reset
10
+ self.items = []
11
+ end
12
+
13
+ def item_count
14
+ items.map { |item| item.quantity }.inject(:+) || 0
15
+ end
16
+
17
+ def subtotal
18
+ items.map { |item| item.price }.inject(:+) || 0.0
19
+ end
20
+
21
+ def total
22
+ subtotal + shipping['amount'] + tax['amount'] - discount['amount']
23
+ end
24
+
25
+ def country
26
+ nil
27
+ end
28
+
29
+ def shipping
30
+ {
31
+ 'enabled' => false,
32
+ 'amount' => 0.0,
33
+ 'strict' => false,
34
+ 'pending' => false
35
+ }
36
+ end
37
+
38
+ def tax
39
+ {
40
+ 'enabled' => false,
41
+ 'amount' => 0.0
42
+ }
43
+ end
44
+
45
+ def discount
46
+ {
47
+ 'enabled' => false,
48
+ 'pending' => false,
49
+ 'amount' => 0.0
50
+ }
51
+ end
52
+
53
+ def update(params)
54
+ add, adds, updates = params.delete(:add), params.delete(:adds), params.delete(:update)
55
+ add_item(add) if add
56
+ add_item(adds) if adds
57
+ update_quantities(updates) if updates
58
+ end
59
+
60
+ def empty?
61
+ items.empty?
62
+ end
63
+
64
+ def as_json(options=nil)
65
+ {
66
+ :item_count => item_count,
67
+ :subtotal => subtotal,
68
+ :price => subtotal, # deprecated but need this for backwards JS compatibility
69
+ :total => total,
70
+ :items => items,
71
+ :country => country,
72
+ :shipping => shipping,
73
+ :discount => discount
74
+ }
75
+ end
76
+
77
+ private
78
+
79
+ def add_item(add)
80
+ id = add[:id].to_i
81
+
82
+ unless item = items.find { |i| i.option['id'] == id.to_i }
83
+ product, option = Dugway.store.product_and_option(id)
84
+
85
+ if product && option
86
+ item = CartItem.new
87
+ item.id = items.size + 1
88
+ item.name = option['name'] == 'Default' ? product['name'] : "#{ product['name'] } - #{ option['name'] }"
89
+ item.unit_price = option['price']
90
+ item.product = product
91
+ item.option = option
92
+ item.quantity = 0
93
+
94
+ items << item
95
+ end
96
+ end
97
+
98
+ if item
99
+ item.quantity += add[:quantity] ? add[:quantity].to_i : 1
100
+ end
101
+
102
+ item
103
+ end
104
+
105
+ def add_items(adds)
106
+ if adds.kind_of?(Array)
107
+ adds.each { |add| add_item(add) }
108
+ elsif adds.kind_of?(Hash)
109
+ adds.each_pair { |key, add| add_item(add.reverse_merge(:id => key)) }
110
+ end
111
+ end
112
+
113
+ def update_quantities(updates)
114
+ updates.each_pair { |id, qty|
115
+ if item = items.find { |i| i.id == id.to_i }
116
+ item.quantity = qty.to_i
117
+ end
118
+ }
119
+
120
+ items.reject! { |item| item.quantity == 0 }
121
+ end
122
+ end
123
+
124
+ CartItem = Struct.new(:id, :name, :unit_price, :quantity, :product, :option) do
125
+ def price
126
+ unit_price * quantity
127
+ end
128
+
129
+ def as_json(options=nil)
130
+ {
131
+ :id => id,
132
+ :name => name,
133
+ :price => price,
134
+ :unit_price => unit_price,
135
+ :shipping => 0.0,
136
+ :tax => 0.0,
137
+ :total => price,
138
+ :quantity => quantity,
139
+ :product => product['permalink'],
140
+ :option => option['id']
141
+ }
142
+ end
143
+ end
144
+ end
data/lib/dugway/cli.rb ADDED
@@ -0,0 +1,22 @@
1
+ require 'thor'
2
+ require 'active_support/all'
3
+
4
+ require 'dugway'
5
+ require 'dugway/cli/build'
6
+ require 'dugway/cli/create'
7
+ require 'dugway/cli/server'
8
+
9
+ module Dugway
10
+ module Cli
11
+ class Base < Thor
12
+ register Create, 'create', 'create', 'Create a new Big Cartel theme'
13
+ register Build, 'build', 'build', 'Build your Big Cartel theme for use'
14
+ register Server, 'server', 'server', 'Run your Big Cartel theme in the browser'
15
+
16
+ desc 'version', 'Show version of Dugway'
17
+ def version
18
+ say "Dugway #{ Dugway::VERSION }"
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,56 @@
1
+ require 'zip/zip'
2
+
3
+ module Dugway
4
+ module Cli
5
+ class Build < Thor::Group
6
+ include Thor::Actions
7
+
8
+ def self.source_root
9
+ File.join(Dir.pwd, 'source')
10
+ end
11
+
12
+ def self.destination_root
13
+ File.join(Dir.pwd, 'build')
14
+ end
15
+
16
+ def validate
17
+ unless theme.valid?
18
+ theme.errors.each { |error| say(error, :red) }
19
+ raise "Theme is invalid"
20
+ end
21
+ end
22
+
23
+ def create_destination
24
+ empty_directory self.class.destination_root
25
+ end
26
+
27
+ def build
28
+ Zip::ZipFile.open(build_file, Zip::ZipFile::CREATE) { |zipfile|
29
+ theme.files.each { |file|
30
+ zipfile.get_output_stream(file) { |f|
31
+ f << theme.build_file(file)
32
+ }
33
+ }
34
+ }
35
+ end
36
+
37
+ def success
38
+ say_status(:create, "build/#{ build_name }")
39
+ end
40
+
41
+ private
42
+
43
+ def theme
44
+ @theme ||= Theme.new(self.class.source_root)
45
+ end
46
+
47
+ def build_name
48
+ @build_name ||= "#{ theme.name.parameterize }-#{ theme.version }.zip"
49
+ end
50
+
51
+ def build_file
52
+ @build_file ||= File.join(self.class.destination_root, build_name)
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,71 @@
1
+ module Dugway
2
+ module Cli
3
+ class Create < Thor::Group
4
+ include Thor::Actions
5
+
6
+ argument :name
7
+
8
+ class_option 'skip-source',
9
+ :type => :boolean,
10
+ :default => false,
11
+ :desc => "Don't create a starter theme"
12
+
13
+ class_option 'skip-git',
14
+ :type => :boolean,
15
+ :default => false,
16
+ :desc => "Don't create a .gitignore file"
17
+
18
+ class_option 'skip-bundle',
19
+ :type => :boolean,
20
+ :default => false,
21
+ :desc => "Don't run bundle install"
22
+
23
+ def self.source_root
24
+ File.join(File.dirname(__FILE__), 'templates')
25
+ end
26
+
27
+ def core
28
+ template('Gemfile.tt', "#{ theme_dir }/Gemfile")
29
+ template('config.tt', "#{ theme_dir }/config.ru")
30
+ template('source/settings.json', "#{ source_dir }/settings.json")
31
+ end
32
+
33
+ def source
34
+ unless options['skip-source']
35
+ Dir.glob("#{ self.class.source_root }/source/**/*.{html,jpg,png,js,coffee,css,sass}") do |file|
36
+ file_name = file.gsub("#{ self.class.source_root }/source/", '')
37
+ copy_file "source/#{ file_name }", "#{ source_dir }/#{ file_name }"
38
+ end
39
+ end
40
+ end
41
+
42
+ def git
43
+ unless options['skip-git']
44
+ copy_file('gitignore.tt', "#{ theme_dir }/.gitignore")
45
+ end
46
+ end
47
+
48
+ def bundle
49
+ unless options['skip-bundle']
50
+ inside theme_dir, {} do
51
+ run('bundle install --without development test')
52
+ end
53
+ end
54
+ end
55
+
56
+ def done
57
+ say("#{ name } is ready!", :blue)
58
+ end
59
+
60
+ private
61
+
62
+ def theme_dir
63
+ name.parameterize
64
+ end
65
+
66
+ def source_dir
67
+ "#{ theme_dir }/source"
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,37 @@
1
+ require 'rack'
2
+
3
+ module Dugway
4
+ module Cli
5
+ class Server < Thor::Group
6
+ include Thor::Actions
7
+
8
+ class_option :host,
9
+ :type => :string,
10
+ :aliases => '-h',
11
+ :default => '0.0.0.0',
12
+ :desc => 'The host address to bind to'
13
+
14
+ class_option :port,
15
+ :type => :numeric,
16
+ :aliases => '-p',
17
+ :default => 9292,
18
+ :desc => "The port address to bind to"
19
+
20
+ class_option :daemonize,
21
+ :type => :boolean,
22
+ :aliases => '-d',
23
+ :default => false,
24
+ :desc => "Run daemonized in the background"
25
+
26
+ def start
27
+ Rack::Server.start({
28
+ :config => File.join(Dir.pwd, 'config.ru'),
29
+ :environment => 'none',
30
+ :Host => options[:host],
31
+ :Port => options[:port],
32
+ :daemonize => options[:daemonize]
33
+ })
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,2 @@
1
+ source :rubygems
2
+ gem 'dugway'
@@ -0,0 +1,24 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+ require 'dugway'
4
+
5
+ options = {}
6
+
7
+ # Use data from any store to make sure your theme looks great with all sorts of products, pages,
8
+ # categories, and more. Just give us the subdomain. Default is "dugway" for dugway.bigcartel.com.
9
+ # options[:store] = 'mystore'
10
+
11
+ # Simulate the customization done by store owners by passing values to different variables.
12
+ # Default values are based on the "default" for each setting in your settings.json.
13
+ # options[:customization] = {
14
+ # :logo => {
15
+ # :url => 'http://placehold.it/200x50/000000/ffffff&text=My+Logo',
16
+ # :width => 200,
17
+ # :height => 50
18
+ # },
19
+ # :background_color => '#CCCCCC',
20
+ # :show_search => true,
21
+ # :twitter_username => 'mytwitter'
22
+ # }
23
+
24
+ run Dugway.application(options)
@@ -0,0 +1,9 @@
1
+ .DS_Store
2
+
3
+ build
4
+ tmp
5
+ log
6
+
7
+ *.tmproj
8
+ *.esproj
9
+ *.sublime*
@@ -0,0 +1,40 @@
1
+ {% if cart.items != blank %}
2
+
3
+ <form method="post" action="/cart">
4
+ <ul>
5
+ {% for item in cart.items %}
6
+ <li>
7
+ <a href="{{ item.product.url }}">
8
+ <img src="{{ item.product.image | product_image_url size:"thumb" }}">
9
+ </a>
10
+ <h2>
11
+ <a href="{{ item.product.url }}">
12
+ {{ item.product.name }}
13
+ {% unless item.product.has_default_option %}
14
+ <em>{{ item.option.name }}</em>
15
+ {% endunless %}
16
+ </a>
17
+ </h2>
18
+ <p>
19
+ {{ item | item_quantity_input }}
20
+ {{ item.price | money_with_sign }}
21
+ <a href="#" class="remove">&times;</a>
22
+ </p>
23
+ </li>
24
+ {% endfor %}
25
+ </ul>
26
+
27
+ <p>
28
+ <strong>Subtotal</strong>
29
+ <span>{{ cart.subtotal | money_with_sign }}</span>
30
+ </p>
31
+ <button type="submit" name="checkout" title="Checkout">Checkout</button>
32
+ </form>
33
+
34
+ {% else %}
35
+
36
+ <div>
37
+ <p><strong>Your cart is empty!</strong> Sounds like a good time to <a href="/">start shopping &rarr;</a></p>
38
+ </div>
39
+
40
+ {% endif %}
@@ -0,0 +1,33 @@
1
+ <!DOCTYPE html>
2
+ <head>
3
+ <title>{{ store.name }} &mdash; {{ page.name }}</title>
4
+
5
+ <meta charset="utf-8">
6
+ <meta name="description" content="{{ page.meta_description }}">
7
+ <meta name="keywords" content="{{ page.meta_keywords }}">
8
+
9
+ <link href="{{ theme | theme_css_url }}" media="screen" rel="stylesheet" type="text/css">
10
+
11
+ <script type="text/javascript" charset="utf-8">
12
+ function checkout() {
13
+ if(top != self) {
14
+ top.location.replace(self.location.href);
15
+ } else {
16
+ document.checkout_form.submit();
17
+ }
18
+ }
19
+ </script>
20
+
21
+ {{ head_content }}
22
+ </head>
23
+
24
+ <body id="{{ page.permalink }}" class="{{ page.category }}" onload="checkout();">
25
+ <h1>One moment&hellip;</h1>
26
+
27
+ {% checkoutform %}
28
+ <noscript>
29
+ <button type="submit" name="checkout" title="Checkout">Checkout</button>
30
+ </noscript>
31
+ {% endcheckoutform %}
32
+ </body>
33
+ </html>