dugway 0.5.0

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.
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,44 @@
1
+ module Dugway
2
+ class Template
3
+ attr_reader :name
4
+
5
+ def initialize(name)
6
+ @name = name
7
+ end
8
+
9
+ def content
10
+ Dugway.theme.file_content(name)
11
+ end
12
+
13
+ def content_type
14
+ Rack::Mime.mime_type(extension)
15
+ end
16
+
17
+ def extension
18
+ File.extname(name)
19
+ end
20
+
21
+ def html?
22
+ extension == '.html'
23
+ end
24
+
25
+ def standalone_html?
26
+ html? && !!(content =~ /\{\{\s*head_content\s*\}\}/)
27
+ end
28
+
29
+ def render(request, variables={})
30
+ if html?
31
+ liquifier = Liquifier.new(request)
32
+ rendered_content = liquifier.render(content, variables)
33
+
34
+ if standalone_html?
35
+ rendered_content
36
+ else
37
+ liquifier.render(Dugway.theme.layout, variables.update(:page_content => rendered_content))
38
+ end
39
+ else
40
+ content
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,145 @@
1
+ require 'coffee-script'
2
+ require 'sass'
3
+ require 'less'
4
+ require 'sprockets'
5
+ require 'yui/compressor'
6
+
7
+ module Dugway
8
+ class Theme
9
+ REQUIRED_FILES = %w( layout.html home.html products.html product.html cart.html checkout.html success.html contact.html maintenance.html scripts.js styles.css settings.json screenshot.jpg )
10
+
11
+ attr_reader :errors
12
+
13
+ def initialize(overridden_customization={})
14
+ @overridden_customization = overridden_customization.stringify_keys
15
+ end
16
+
17
+ def layout
18
+ read_source_file('layout.html')
19
+ end
20
+
21
+ def settings
22
+ JSON.parse(read_source_file('settings.json'))
23
+ end
24
+
25
+ def fonts
26
+ customization_for_type('fonts')
27
+ end
28
+
29
+ def customization
30
+ Hash.new.tap { |customization|
31
+ %w( fonts colors options ).each { |type|
32
+ customization.update(customization_for_type(type))
33
+ }
34
+
35
+ customization.update(@overridden_customization)
36
+ }
37
+ end
38
+
39
+ def name
40
+ settings['name']
41
+ end
42
+
43
+ def version
44
+ settings['version']
45
+ end
46
+
47
+ def file_content(name)
48
+ case name
49
+ when 'scripts.js'
50
+ if @building
51
+ YUI::JavaScriptCompressor.new.compress(sprockets[name].to_s)
52
+ else
53
+ sprockets[name].to_s
54
+ end
55
+ when 'styles.css'
56
+ sprockets[name].to_s
57
+ else
58
+ read_source_file(name)
59
+ end
60
+ end
61
+
62
+ def build_file(name)
63
+ @building = true
64
+ file_content(name)
65
+ end
66
+
67
+ def files
68
+ REQUIRED_FILES + image_files
69
+ end
70
+
71
+ def image_files
72
+ Dir.glob(File.join(source_dir, 'images', '**', '*.{png,jpg,jpeg,gif}')).map { |i|
73
+ i.gsub(source_dir, '')[1..-1]
74
+ }
75
+ end
76
+
77
+ def valid?
78
+ @errors = []
79
+
80
+ REQUIRED_FILES.each { |file|
81
+ @errors << "Missing source/#{ file }" if read_source_file(file).nil?
82
+ }
83
+
84
+ @errors << 'Missing theme name in source/settings.json' if name.blank?
85
+ @errors << 'Invalid theme version in source/settings.json (ex: 1.0.3)' unless !!(version =~ /\d+\.\d+\.\d+/)
86
+ @errors << 'Missing images in source/images' if image_files.empty?
87
+
88
+ @errors.empty?
89
+ end
90
+
91
+ private
92
+
93
+ def source_dir
94
+ Dugway.source_dir
95
+ end
96
+
97
+ def sprockets
98
+ @sprockets ||= begin
99
+ sprockets = Sprockets::Environment.new
100
+ sprockets.append_path source_dir
101
+
102
+ # CSS engines like Sass and LESS choke on Liquid variables, so here we render the Liquid
103
+ # if we're viewing the file, or escape and unescape it if we're building the file.
104
+
105
+ sprockets.register_preprocessor 'text/css', :liquifier do |context, data|
106
+ if @building
107
+ Liquifier.escape_styles(data)
108
+ else
109
+ Liquifier.render_styles(data)
110
+ end
111
+ end
112
+
113
+ sprockets.register_postprocessor 'text/css', :liquifier do |context, data|
114
+ if @building
115
+ Liquifier.unescape_styles(data)
116
+ else
117
+ data
118
+ end
119
+ end
120
+
121
+ sprockets
122
+ end
123
+ end
124
+
125
+ def read_source_file(file_name)
126
+ file_path = File.join(source_dir, file_name)
127
+
128
+ if File.exist?(file_path)
129
+ File.read(file_path)
130
+ else
131
+ nil
132
+ end
133
+ end
134
+
135
+ def customization_for_type(type)
136
+ Hash.new.tap { |hash|
137
+ if settings.has_key?(type)
138
+ settings[type].each { |setting|
139
+ hash[setting['variable']] = setting['default']
140
+ }
141
+ end
142
+ }
143
+ end
144
+ end
145
+ end
@@ -0,0 +1,68 @@
1
+ require 'yaml'
2
+
3
+ module Dugway
4
+ class ThemeFont < Struct.new(:name, :family, :collection)
5
+ class << self
6
+ def all
7
+ @@all ||= Array.new.tap { |fonts|
8
+ source.each_pair { |collection, collection_fonts|
9
+ collection_fonts.values.each { |font|
10
+ fonts << ThemeFont.new(font[:name], font[:family], collection)
11
+ }
12
+ }
13
+ }.sort_by { |font| font.name }
14
+ end
15
+
16
+ def options
17
+ @@options ||= all.map(&:name)
18
+ end
19
+
20
+ def find_by_name(name)
21
+ all.find { |font|
22
+ name.downcase == font.name.downcase
23
+ }
24
+ end
25
+
26
+ def find_family_by_name(name)
27
+ if font = find_by_name(name)
28
+ font.family
29
+ else
30
+ name
31
+ end
32
+ end
33
+
34
+ def google_font_names
35
+ @@google_font_names ||= all.select { |font|
36
+ font.collection == 'google'
37
+ }.map(&:name)
38
+ end
39
+
40
+ def google_font_url_for_fonts(fonts)
41
+ "//fonts.googleapis.com/css?family=#{ fonts.map { |font| font.gsub(' ', '+') }.join('|') }"
42
+ end
43
+
44
+ def google_font_url_for_all_fonts
45
+ google_font_url_for_fonts(google_font_names)
46
+ end
47
+
48
+ def google_font_url_for_theme
49
+ theme = Dugway.theme
50
+ fonts = theme.fonts.keys.map { |key|
51
+ theme.customization[key] }.select { |font_name|
52
+ google_font_names.include? font_name }.sort
53
+
54
+ if fonts.present?
55
+ google_font_url_for_fonts(fonts)
56
+ else
57
+ nil
58
+ end
59
+ end
60
+
61
+ private
62
+
63
+ def source
64
+ @@source ||= HashWithIndifferentAccess.new(YAML.load(File.read(File.join(File.dirname(__FILE__), 'data', 'theme_fonts.yml'))))
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,3 @@
1
+ module Dugway
2
+ VERSION = "0.5.0"
3
+ end
@@ -0,0 +1 @@
1
+ {"category":"custom","content":"<p>We're really cool!</p>","permalink":"about-us","name":"About Us","id":95821979,"url":"/about-us"}
@@ -0,0 +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":475,"secure_url":"https://s3.amazonaws.com/bigcartel/product_images/92599166/mens_tee_1.jpg","url":"http://cache1.bigcartel.com/product_images/92599166/mens_tee_1.jpg"},{"width":475,"height":475,"secure_url":"https://s3.amazonaws.com/bigcartel/product_images/92599178/mens_tee_2.jpg","url":"http://cache1.bigcartel.com/product_images/92599178/mens_tee_2.jpg"},{"width":475,"height":475,"secure_url":"https://s3.amazonaws.com/bigcartel/product_images/92599196/mens_tee_3.jpg","url":"http://cache1.bigcartel.com/product_images/92599196/mens_tee_3.jpg"},{"width":475,"height":475,"secure_url":"https://s3.amazonaws.com/bigcartel/product_images/92599214/mens_tee_4.jpg","url":"http://cache0.bigcartel.com/product_images/92599214/mens_tee_4.jpg"},{"width":475,"height":475,"secure_url":"https://s3.amazonaws.com/bigcartel/product_images/92599226/mens_tee_5.jpg","url":"http://cache1.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":false,"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://s3.amazonaws.com/bigcartel/product_images/95272745/mens_tee_8.jpg","url":"http://cache0.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":false,"permalink":"my-print","name":"My 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/my-print"}]
@@ -0,0 +1 @@
1
+ {"website":"","artists":[{"permalink":"artist-one","name":"Artist One","id":176141,"url":"/artist/artist-one"},{"permalink":"artist-two","name":"Artist Two","id":176144,"url":"/artist/artist-two"}],"products_count":3,"currency":{"sign":"$","name":"U.S. Dollar","id":1,"code":"USD"},"country":{"name":"United States","id":43,"code":"US"},"categories":[{"permalink":"cds","name":"CDs","id":4615184,"url":"/category/cds"},{"permalink":"hats","name":"Hats","id":4615187,"url":"/category/hats"},{"permalink":"prints","name":"Prints","id":4615190,"url":"/category/prints"},{"permalink":"tees","name":"Tees","id":4615193,"url":"/category/tees"}],"name":"Dugway","pages":[{"permalink":"about-us","name":"About Us"}],"url":"http://dugway.bigcartel.com","description":""}
@@ -0,0 +1,33 @@
1
+ <div>
2
+ {% if cart.items != blank %}
3
+ <form method="post" action="/cart">
4
+ <h1>Cart</h1>
5
+
6
+ <ul>
7
+ {% for item in cart.items %}
8
+ <li>
9
+ <a href="{{ item.product.url }}" style="background-image: url({{ item.product.image | product_image_url size:"thumb" }});">{{ item.name }}</a>
10
+ <span><a href="{{ item.product.url }}">{{ item.product.name }}</a></span>
11
+ {% unless item.product.has_default_option %}
12
+ <span>{{ item.option.name }}</span>
13
+ {% endunless %}
14
+ </li>
15
+ {% endfor %}
16
+
17
+ <li>
18
+ <label>Total:</label>
19
+ <span>{{ cart.total | money_with_sign }}</span>
20
+ </li>
21
+
22
+ <li>
23
+ <button type="submit"name="checkout" title="Checkout" class="button">Checkout Now</button>
24
+ </li>
25
+ </ul>
26
+ </form>
27
+ {% else %}
28
+ <div>
29
+ <h1>Your cart is empty</h1>
30
+ <p>Sounds like a good time to <a href="/">start shopping</a>.</p>
31
+ </div>
32
+ {% endif %}
33
+ </div>
@@ -0,0 +1,31 @@
1
+ <!DOCTYPE html>
2
+ <head>
3
+ <title>{{ store.name }} &mdash; {{ page.name }}</title>
4
+ <meta charset="utf-8">
5
+ <meta name="description" content="{{ page.meta_description }}">
6
+ <meta name="keywords" content="{{ page.meta_keywords }}">
7
+ <link href="{{ theme | theme_css_url }}" media="screen" rel="stylesheet" type="text/css">
8
+ <script type="text/javascript" charset="utf-8">
9
+ function checkout() {
10
+ if(top != self) {
11
+ top.location.replace(self.location.href);
12
+ } else {
13
+ document.checkout_form.submit();
14
+ }
15
+ }
16
+ </script>
17
+ {{ head_content }}
18
+ </head>
19
+
20
+ <body id="{{ page.permalink }}" class="{{ page.category }}" onload="checkout();">
21
+ <div>
22
+ <h2>One moment...</h2>
23
+ </div>
24
+
25
+ {% checkoutform %}
26
+ <noscript>
27
+ <input type="submit" value="Checkout" />
28
+ </noscript>
29
+ {% endcheckoutform %}
30
+ </body>
31
+ </html>
@@ -0,0 +1,37 @@
1
+ <div>
2
+ {% if contact.sent %}
3
+ <h1>Thank You!</h1>
4
+ <p>Your message has been sent and we will try to respond within 24 business hours.</p>
5
+ {% else %}
6
+ <h1>{{ page.name }}</h1>
7
+ <form method="post" action="/contact">
8
+ <ul>
9
+ <li>
10
+ <label>Your Name:</label>
11
+ {{ contact | contact_input: 'name' }}
12
+ </li>
13
+ <li>
14
+ <label>Your Email:</label>
15
+ {{ contact | contact_input: 'email' }}
16
+ </li>
17
+ <li>
18
+ <label>Subject:</label>
19
+ {{ contact | contact_input: 'subject' }}
20
+ </li>
21
+ <li>
22
+ <label>Message:</label>
23
+ {{ contact | contact_input: 'message' }}
24
+ </li>
25
+ <li id="captcha_img" class="clearfix">
26
+ <label>Spam Check:</label>
27
+ <p>Please enter the characters from the image.</p>
28
+ {{ contact | contact_input: 'captcha' }}
29
+ <div id="captcha_phrase">{{ contact.captcha }}</div>
30
+ </li>
31
+ <li>
32
+ <button type="submit" name="submit" class="button">Send Message</button>
33
+ </li>
34
+ </ul>
35
+ </form>
36
+ {% endif %}
37
+ </div>
@@ -0,0 +1,38 @@
1
+ <div>
2
+ {% paginate products from products.all by 20 %}
3
+ {% if products != blank %}
4
+ <ul>
5
+ {% for product in products %}
6
+ <li id="product_{{ product.id }}">
7
+ <a href="{{ product.url }}">
8
+ <img alt="Image of {{ product.name | escape }}" src="{{ product.image | product_image_url size: theme.product_list_size }}" />
9
+ <div>
10
+ <div>
11
+ <span>{{ product.name }}</span>
12
+ <span>{{ product.default_price | money_with_sign }}{% case product.status %}{% when 'sold-out' %} / Sold Out{% when 'coming-soon' %} / Coming Soon{% when 'active' %}{% if product.on_sale %} / On Sale{% endif %}{% endcase %}</span>
13
+ </div>
14
+ </div>
15
+ </a>
16
+ </li>
17
+ {% endfor %}
18
+ </ul>
19
+
20
+ <div class="pagination" id="pagination">
21
+ {% if paginate.previous %}
22
+ {% if paginate.previous.is_link %}
23
+ <a href="{{ paginate.previous.url }}" id="previous" class="circle">&larr;<em>Previous</em></a>
24
+ {% endif %}
25
+ {% endif %}
26
+
27
+ {% if paginate.next %}
28
+ {% if paginate.next.is_link %}
29
+ <a href="{{ paginate.next.url }}" id="next" class="circle">&rarr;<em>Next</em></a>
30
+ {% endif %}
31
+ {% endif %}
32
+ </div>
33
+
34
+ {% else %}
35
+ <p><span>No products found.</span></p>
36
+ {% endif %}
37
+ {% endpaginate %}
38
+ </div>
@@ -0,0 +1,3 @@
1
+ $(function() {
2
+ console.log('One')
3
+ });
@@ -0,0 +1,2 @@
1
+ $ ->
2
+ console.log 'Two'
@@ -0,0 +1,77 @@
1
+ <!DOCTYPE html>
2
+ <head>
3
+ <title>{{ store.name }} &mdash; {{ page.name }}</title>
4
+ <meta charset="utf-8">
5
+ <meta name="description" content="{{ page.meta_description }}">
6
+ <meta name="keywords" content="{{ page.meta_keywords }}">
7
+ <link href="{{ theme | theme_css_url }}" media="screen" rel="stylesheet" type="text/css">
8
+ <script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js" type="text/javascript"></script>
9
+ <script src="{{ 'api' | theme_js_url }}" type="text/javascript"></script>
10
+ <script src="{{ theme | theme_js_url }}" type="text/javascript"></script>
11
+ {{ head_content }}
12
+ </head>
13
+
14
+ <body id="{{ page.permalink }}" class="{{ page.category }}">
15
+ <header>
16
+ <a href="/" title="{{ store.name | escape }}">{{ store.name }}</a>
17
+ </header>
18
+
19
+ <aside>
20
+ <section>
21
+ <a href="/cart">Cart ({{ cart.total | money_with_sign }})</a>
22
+ </section>
23
+
24
+ {% if theme.show_search %}
25
+ <section>
26
+ <form action="/products" method="get">
27
+ <label>Search: <input type="text" name="search"></label>
28
+ </form>
29
+ </section>
30
+ {% endif %}
31
+
32
+ <nav>
33
+ <h3>Products</h3>
34
+ <ul>
35
+ <li><a href="/products">All</a></li>
36
+ {% for category in categories.active %}
37
+ <li>{{ category | link_to }}</li>
38
+ {% endfor %}
39
+ </ul>
40
+
41
+ {% if artists.active != blank %}
42
+ <h3>Artists</h3>
43
+ <ul>
44
+ <li><a href="/products">All</a></li>
45
+ {% for artist in artists.active %}
46
+ <li>{{ artist | link_to }}</li>
47
+ {% endfor %}
48
+ </ul>
49
+ {% endif %}
50
+
51
+ <h3>Info</h3>
52
+ <ul>
53
+ {% for page in pages.all %}
54
+ <li>{{ page | link_to }}</li>
55
+ {% endfor %}
56
+ <li><a href="/contact">Contact Us</a></li>
57
+ {% if store.website != blank %}
58
+ <li><a href="{{ store.website }}">Back to Site</a></li>
59
+ {% endif %}
60
+ </ul>
61
+ </nav>
62
+ </aside>
63
+
64
+ <section>
65
+ {% if page.category == 'custom' %}
66
+ <h1>{{ page.name }}</h1>
67
+ {{ page_content | paragraphs }}
68
+ {% else %}
69
+ {{ page_content }}
70
+ {% endif %}
71
+ </section>
72
+
73
+ <footer>
74
+ <cite>{{ bigcartel_credit }}</cite>
75
+ </footer>
76
+ </body>
77
+ </html>