solidus_liquid 0.0.1.alpha

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 (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>.