shopifydev 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +17 -0
- data/.pryrc +3 -0
- data/.root.shopifydev.yaml.sample +21 -0
- data/.ruby-version +1 -0
- data/.shopifydev.yaml.sample +7 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/NEXTSTEPS.md +33 -0
- data/README.md +78 -0
- data/Rakefile +1 -0
- data/bin/shopify_console +15 -0
- data/bin/shopifydev +100 -0
- data/lib/rails/generators/shopifydev/shops_generator.rb +11 -0
- data/lib/rails/generators/shopifydev/templates/shops.rake +5 -0
- data/lib/rails/tasks/shops.rake +7 -0
- data/lib/shopifydev/asset.rb +58 -0
- data/lib/shopifydev/commands.rb +83 -0
- data/lib/shopifydev/config.rb +9 -0
- data/lib/shopifydev/generators/shop.rb +29 -0
- data/lib/shopifydev/generators/templates/Gemfile +10 -0
- data/lib/shopifydev/generators/templates/gitignore +1 -0
- data/lib/shopifydev/generators/templates/rvmrc +1 -0
- data/lib/shopifydev/generators/templates/shopify-tmbundle +21 -0
- data/lib/shopifydev/pry/commands.rb +194 -0
- data/lib/shopifydev/railtie.rb +11 -0
- data/lib/shopifydev/shop.rb +38 -0
- data/lib/shopifydev/template.rb +73 -0
- data/lib/shopifydev/version.rb +3 -0
- data/lib/shopifydev.rb +10 -0
- data/shopifydev.gemspec +35 -0
- data/spec/shopifydev/config_spec.rb +5 -0
- data/spec/shopifydev/generators/shopifydev/shopifydev_generator_spec.rb +5 -0
- data/spec/shopifydev/pry/commands_spec.rb +5 -0
- data/spec/shopifydev/railtie_spec.rb +5 -0
- data/templates/customers/order.liquid +109 -0
- data/templates/customers/register.liquid +42 -0
- data/templates/page.support.liquid +78 -0
- data/templates/page.verbose.liquid +18 -0
- data/templates/product.liquid +284 -0
- data/templates/search.liquid +63 -0
- data/test_driver.rb +31 -0
- metadata +275 -0
data/.gitignore
ADDED
data/.pryrc
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
test_shops:
|
2
|
+
cronin:
|
3
|
+
api_key: akey
|
4
|
+
password: aword
|
5
|
+
myshopify_domain: cronin-group3575.myshopify.com
|
6
|
+
schumm:
|
7
|
+
api_key: anotherkey
|
8
|
+
password: anotherword
|
9
|
+
myshopify_domain: schumm-durgan-and-lang94.myshopify.com
|
10
|
+
|
11
|
+
apps:
|
12
|
+
development:
|
13
|
+
meta: ~/clients/webify/metafieldeditor
|
14
|
+
ship: ~/clients/webify/shipping
|
15
|
+
|
16
|
+
heroku:
|
17
|
+
metafieldseditor: metafieldseditor
|
18
|
+
morfars-metafields: morfars-metafields
|
19
|
+
red-pepper-shipping: red-pepper-shipping
|
20
|
+
shipping-lifemap-bioreagents: shipping-lifemap-bioreagents
|
21
|
+
shipping-staging: shipping-staging
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
ruby-1.9.3-p429
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Michael Johnston
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/NEXTSTEPS.md
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# switch command
|
2
|
+
|
3
|
+
should be some shortcuts
|
4
|
+
|
5
|
+
switch cronin
|
6
|
+
|
7
|
+
should look for shops in an app
|
8
|
+
|
9
|
+
switch with no arguments
|
10
|
+
you get a list:
|
11
|
+
|
12
|
+
test shops:
|
13
|
+
1. cronin
|
14
|
+
|
15
|
+
apps (development):
|
16
|
+
1. metafieldseditor
|
17
|
+
2. shipping
|
18
|
+
|
19
|
+
apps (heroku):
|
20
|
+
1. metafieldseditor
|
21
|
+
2. shipping
|
22
|
+
|
23
|
+
|
24
|
+
|
25
|
+
when you choose
|
26
|
+
|
27
|
+
|
28
|
+
# To check out
|
29
|
+
|
30
|
+
https://github.com/pry/pry-coolline
|
31
|
+
https://github.com/cldwalker/bond
|
32
|
+
|
33
|
+
|
data/README.md
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
# Shopifydev
|
2
|
+
|
3
|
+
Abstract out and port to ruby the functionality of the shopify textmate bundle for use in other editors.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'shopifydev'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install shopifydev
|
18
|
+
|
19
|
+
Once Shopifydev is installed, you'll need to add a .shopifydev.yaml file to your project root. This config
|
20
|
+
file should contain the secrets specific to the shopify site you are working on. Here's a sample:
|
21
|
+
|
22
|
+
api_key: youneedakey
|
23
|
+
password: andapassword
|
24
|
+
url: my_store_url.myshopify.com
|
25
|
+
project_root: relative/path (this might just be '.' for a lot of you cats)
|
26
|
+
project_root_variable: SOME_ENVIRONMENT_VARIABLE
|
27
|
+
|
28
|
+
Don't include 'http://' in the url, and don't commit this file to your repo (because secrets). The project
|
29
|
+
root should be the directory where the 'assets' directory lives. If you would rather use an environment
|
30
|
+
variable specific to your text editor of choice, like TM_PROJECT_DIRECTORY, you can supply that as well.
|
31
|
+
Shopifydev will always prefer the environment variable, though.
|
32
|
+
|
33
|
+
## Usage
|
34
|
+
|
35
|
+
WARNING: Files will always be uploaded from `project_root/`. This is great, because it means you can keep
|
36
|
+
the shopify files separate from whatever sweet app you happen to be working on. Unfortunately, at the
|
37
|
+
moment, this means autocompletion of file names really only works if `project_root` is `'.'`. But Imma fix
|
38
|
+
that.
|
39
|
+
|
40
|
+
With shopifydev uploading a shopify file is a snap!
|
41
|
+
|
42
|
+
$ shopifydev upload assets/some_pic.jpg
|
43
|
+
|
44
|
+
Uploading two files is also a snap!
|
45
|
+
|
46
|
+
$ shopifydev upload assets/cart.png templates/cart.liquid
|
47
|
+
|
48
|
+
More files? It's a UNIX system! You know this!
|
49
|
+
|
50
|
+
$ shopifydev upload {snippets,templates}/*.liquid
|
51
|
+
|
52
|
+
But Mr Authors, what if I don't have any files to upload?
|
53
|
+
|
54
|
+
$ shopify download
|
55
|
+
|
56
|
+
What could be better than that? How about uploading all your files:
|
57
|
+
|
58
|
+
$ shopifydev upload --patchify patch_directory
|
59
|
+
|
60
|
+
(I wouldn't recommend running that with '.' or any directory that contains subdirectories shopify wouldn't recognize. I'll fix that someday too! (^o ^)//)
|
61
|
+
|
62
|
+
Oh, you don't want to upload all your files, and you're too lazy to glob?
|
63
|
+
Use `--gitify` to upload all the shopify files with changes.
|
64
|
+
|
65
|
+
$ shopifydev upload --gitify
|
66
|
+
|
67
|
+
(this uses the output of `git status --porcelain`, and it also runs `git add` on all those files so that
|
68
|
+
you won't upload a file twice unless it gets changed twice in the same commit)
|
69
|
+
|
70
|
+
One final tip: `alias upify='shopifydev upload'`
|
71
|
+
|
72
|
+
## Contributing
|
73
|
+
|
74
|
+
1. Fork it
|
75
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
76
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
77
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
78
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/bin/shopify_console
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'pry'
|
3
|
+
require 'shopifydev'
|
4
|
+
require 'shopifydev/pry/commands'
|
5
|
+
|
6
|
+
|
7
|
+
MY_OBJ = []
|
8
|
+
|
9
|
+
def bob
|
10
|
+
"yo, bob here"
|
11
|
+
end
|
12
|
+
# start a REPL session
|
13
|
+
binding.pry
|
14
|
+
|
15
|
+
puts "Thank you for using Shopify Console. Enjoy your day."
|
data/bin/shopifydev
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'gli'
|
3
|
+
begin # XXX: Remove this begin/rescue before distributing your app
|
4
|
+
require 'shopifydev'
|
5
|
+
rescue LoadError
|
6
|
+
STDERR.puts "In development, you need to use `bundle exec bin/todo` to run your app"
|
7
|
+
STDERR.puts "At install-time, RubyGems will make sure lib, etc. are in the load path"
|
8
|
+
STDERR.puts "Feel free to remove this message from bin/foxhole now"
|
9
|
+
exit 64
|
10
|
+
end
|
11
|
+
|
12
|
+
include GLI::App
|
13
|
+
|
14
|
+
program_desc "Upload shopify files from the command-line like a boss."
|
15
|
+
|
16
|
+
version Shopifydev::VERSION
|
17
|
+
|
18
|
+
desc 'verbose'
|
19
|
+
switch [:v, :verbose]
|
20
|
+
|
21
|
+
desc 'Download the theme from an existing shopify site'
|
22
|
+
arg_name '' # Download take no particular args
|
23
|
+
command :download do |c|
|
24
|
+
|
25
|
+
c.action do |global_options,options,args|
|
26
|
+
|
27
|
+
Shopifydev::CommandRunner.new.download(options)
|
28
|
+
|
29
|
+
# If you have any errors, just raise them
|
30
|
+
# raise "that command made no sense"
|
31
|
+
|
32
|
+
puts "download command ran"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
desc 'Upload a particular file to shopify'
|
37
|
+
arg_name 'remote key' # upload requires the remote key be specified here
|
38
|
+
command :upload do |c|
|
39
|
+
|
40
|
+
c.desc 'Upload all files from a given root'
|
41
|
+
c.default_value 'none'
|
42
|
+
c.arg_name 'patch_root'
|
43
|
+
c.flag [:p, :patchify]
|
44
|
+
|
45
|
+
c.desc 'Upload all files with changes in git'
|
46
|
+
c.default_value 'none'
|
47
|
+
c.switch [:g, :gitify]
|
48
|
+
|
49
|
+
c.action do |global_options,options,args|
|
50
|
+
gitify = options[:gitify] != 'none'
|
51
|
+
patchify = options[:patchify] != 'none'
|
52
|
+
raise "gitify and patchify are mutually exclusive" if gitify && patchify
|
53
|
+
|
54
|
+
mode = (patchify) ? 'patchify' : ''
|
55
|
+
mode = (gitify) ? 'gitify' : '' if mode.blank?
|
56
|
+
|
57
|
+
runner = Shopifydev::CommandRunner.new
|
58
|
+
|
59
|
+
case mode
|
60
|
+
when 'patchify'
|
61
|
+
puts mode
|
62
|
+
raise "patchify takes no args" if args.length > 0
|
63
|
+
|
64
|
+
runner.patchify(options[:p])
|
65
|
+
when 'gitify'
|
66
|
+
puts mode
|
67
|
+
raise "patchify takes no args" if args.length > 0
|
68
|
+
|
69
|
+
runner.gitify
|
70
|
+
else
|
71
|
+
puts mode
|
72
|
+
runner.upload(args)
|
73
|
+
end
|
74
|
+
|
75
|
+
puts "upload command ran"
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
pre do |global,command,options,args|
|
80
|
+
# Pre logic here
|
81
|
+
# Return true to proceed; false to abourt and not call the
|
82
|
+
# chosen command
|
83
|
+
# Use skips_pre before a command to skip this block
|
84
|
+
# on that command only
|
85
|
+
true
|
86
|
+
end
|
87
|
+
|
88
|
+
post do |global,command,options,args|
|
89
|
+
# Post logic here
|
90
|
+
# Use skips_post before a command to skip this
|
91
|
+
# block on that command only
|
92
|
+
end
|
93
|
+
|
94
|
+
on_error do |exception|
|
95
|
+
# Error logic here
|
96
|
+
# return false to skip default error handling
|
97
|
+
true
|
98
|
+
end
|
99
|
+
|
100
|
+
exit run(ARGV)
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'shopify_api'
|
2
|
+
require 'filemagic'
|
3
|
+
|
4
|
+
module Shopifydev
|
5
|
+
class Asset
|
6
|
+
attr_accessor :shop, :remote_key
|
7
|
+
|
8
|
+
def initialize(shop, path=ENV['TM_FILEPATH'], project_root)
|
9
|
+
puts "in asset::initialize"
|
10
|
+
@shop = shop
|
11
|
+
|
12
|
+
# Asset name should be relative to TM_PROJECT_DIRECTORY
|
13
|
+
# but if it isn't, then gsub just doesn't replace anything
|
14
|
+
# so if you know the key, you can just supply the key?
|
15
|
+
unless project_root.nil?
|
16
|
+
@remote_key = path.gsub(project_root + '/', '') # fix absolute path
|
17
|
+
@local_path = Pathname.new(project_root + '/' + @remote_key) # prepend project root
|
18
|
+
else
|
19
|
+
raise Exception, "could no determine project_root. In .shopifydev.yaml include\n project_root: relative/path"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def upload(root=nil)
|
24
|
+
# check that it's not binary
|
25
|
+
puts "in upload"
|
26
|
+
|
27
|
+
puts "creating asset for " + @remote_key
|
28
|
+
puts @remote_key
|
29
|
+
asset = ShopifyAPI::Asset.new(:key => @remote_key)
|
30
|
+
|
31
|
+
puts "filling with 1's and 0's from " + @local_path.to_path
|
32
|
+
|
33
|
+
contents = File.read(@local_path.to_path)
|
34
|
+
|
35
|
+
fm = FileMagic.new
|
36
|
+
|
37
|
+
if (fm.file(@local_path.realpath.to_path).include?('image'))
|
38
|
+
asset.attach contents
|
39
|
+
else
|
40
|
+
asset.value = contents
|
41
|
+
end
|
42
|
+
|
43
|
+
# TODO this doesn't fail spectacularly enough... I don't
|
44
|
+
# feel comfortable with that
|
45
|
+
puts "saving..."
|
46
|
+
if asset.valid?
|
47
|
+
if asset.save
|
48
|
+
puts "Success!"
|
49
|
+
else
|
50
|
+
puts "failed to save"
|
51
|
+
end
|
52
|
+
else
|
53
|
+
puts "failed to validate"
|
54
|
+
end
|
55
|
+
puts "---"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
|
2
|
+
require "logger"
|
3
|
+
require "shopify_api"
|
4
|
+
|
5
|
+
module Shopifydev
|
6
|
+
class CommandRunner
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@devshop = Shopifydev::Shop.new(credentials)
|
10
|
+
end
|
11
|
+
|
12
|
+
def credentials
|
13
|
+
unless @credentials
|
14
|
+
@credentials = YAML::load(
|
15
|
+
File.open('.shopifydev.yaml'))
|
16
|
+
end
|
17
|
+
|
18
|
+
@credentials
|
19
|
+
end
|
20
|
+
|
21
|
+
def upload(remote_keys)
|
22
|
+
# upload one asset or directory
|
23
|
+
raise "no shopify files were specified" if remote_keys.empty?
|
24
|
+
|
25
|
+
remote_keys.each do |remote_key|
|
26
|
+
if File.directory?(remote_key) then
|
27
|
+
self.upload_dir(remote_key)
|
28
|
+
else
|
29
|
+
@devshop.asset(remote_key).upload
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def patchify(patch_dir)
|
35
|
+
|
36
|
+
ENV['PATCHIFY_ROOT'] = patch_dir # temporarily set an environment variable
|
37
|
+
|
38
|
+
Dir.glob(File.join(ENV['PATCHIFY_ROOT'], "*/*")).reverse.each do |file|
|
39
|
+
|
40
|
+
self.upload(Array.wrap(File.join(file.split('/')[-2..-1])))
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def gitify
|
45
|
+
porcelain = `git status --porcelain`
|
46
|
+
|
47
|
+
modified = porcelain.scan(/^[ AM][M](.*)/).flatten.each {|f| f.strip!}
|
48
|
+
|
49
|
+
remote_keys = modified.delete_if do |file|
|
50
|
+
not ["assets", "snippets", "templates", "layout"].include?(file.split('/')[0].strip)
|
51
|
+
end
|
52
|
+
|
53
|
+
remote_keys.each do |file|
|
54
|
+
`git add #{file}`
|
55
|
+
end
|
56
|
+
|
57
|
+
upload(remote_keys)
|
58
|
+
end
|
59
|
+
|
60
|
+
def upload_dir(upload_dir)
|
61
|
+
# upload all assets in the given dir
|
62
|
+
|
63
|
+
Dir[upload_dir + "/*"].each do |remote_key|
|
64
|
+
self.upload(remote_key)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def upload_glob(glob)
|
69
|
+
# upload all assets in the given dir matching a given pattern
|
70
|
+
|
71
|
+
glob.each do |remote_key|
|
72
|
+
self.upload(remote_key)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def download(options={})
|
77
|
+
# Download the whole template
|
78
|
+
|
79
|
+
@devshop.template.download
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Shopifydev
|
2
|
+
module Generators
|
3
|
+
class Shop < Thor::Group
|
4
|
+
include Thor::Actions
|
5
|
+
|
6
|
+
source_root File.expand_path('../templates', __FILE__)
|
7
|
+
|
8
|
+
argument :name
|
9
|
+
class_option :test_shop
|
10
|
+
class_option :live_shop
|
11
|
+
|
12
|
+
def setup
|
13
|
+
create_file "#{name}/TODO"
|
14
|
+
copy_file "Gemfile", "#{name}/Gemfile"
|
15
|
+
copy_file "rvmrc", "#{name}/.rvmrc"
|
16
|
+
copy_file "gitignore", "#{name}/.gitignore"
|
17
|
+
copy_file "shopify-tmbundle", "#{name}/.shopify-tmbundle"
|
18
|
+
system "git init"
|
19
|
+
system "git add --all"
|
20
|
+
system 'git commit -m "initial setup"'
|
21
|
+
end
|
22
|
+
|
23
|
+
def download_template
|
24
|
+
say "TODO: automate downloading template from test shop"
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
.shopify-tmbundle
|
@@ -0,0 +1 @@
|
|
1
|
+
rvm use ruby-1.9.3-p194@shopify
|
@@ -0,0 +1,21 @@
|
|
1
|
+
; config file for shopify.tmbundle
|
2
|
+
; You can now setup multiple shops. Just follow the pattern you see below.
|
3
|
+
; You can have more than 2 (as many as you want really)
|
4
|
+
; this config uses ini style http://php.net/manual/en/function.parse-ini-file.php
|
5
|
+
; you can just change the settings under default, and everything should work.
|
6
|
+
; or you can do things the old way as well.
|
7
|
+
|
8
|
+
; this is the currently active shop. you can change it here
|
9
|
+
use="default"
|
10
|
+
|
11
|
+
; test shop for development
|
12
|
+
[default]
|
13
|
+
api_key="###TEST_SHOP_API_KEY###"
|
14
|
+
password="###TEST_SHOP_PASSWORD###"
|
15
|
+
store="TEST_SHOP_DOMAIN"
|
16
|
+
|
17
|
+
; and the live shop
|
18
|
+
[live]
|
19
|
+
api_key="###LIVE_SHOP_API_KEY###"
|
20
|
+
password="###LIVE_SHOP_PASSWORD###"
|
21
|
+
store="###LIVE_SHOP_DOMAIN###"
|