jekyll_remote_assets 0.1.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 (3) hide show
  1. checksums.yaml +7 -0
  2. data/lib/jekyll_remote_assets.rb +171 -0
  3. metadata +65 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 8f68758084318ca0826f198ad193561eaadc6ed0
4
+ data.tar.gz: 3509c3789e3ba1336da8493fd0826b577ff06813
5
+ SHA512:
6
+ metadata.gz: 5fce80ddeb49d69f0533c406d9ae78607c810af9fd9be45c0eb7bd27c92d1bc2f61982498299e5a17c7d3812babf7d39afbf7da76d5a358e2040719538522679
7
+ data.tar.gz: d7bbff9c56a4e6b8bc926f508b57fb8ed3e8846583b36659d01ce4db8a00707554f6e137c9dc1335fd88fe7a4b153fa1d68c1ca493e6339b4924860a2f25f94c
@@ -0,0 +1,171 @@
1
+ require 'uri'
2
+ require 'unirest'
3
+ require 'set'
4
+
5
+ module Jekyll
6
+ module RemoteAsset
7
+
8
+ module SitePatch
9
+ def remote_assets
10
+ @remote_assets ||= {}
11
+ end
12
+ end
13
+
14
+ Jekyll::Site.send :include, Jekyll::RemoteAsset::SitePatch
15
+
16
+ class RemoteAssetTag < Liquid::Tag
17
+ def initialize(tag_name, asset_name, tokens)
18
+ super
19
+ @asset_name = asset_name.strip
20
+ end
21
+
22
+ def render(context)
23
+ "#{ context.registers[:site].remote_assets[@asset_name] }"
24
+ end
25
+ end
26
+
27
+ Liquid::Template.register_tag('asset', Jekyll::RemoteAsset::RemoteAssetTag)
28
+
29
+ class Generator < Jekyll::Generator
30
+ REQUEST_TOKEN_URL = "https://api.dropbox.com/1/oauth/request_token"
31
+ ACCESS_TOKEN_URL = "https://api.dropbox.com/1/oauth/access_token"
32
+ FILES_PUT_URL = "https://api-content.dropbox.com/1/files_put/auto"
33
+ FILE_METADATA_URL = "https://api.dropbox.com/1/metadata/auto"
34
+ SHARES_URL = "https://api.dropbox.com/1/shares/auto"
35
+
36
+ def config_oauth(plugin_config)
37
+ @oauth_config = {}
38
+ config_file = plugin_config["config"] || __dir__ + "/.remote_assets_config"
39
+ if not File.exist?(config_file)
40
+ puts "1. Create a new application on the Dropbox App Console, if you haven't already: https://www.dropbox.com/developers/apps"
41
+ $stdin.gets
42
+
43
+ puts "2. Please enter your app key. "
44
+ @oauth_config[:app_key] = $stdin.gets.strip
45
+
46
+ puts "3. Please enter your app secret. "
47
+ @oauth_config[:app_secret] = $stdin.gets.strip
48
+
49
+ response = Unirest.post REQUEST_TOKEN_URL,
50
+ headers: { "Authorization" => build_oauth1_header(@oauth_config[:app_key], @oauth_config[:app_secret]) }
51
+
52
+ request_tokens = CGI::parse(response.body)
53
+
54
+ puts "4. Visit https://www.dropbox.com/1/oauth/authorize?oauth_token=#{ request_tokens['oauth_token'][0] } and approve this app. Press enter when finished."
55
+ $stdin.gets
56
+
57
+ response = Unirest.post ACCESS_TOKEN_URL,
58
+ headers: {"Authorization" => build_oauth1_header(@oauth_config[:app_key], @oauth_config[:app_secret], request_tokens['oauth_token'][0], request_tokens['oauth_token_secret'][0]) }
59
+
60
+ access_tokens = CGI::parse(response.body)
61
+
62
+ @oauth_config[:access_token] = access_tokens['oauth_token'][0]
63
+ @oauth_config[:access_token_secret] = access_tokens['oauth_token_secret'][0]
64
+
65
+ File.open(config_file, 'w+') do |f|
66
+ YAML.dump(@oauth_config, f)
67
+ end
68
+ else
69
+ File.open(config_file) do |f|
70
+ @oauth_config = YAML.load_file(f)
71
+ end
72
+ end
73
+ end
74
+
75
+ def init_cache(plugin_config)
76
+ @cache = {}
77
+ cache_file = plugin_config["cache"] || __dir__ + "/.remote_assets_cache"
78
+
79
+ # TODO: fix first-time set up of cache
80
+ if not File.exist?(cache_file)
81
+ File.open(cache_file, 'w+') do |f|
82
+ YAML.dump(@cache, f)
83
+ end
84
+ end
85
+
86
+ File.open(cache_file) do |f|
87
+ @cache = YAML.load_file(f)
88
+ end
89
+ end
90
+
91
+ def nonce(size = 7)
92
+ Base64.encode64(OpenSSL::Random.random_bytes(size)).gsub(/\W/, '')
93
+ end
94
+
95
+ def build_oauth1_header(app_key, app_secret, token=nil, token_secret=nil)
96
+ header_params = {
97
+ oauth_version: "1.0",
98
+ oauth_consumer_key: app_key,
99
+ oauth_signature_method: "PLAINTEXT",
100
+ oauth_token: token,
101
+ oauth_signature: "#{ app_secret }&#{ token_secret }"
102
+ }
103
+
104
+ result = header_params.map do |k, v|
105
+ "#{ k }=\"#{ v }\"" if v
106
+ end
107
+
108
+ return "OAuth #{ result.compact.join ', ' }"
109
+ end
110
+
111
+ def generate(site)
112
+ plugin_config = site.config["remote_assets"] || {}
113
+ config_oauth(plugin_config)
114
+ init_cache(plugin_config)
115
+
116
+ file_set = Set.new
117
+
118
+ Dir.glob("_assets/**/*") do |filename|
119
+ begin
120
+ next if File.directory?(filename)
121
+
122
+ name = filename[filename.index('/')..-1]
123
+ overwrite = plugin_config['overwrite'] || true
124
+
125
+ File.open(filename) do |f|
126
+ file_set.add filename
127
+
128
+ md5 = Digest::MD5.file(filename).hexdigest
129
+ if @cache[filename] and @cache[filename][:md5] == md5
130
+ # if it's cached, make sure the file is still in the Dropbox drive
131
+ response = Unirest.get FILE_METADATA_URL + name,
132
+ headers: {"Authorization" => build_oauth1_header(@oauth_config[:app_key], @oauth_config[:app_secret], @oauth_config[:access_token], @oauth_config[:access_token_secret])}
133
+
134
+ if response.body["error"] == nil && !response.body["is_deleted"]
135
+ site.remote_assets[name[1..name.length]] = @cache[filename][:url]
136
+ next
137
+ end
138
+ end
139
+
140
+ # upload the file
141
+ response = Unirest.put FILES_PUT_URL + name + "?overwrite=#{ overwrite }",
142
+ headers: {"Authorization" => build_oauth1_header(@oauth_config[:app_key], @oauth_config[:app_secret], @oauth_config[:access_token], @oauth_config[:access_token_secret]),
143
+ "Content-Length" => File::size(f),
144
+ "Content-Type" => "text/plain"},
145
+ parameters: f
146
+
147
+ # retrieve the url
148
+ response = Unirest.post SHARES_URL + name,
149
+ headers: {"Authorization" => build_oauth1_header(@oauth_config[:app_key], @oauth_config[:app_secret], @oauth_config[:access_token], @oauth_config[:access_token_secret])},
150
+ parameters: {short_url: false}
151
+
152
+ uri = URI(response.body["url"])
153
+ site.remote_assets[name[1..-1]] = "http://dl.dropboxusercontent.com#{ uri.path }"
154
+
155
+ @cache[filename] = { md5: md5, url: "http://dl.dropboxusercontent.com#{ uri.path }"}
156
+ end
157
+ rescue
158
+ puts "Error uploading #{ filename }"
159
+ end
160
+ end
161
+ @cache.delete_if { |key, value| not file_set.include? key }
162
+
163
+ # TODO: clean up file saving
164
+ File.open(plugin_config["cache"] || __dir__ + "/.remote_assets_cache", 'w+') do |f|
165
+ YAML.dump(@cache, f)
166
+ end
167
+ end
168
+ end
169
+
170
+ end
171
+ end
metadata ADDED
@@ -0,0 +1,65 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jekyll_remote_assets
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Aaron Broder
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-03-21 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: unirest
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.1'
20
+ - - '>='
21
+ - !ruby/object:Gem::Version
22
+ version: 1.1.2
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '1.1'
30
+ - - '>='
31
+ - !ruby/object:Gem::Version
32
+ version: 1.1.2
33
+ description:
34
+ email: aaronbroder@gmail.com
35
+ executables: []
36
+ extensions: []
37
+ extra_rdoc_files: []
38
+ files:
39
+ - lib/jekyll_remote_assets.rb
40
+ homepage: https://github.com/abroder/jekyll-remote-assets
41
+ licenses:
42
+ - MIT
43
+ metadata: {}
44
+ post_install_message:
45
+ rdoc_options: []
46
+ require_paths:
47
+ - lib
48
+ required_ruby_version: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - '>='
51
+ - !ruby/object:Gem::Version
52
+ version: '0'
53
+ required_rubygems_version: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - '>='
56
+ - !ruby/object:Gem::Version
57
+ version: '0'
58
+ requirements: []
59
+ rubyforge_project:
60
+ rubygems_version: 2.4.5
61
+ signing_key:
62
+ specification_version: 4
63
+ summary: Automatically upload static assets to Dropbox on site generation to save
64
+ on server costs
65
+ test_files: []