solidus_liquid 0.0.1.alpha

Sign up to get free protection for your applications and to get access to all the features.
Files changed (139) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +10 -0
  3. data/.rspec +2 -0
  4. data/.rubocop.yml +36 -0
  5. data/.travis.yml +10 -0
  6. data/CODE_OF_CONDUCT.md +74 -0
  7. data/Gemfile +3 -0
  8. data/Guardfile +37 -0
  9. data/LICENSE.txt +21 -0
  10. data/README.md +84 -0
  11. data/Rakefile +35 -0
  12. data/app/controllers/concerns/solidus_liquid/liquid.rb +26 -0
  13. data/app/controllers/solidus_liquid/addresses_controller.rb +15 -0
  14. data/app/controllers/solidus_liquid/carts_controller.rb +15 -0
  15. data/app/controllers/solidus_liquid/collections_controller.rb +22 -0
  16. data/app/controllers/solidus_liquid/customers_controller.rb +16 -0
  17. data/app/controllers/solidus_liquid/home_controller.rb +15 -0
  18. data/app/controllers/solidus_liquid/liquid_controller.rb +25 -0
  19. data/app/controllers/solidus_liquid/orders_controller.rb +18 -0
  20. data/app/controllers/solidus_liquid/pages_controller.rb +22 -0
  21. data/app/controllers/solidus_liquid/products_controller.rb +30 -0
  22. data/app/controllers/solidus_liquid/registrations_controller.rb +25 -0
  23. data/app/controllers/solidus_liquid/responders/solidus_liquid/liquid_responder.rb +29 -0
  24. data/app/controllers/solidus_liquid/search_controller.rb +41 -0
  25. data/app/controllers/solidus_liquid/sessions_controller.rb +15 -0
  26. data/app/drops/rails_settings/scoped_settings_drop.rb +11 -0
  27. data/app/drops/solidus_liquid/errors_drop.rb +14 -0
  28. data/app/drops/solidus_liquid/link_drop.rb +15 -0
  29. data/app/drops/solidus_liquid/link_list_drop.rb +7 -0
  30. data/app/drops/solidus_liquid/nil_drop.rb +7 -0
  31. data/app/drops/solidus_liquid/page_drop.rb +7 -0
  32. data/app/drops/solidus_liquid/search_drop.rb +7 -0
  33. data/app/drops/spree/address_drop.rb +24 -0
  34. data/app/drops/spree/image_drop.rb +10 -0
  35. data/app/drops/spree/line_item_drop.rb +5 -0
  36. data/app/drops/spree/option_type_drop.rb +4 -0
  37. data/app/drops/spree/order_drop.rb +18 -0
  38. data/app/drops/spree/product_drop.rb +92 -0
  39. data/app/drops/spree/taxon_drop.rb +31 -0
  40. data/app/drops/spree/user_drop.rb +19 -0
  41. data/app/drops/spree/variant_drop.rb +80 -0
  42. data/app/filters/solidus_liquid/additional_filters.rb +22 -0
  43. data/app/filters/solidus_liquid/html_filters.rb +20 -0
  44. data/app/filters/solidus_liquid/money_filters.rb +15 -0
  45. data/app/filters/solidus_liquid/string_filters.rb +11 -0
  46. data/app/filters/solidus_liquid/url_filters.rb +55 -0
  47. data/app/helpers/solidus_liquid/liquid_helper.rb +107 -0
  48. data/app/helpers/solidus_liquid/shop_helper.rb +7 -0
  49. data/app/models/concerns/solidus_liquid/address.rb +15 -0
  50. data/app/models/concerns/solidus_liquid/full_name.rb +11 -0
  51. data/app/models/concerns/solidus_liquid/handle.rb +25 -0
  52. data/app/models/concerns/solidus_liquid/inventory_policy.rb +7 -0
  53. data/app/models/solidus_liquid/asset.rb +12 -0
  54. data/app/models/solidus_liquid/link.rb +10 -0
  55. data/app/models/solidus_liquid/link_list.rb +7 -0
  56. data/app/models/solidus_liquid/page.rb +5 -0
  57. data/app/models/solidus_liquid/setting.rb +8 -0
  58. data/app/models/solidus_liquid/theme.rb +19 -0
  59. data/app/models/spree/address_decorator.rb +20 -0
  60. data/app/models/spree/image_decorator.rb +19 -0
  61. data/app/models/spree/product_decorator.rb +14 -0
  62. data/app/models/spree/taxon_decorator.rb +5 -0
  63. data/app/models/spree/variant_decorator.rb +15 -0
  64. data/app/poro/solidus_liquid/search.rb +14 -0
  65. data/app/services/solidus_liquid/app_specific_string_io.rb +15 -0
  66. data/app/services/solidus_liquid/asset_compiler.rb +11 -0
  67. data/app/services/solidus_liquid/asset_postprocessor.rb +53 -0
  68. data/app/services/solidus_liquid/link_list_seeder.rb +26 -0
  69. data/app/services/solidus_liquid/liquid_asset_compiler.rb +19 -0
  70. data/app/services/solidus_liquid/scss_asset_compiler.rb +15 -0
  71. data/app/services/solidus_liquid/shop_settings_seeder.rb +26 -0
  72. data/app/services/solidus_liquid/theme_mechanic.rb +45 -0
  73. data/app/uploaders/solidus_liquid/asset_uploader.rb +10 -0
  74. data/app/views/solidus_liquid/global/content_for_header.html.erb +0 -0
  75. data/app/views/solidus_liquid/themes/skeleton-theme/README.md +54 -0
  76. data/app/views/solidus_liquid/themes/skeleton-theme/assets/arrow-down.svg.liquid +3 -0
  77. data/app/views/solidus_liquid/themes/skeleton-theme/assets/cart.svg.liquid +4 -0
  78. data/app/views/solidus_liquid/themes/skeleton-theme/assets/shop.js.liquid +75 -0
  79. data/app/views/solidus_liquid/themes/skeleton-theme/assets/shopify_common.js +14 -0
  80. data/app/views/solidus_liquid/themes/skeleton-theme/assets/style.scss.liquid +768 -0
  81. data/app/views/solidus_liquid/themes/skeleton-theme/config/settings.html +217 -0
  82. data/app/views/solidus_liquid/themes/skeleton-theme/config/settings_data.json +26 -0
  83. data/app/views/solidus_liquid/themes/skeleton-theme/layout/theme.liquid +181 -0
  84. data/app/views/solidus_liquid/themes/skeleton-theme/snippets/article-grid-item.liquid +73 -0
  85. data/app/views/solidus_liquid/themes/skeleton-theme/snippets/collection-grid-item.liquid +46 -0
  86. data/app/views/solidus_liquid/themes/skeleton-theme/snippets/collection-listing.liquid +46 -0
  87. data/app/views/solidus_liquid/themes/skeleton-theme/snippets/open-graph-tags.liquid +35 -0
  88. data/app/views/solidus_liquid/themes/skeleton-theme/snippets/product-grid-item.liquid +70 -0
  89. data/app/views/solidus_liquid/themes/skeleton-theme/snippets/site-nav.liquid +57 -0
  90. data/app/views/solidus_liquid/themes/skeleton-theme/snippets/social-links.liquid +42 -0
  91. data/app/views/solidus_liquid/themes/skeleton-theme/snippets/twitter-card.liquid +41 -0
  92. data/app/views/solidus_liquid/themes/skeleton-theme/templates/404.liquid +2 -0
  93. data/app/views/solidus_liquid/themes/skeleton-theme/templates/article.liquid +160 -0
  94. data/app/views/solidus_liquid/themes/skeleton-theme/templates/blog.grid.liquid +30 -0
  95. data/app/views/solidus_liquid/themes/skeleton-theme/templates/blog.liquid +92 -0
  96. data/app/views/solidus_liquid/themes/skeleton-theme/templates/cart.liquid +123 -0
  97. data/app/views/solidus_liquid/themes/skeleton-theme/templates/collection.liquid +102 -0
  98. data/app/views/solidus_liquid/themes/skeleton-theme/templates/customers/account.liquid +57 -0
  99. data/app/views/solidus_liquid/themes/skeleton-theme/templates/customers/activate_account.liquid +26 -0
  100. data/app/views/solidus_liquid/themes/skeleton-theme/templates/customers/addresses.liquid +173 -0
  101. data/app/views/solidus_liquid/themes/skeleton-theme/templates/customers/login.liquid +90 -0
  102. data/app/views/solidus_liquid/themes/skeleton-theme/templates/customers/order.liquid +103 -0
  103. data/app/views/solidus_liquid/themes/skeleton-theme/templates/customers/register.liquid +32 -0
  104. data/app/views/solidus_liquid/themes/skeleton-theme/templates/customers/reset_password.liquid +27 -0
  105. data/app/views/solidus_liquid/themes/skeleton-theme/templates/index.liquid +39 -0
  106. data/app/views/solidus_liquid/themes/skeleton-theme/templates/list-collections.liquid +19 -0
  107. data/app/views/solidus_liquid/themes/skeleton-theme/templates/page.liquid +16 -0
  108. data/app/views/solidus_liquid/themes/skeleton-theme/templates/product.liquid +202 -0
  109. data/app/views/solidus_liquid/themes/skeleton-theme/templates/search.liquid +72 -0
  110. data/bin/rails +12 -0
  111. data/config/app.yml +0 -0
  112. data/config/initializers/carrierwave.rb +25 -0
  113. data/config/initializers/devise.rb +286 -0
  114. data/config/initializers/form_tag.rb +43 -0
  115. data/config/initializers/liquid.rb +202 -0
  116. data/config/initializers/sass.rb +15 -0
  117. data/config/initializers/theme_settings.rb +29 -0
  118. data/config/routes.rb +48 -0
  119. data/db/migrate/20170223064316_create_solidus_liquid_assets.solidus_liquid.rb +14 -0
  120. data/db/migrate/20170223064317_create_solidus_liquid_themes.solidus_liquid.rb +10 -0
  121. data/db/migrate/20170223064318_create_solidus_liquid_link_lists.solidus_liquid.rb +12 -0
  122. data/db/migrate/20170223064319_create_solidus_liquid_links.solidus_liquid.rb +13 -0
  123. data/db/migrate/20170223064320_create_solidus_liquid_settings.solidus_liquid.rb +22 -0
  124. data/db/migrate/20170223064321_create_solidus_liquid_pages.solidus_liquid.rb +16 -0
  125. data/db/migrate/20170223064322_add_attributes_to_spree_users.solidus_liquid.rb +7 -0
  126. data/db/migrate/20170223064323_add_handle_to_spree_taxons.solidus_liquid.rb +7 -0
  127. data/lib/generators/solidus_liquid/install/install_generator.rb +13 -0
  128. data/lib/solidus_liquid.rb +11 -0
  129. data/lib/solidus_liquid/configuration.rb +21 -0
  130. data/lib/solidus_liquid/engine.rb +24 -0
  131. data/lib/solidus_liquid/factories.rb +7 -0
  132. data/lib/solidus_liquid/version.rb +3 -0
  133. data/lib/tasks/download_theme.rake +18 -0
  134. data/lib/tasks/seed_default_theme.rake +8 -0
  135. data/lib/tasks/seed_everything.rake +14 -0
  136. data/lib/tasks/seed_link_list.rake +8 -0
  137. data/lib/tasks/seed_shop_settings.rake +8 -0
  138. data/solidus_liquid.gemspec +56 -0
  139. metadata +586 -0
@@ -0,0 +1,12 @@
1
+ module SolidusLiquid
2
+ class Asset < ActiveRecord::Base
3
+ mount_uploader :file, AssetUploader
4
+ belongs_to :theme
5
+
6
+ before_save :postprocess_asset
7
+
8
+ def postprocess_asset
9
+ AssetPostprocessor.new(self).process if file_changed?
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,10 @@
1
+ module SolidusLiquid
2
+ class Link < ActiveRecord::Base
3
+ extend FriendlyId
4
+ friendly_id :name, use: [:finders, :slugged], slug_column: :url
5
+
6
+ belongs_to :link_list
7
+
8
+ alias_attribute :title, :name
9
+ end
10
+ end
@@ -0,0 +1,7 @@
1
+ module SolidusLiquid
2
+ class LinkList < ActiveRecord::Base
3
+ include SolidusLiquid::Handle
4
+
5
+ has_many :links
6
+ end
7
+ end
@@ -0,0 +1,5 @@
1
+ module SolidusLiquid
2
+ class Page < ActiveRecord::Base
3
+ include SolidusLiquid::Handle
4
+ end
5
+ end
@@ -0,0 +1,8 @@
1
+ module SolidusLiquid
2
+ # RailsSettings Model
3
+ class Setting < ::RailsSettings::Base
4
+ # self.table_name = "#{SolidusLiquid::Engine.engine_name}_settings"
5
+ source Rails.root.join('config', 'app.yml')
6
+ namespace Rails.env
7
+ end
8
+ end
@@ -0,0 +1,19 @@
1
+ module SolidusLiquid
2
+ class Theme < ActiveRecord::Base
3
+ has_many :assets
4
+
5
+ def settings
6
+ settings = Redis.current.get("solidus_liquid_themes_#{id}")
7
+ settings ||= Redis.current.get('solidus_liquid_themes_')
8
+ JSON.parse(settings)
9
+ end
10
+
11
+ def previewable
12
+ true
13
+ end
14
+
15
+ def processing
16
+ false
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,20 @@
1
+ module Spree
2
+ Address.class_eval do
3
+ include ::SolidusLiquid::Address
4
+ include ::SolidusLiquid::FullName
5
+
6
+ def default
7
+ user_addresses.first.try(:default)
8
+ end
9
+
10
+ def province
11
+ state.name
12
+ end
13
+
14
+ def province_code
15
+ state.abbr
16
+ end
17
+
18
+ alias_attribute :zip, :zipcode
19
+ end
20
+ end
@@ -0,0 +1,19 @@
1
+ module Spree
2
+ Image.class_eval do
3
+ def attached_to_variant?
4
+ !viewable.is_master?
5
+ end
6
+
7
+ def product_id
8
+ viewable.try(:product_id)
9
+ end
10
+
11
+ def src
12
+ attachment.try(:url)
13
+ end
14
+
15
+ def variants
16
+ [viewable]
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,14 @@
1
+ module Spree
2
+ Product.class_eval do
3
+ include ::RailsSettings::Extend
4
+ include ::SolidusLiquid::Handle
5
+
6
+ def available
7
+ variants.any?(&:available)
8
+ end
9
+
10
+ # display_image just shows first image
11
+ # probably producing many queries on the db
12
+ alias_method :featured_image, :display_image
13
+ end
14
+ end
@@ -0,0 +1,5 @@
1
+ module Spree
2
+ Taxon.class_eval do
3
+ include ::SolidusLiquid::Handle
4
+ end
5
+ end
@@ -0,0 +1,15 @@
1
+ module Spree
2
+ Variant.class_eval do
3
+ include SolidusLiquid::InventoryPolicy
4
+ # Returns true if the variant is available for purchase, or false if it not.
5
+ # For a variant to be available, its variant.inventory_quantity must be
6
+ # greater than zero or variant.inventory_policy must be set to continue. A
7
+ # variant with no variant.inventory_management is also considered available.
8
+ def available
9
+ true
10
+ # inventory_management.blank? ||
11
+ # inventory_policy == INVENTORY_POLICY_ALLOW ||
12
+ # inventory_quantity(??? check VariantDrop) > 0
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,14 @@
1
+ module SolidusLiquid
2
+ class Search
3
+ include ::Liquid::Rails::Droppable
4
+
5
+ attr_accessor :performed, :results, :results_count, :terms
6
+
7
+ def initialize(performed: nil, results: nil, results_count: nil, terms: nil)
8
+ @performed = performed
9
+ @results = results
10
+ @results_count = results_count
11
+ @terms = terms
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,15 @@
1
+ # copied from: https://github.com/carrierwaveuploader/carrierwave/wiki/How-to:-Upload-from-a-string-in-Rails-3-or-later
2
+ module SolidusLiquid
3
+ class AppSpecificStringIO < StringIO
4
+ attr_accessor :filepath
5
+
6
+ def initialize(*args)
7
+ super(*args[1..-1])
8
+ @filepath = args[0]
9
+ end
10
+
11
+ def original_filename
12
+ File.basename(@filepath)
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,11 @@
1
+ module SolidusLiquid
2
+ module AssetCompiler
3
+ def initialize(template)
4
+ @template = template
5
+ end
6
+
7
+ def compile
8
+ raise 'Implement in subclass'
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,53 @@
1
+ module SolidusLiquid
2
+ class AssetPostprocessor
3
+ def initialize(asset)
4
+ @asset = asset
5
+ end
6
+
7
+ def process
8
+ process_for_key(
9
+ asset: @asset,
10
+ key: @asset.key,
11
+ template: File.read(@asset.file.path),
12
+ settings: @asset.theme.settings
13
+ )
14
+ end
15
+
16
+ private
17
+
18
+ def process_for_key(asset:, key:, template:, settings:)
19
+ return unless key.start_with?('assets/')
20
+ if key.end_with?('.liquid')
21
+ process_liquid(asset: asset, key: key.gsub(/.liquid$/, ''),
22
+ template: template, settings: settings)
23
+ elsif key.end_with?('.scss')
24
+ process_scss(asset: asset, key: key, template: template)
25
+ end
26
+ end
27
+
28
+ def process_liquid(asset:, key:, template:, settings:)
29
+ rendered_liquid = LiquidAssetCompiler.new(template, settings,
30
+ asset.theme).compile
31
+ if key.end_with?('.scss')
32
+ process_scss(asset: asset, key: key, template: rendered_liquid)
33
+ else
34
+ update_or_create_asset(key: key,
35
+ theme: asset.theme, contents: rendered_liquid)
36
+ end
37
+ end
38
+
39
+ def process_scss(asset:, key:, template:)
40
+ rendered_css = ScssAssetCompiler.new(template).compile
41
+ new_asset = Asset.where(key: "#{key}.css",
42
+ theme: asset.theme).first_or_initialize
43
+ new_asset.update_attributes(
44
+ file: AppSpecificStringIO.new("#{key}.css", rendered_css)
45
+ )
46
+ end
47
+
48
+ def update_or_create_asset(key:, theme:, contents:)
49
+ new_asset = Asset.where(key: key, theme: theme).first_or_initialize
50
+ new_asset.update_attributes(file: AppSpecificStringIO.new(key, contents))
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,26 @@
1
+ module SolidusLiquid
2
+ class LinkListSeeder
3
+ # rubocop:disable Metrics/MethodLength
4
+ def seed
5
+ LinkList.create(
6
+ [
7
+ {
8
+ title: 'Main menu',
9
+ handle: 'main-menu',
10
+ links: [
11
+ Link.new(title: 'Home', url: '/'),
12
+ Link.new(title: 'Catalog', url: '/collections/all')
13
+ ]
14
+ },
15
+ {
16
+ title: 'Footer',
17
+ handle: 'footer',
18
+ links: [
19
+ Link.new(title: 'Search', url: '/search')
20
+ ]
21
+ }
22
+ ]
23
+ )
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,19 @@
1
+ module SolidusLiquid
2
+ class LiquidAssetCompiler
3
+ include AssetCompiler
4
+
5
+ def initialize(template, settings, theme)
6
+ super(template)
7
+ @settings = settings
8
+ @theme = theme
9
+ end
10
+
11
+ def compile
12
+ liquid = ::Liquid::Template.parse(@template)
13
+ assigns = { 'settings' => @settings }
14
+ liquid.render(assigns,
15
+ filters: [UrlFilters],
16
+ registers: { theme: @theme })
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,15 @@
1
+ module SolidusLiquid
2
+ class ScssAssetCompiler
3
+ include AssetCompiler
4
+
5
+ def compile
6
+ options = {
7
+ style: :compressed,
8
+ syntax: :scss,
9
+ cache: false,
10
+ full_exception: true
11
+ }
12
+ ::Sass::Engine.new(@template, options).render
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,26 @@
1
+ module SolidusLiquid
2
+ class ShopSettingsSeeder
3
+ def initialize(theme_id)
4
+ @theme_id = theme_id
5
+ end
6
+
7
+ # rubocop:disable Metrics/MethodLength
8
+ def seed
9
+ {
10
+ 'active_theme_id' => @theme_id,
11
+ 'checkout' => { 'guest_login' => false },
12
+ 'currency' => 'USD',
13
+ 'customer_accounts_enabled' => true,
14
+ 'customer_accounts_optional' => true,
15
+ 'description' => '',
16
+ 'domain' => ENV.fetch('DOMAIN_NAME'),
17
+ 'enabled_payment_types' => nil,
18
+ 'money_format' => '€{{amount}}',
19
+ 'money_with_currency_format' => '€{{amount}} EUR',
20
+ 'name' => 'Split'
21
+ }.each do |k, v|
22
+ SolidusLiquid::Setting[k] = v
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,45 @@
1
+ module SolidusLiquid
2
+ class ThemeMechanic
3
+ def initialize(
4
+ name: 'Simple',
5
+ path: SolidusLiquid::Engine.root.join(
6
+ 'app', 'views', 'solidus_liquid', 'themes', 'skeleton-theme'
7
+ ),
8
+ skip_file_upload: false
9
+ )
10
+ @name = name
11
+ @path = path
12
+ @skip_file_upload = skip_file_upload
13
+ end
14
+
15
+ def create
16
+ theme = Theme.new(name: @name)
17
+
18
+ files = Dir.glob("#{@path}/**/*")
19
+ instantiate_assets_from_files(files, theme)
20
+
21
+ theme.save!
22
+ theme
23
+ end
24
+
25
+ def instantiate_assets_from_files(files, theme)
26
+ files.each do |file|
27
+ next if Dir.exist?(file) # skip directories
28
+ theme.assets << asset_from_file(file)
29
+ end
30
+ end
31
+
32
+ def asset_from_file(file)
33
+ asset = Asset.new(key: Pathname.new(file).relative_path_from(@path).to_s)
34
+ if @skip_file_upload
35
+ asset.file = File.basename(file)
36
+ else
37
+ File.open(file) do |f|
38
+ asset.file = f
39
+ end
40
+ end
41
+
42
+ asset
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,10 @@
1
+ module SolidusLiquid
2
+ class AssetUploader < ::CarrierWave::Uploader::Base
3
+ def store_dir
4
+ asset_file_dir = model.key.split('/')
5
+ asset_file_dir.pop
6
+ asset_file_dir = asset_file_dir.join('/')
7
+ "themes/#{model.theme_id}/#{asset_file_dir}"
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,54 @@
1
+ Skeleton theme
2
+ ============
3
+
4
+ The Skeleton theme is a simplified Shopify theme, to be used as a "blank slate" starting point for theme designers.
5
+
6
+ <b>Features:</b>
7
+ - Almost no theme settings. Ready to be customized any way you want.
8
+ - Only ~500 lines of CSS including comments.
9
+ - Despite its 500 lines of CSS code, it is responsive and has styled drop-down menus.
10
+ - Include SVG images to style select elements and cart icon.
11
+ - Commented code to teach you Liquid concepts in practice.
12
+
13
+ <b>Demo:</b>
14
+
15
+ - [Demo store](http://skeleton.myshopify.com/)
16
+
17
+ Designing a store for a client? Earn 20% revenue through our <a href="http://www.shopify.com/partners">Partner program<a/>.
18
+
19
+ Getting started
20
+ ---------------------
21
+ 1. <a href="https://github.com/Shopify/skeleton-theme/archive/master.zip">Download</a> the latest version
22
+ 2. or clone the git repo: <code>git clone https://github.com/Shopify/skeleton-theme.git</code>
23
+
24
+ Basic structure
25
+ ---------------
26
+ ```
27
+ ├── assets
28
+ │ └── Javascript, CSS, and theme images
29
+ ├── config
30
+ │ └── custom Theme Settings
31
+ ├── layout
32
+ │ ├── theme.liquid
33
+ │ └── optional alternate layouts
34
+ ├── snippets
35
+ │ └── optional custom code snippets
36
+ ├── templates
37
+ │ ├── 404.liquid
38
+ │ ├── article.liquid
39
+ │ ├── blog.liquid
40
+ │ ├── cart.liquid
41
+ │ ├── collection.liquid
42
+ │ ├── index.liquid
43
+ │ ├── page.liquid
44
+ │ ├── product.liquid
45
+ │ └── search.liquid
46
+ │ └── list-collections.liquid
47
+ ```
48
+
49
+ Additional resources
50
+ ---------------------
51
+ - <a href="http://meetup.shopify.com/">Free workshops</a>: Sign up for a free Shopify For Designers workshop in a city near you.
52
+ - <a href="http://docs.shopify.com/themes">Theme Documentation</a>: Learn more about Liquid and theme templates.
53
+ - <a href="http://apps.shopify.com/desktop-theme-editor">Desktop Theme Editor</a>: For Mac OS X users, we recommend our free app to sync theme files in development.
54
+ - Need more help? Ask a question in our <a href="http://ecommerce.shopify.com/c/ecommerce-design"> Design Forums</a>.