vapid 0.1.2 → 0.1.3

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 556c2464ab664d12716b9aa0e667dd11d663edc5
4
- data.tar.gz: a56555d344f0277090d06c52d8a7efd0809fc464
3
+ metadata.gz: 9dca8a0632172a7cd5c13c853dada608dd278b60
4
+ data.tar.gz: 4ec0be44b5311e4e49718c9588c4ee604389c1ba
5
5
  SHA512:
6
- metadata.gz: 92a59742ea2b378905fa5d59d329ce49cf278d52515fce565ca1019a734c6bb8894d292293f7c4482f5e860da14699c290b1c98be835fb33a8f9c53548021f7e
7
- data.tar.gz: 2d259c98b3ad956e51c11ea98cda9714236188a0c503d4976a7722c141dc44ebea479a2af47018ea9ca9544d6e7aa636e5c5c33145a10a3bed56a5752ec0c8b5
6
+ metadata.gz: 9ffff0e3149dafc97c930f1eb5fc275070ff40ea2938a3523319062c0f1fb32e605b1e60a7905a4c7056685f90f21c941abd62a5ff8697e1206313fc97c74aae
7
+ data.tar.gz: 3ab1f4b9be6f3039c6b360d6d7506f5ac6456189a85b2d23060a6e9a8e5e679b724b9eca873fd8776cf86b3993570460d8a925c6ceaeab93cf02d163956892d3
@@ -1,5 +1,9 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.3
4
+ * Cache rendered templates
5
+ * Updated generator example
6
+
3
7
  ## 0.1.2
4
8
  * Changed dashboard route from `/admin` to `/dashboard`
5
9
  * Updated styles to match new design
@@ -9,8 +9,10 @@ end
9
9
 
10
10
  # Top-level namespace
11
11
  module Vapid
12
+ autoload :API, "vapid/api"
12
13
  autoload :Builder, "vapid/builder"
13
14
  autoload :CLI, "vapid/cli"
15
+ autoload :Deployer, "vapid/deployer"
14
16
  autoload :Directive, "vapid/directive"
15
17
  autoload :Directives, "vapid/directives"
16
18
  autoload :Models, "vapid/models"
@@ -0,0 +1,74 @@
1
+ require "faraday"
2
+ require "base64"
3
+
4
+ module Vapid
5
+ # This is a big ol' placeholder class
6
+ # TODO: Think through an API
7
+ class API
8
+ def initialize(token = nil)
9
+ @conn = conn(token)
10
+ end
11
+
12
+ class << self
13
+ def base_url
14
+ ENV["API_URL"] || "https://api.vapid.com"
15
+ end
16
+
17
+ def base_uri
18
+ URI.parse(self.base_url).host
19
+ end
20
+
21
+ def version
22
+ 1
23
+ end
24
+
25
+ def version_url
26
+ "#{base_url}/v#{version}"
27
+ end
28
+ end
29
+
30
+ def login(email, password)
31
+ basic_auth_conn = conn(email, password)
32
+ basic_auth_conn.get "auth/login"
33
+ end
34
+
35
+ def create_site(site_name)
36
+ post "sites", name: site_name
37
+ end
38
+
39
+ def update_site(site_id, params)
40
+ patch "sites/#{site_id}", params
41
+ end
42
+
43
+ def presigned_posts(site_id, manifest)
44
+ post "sites/#{site_id}/presigned_posts", manifest: manifest
45
+ end
46
+
47
+ private
48
+
49
+ def post(path, params)
50
+ @conn.post path do |req|
51
+ req.headers["Content-Type"] = "application/json"
52
+ req.body = params.to_json
53
+ end
54
+ end
55
+
56
+ def patch(path, params)
57
+ @conn.patch path do |req|
58
+ req.headers["Content-Type"] = "application/json"
59
+ req.body = params.to_json
60
+ end
61
+ end
62
+
63
+ def conn(email_or_token, password = nil)
64
+ ::Faraday.new(url: self.class.version_url) do |f|
65
+ if password.nil?
66
+ f.token_auth(email_or_token)
67
+ else
68
+ f.basic_auth(email_or_token, password)
69
+ end
70
+ f.adapter :net_http
71
+ end
72
+ end
73
+ end
74
+ end
@@ -3,12 +3,28 @@ module Vapid
3
3
  class Builder
4
4
  class << self
5
5
  def build!(template_files, &block)
6
- project_tree = build_project_tree(template_files, &block)
7
- groups = consolidate_into_groups(project_tree)
6
+ groups = generate_tree(template_files, &block)
8
7
  update_data_model(groups)
9
8
  remove_unused_groups(groups)
10
9
  end
11
10
 
11
+ def generate_tree(template_files, &block)
12
+ project_tree = build_project_tree(template_files, &block)
13
+ consolidate_into_groups(project_tree)
14
+ end
15
+
16
+ def update_data_model(groups)
17
+ groups.each do |name, attributes|
18
+ group = Models::Group.named(name) || Models::Group.new(name: name)
19
+ group.update_attributes attributes
20
+ prune_orphaned_content(group)
21
+ end
22
+ end
23
+
24
+ def remove_unused_groups(used_groups)
25
+ Models::Group.where.not(name: used_groups.keys).destroy_all
26
+ end
27
+
12
28
  private
13
29
 
14
30
  def build_project_tree(template_files)
@@ -28,14 +44,6 @@ module Vapid
28
44
  end
29
45
  end
30
46
 
31
- def update_data_model(groups)
32
- groups.each do |name, attributes|
33
- group = Models::Group.named(name) || Models::Group.new(name: name)
34
- group.update_attributes attributes
35
- prune_orphaned_content(group)
36
- end
37
- end
38
-
39
47
  def parse_file(file)
40
48
  html = File.open(file).read
41
49
  Template.new(html).tree
@@ -58,10 +66,6 @@ module Vapid
58
66
  end
59
67
  end
60
68
 
61
- def remove_unused_groups(used_groups)
62
- Models::Group.where.not(name: used_groups.keys).destroy_all
63
- end
64
-
65
69
  def content_directives
66
70
  @content_directives ||= Directives.content_changers.keys
67
71
  end
@@ -2,6 +2,8 @@ require "thor"
2
2
  require "guard"
3
3
  require "guard/commander"
4
4
  require "thread"
5
+ require "netrc"
6
+ require "json"
5
7
 
6
8
  module Vapid
7
9
  # Command line interface
@@ -55,7 +57,7 @@ module Vapid
55
57
  ensure_user_exists(options.reset_login)
56
58
 
57
59
  say "== Parsing templates for fields"
58
- template_files = Dir[File.join(target, "templates", "**/*")].reject { |f| File.directory? f }
60
+ template_files = files("templates")
59
61
  Builder.build!(template_files) do |filepath|
60
62
  say_status :parse, filepath
61
63
  end
@@ -63,6 +65,24 @@ module Vapid
63
65
  end
64
66
  end
65
67
 
68
+ desc "deploy", "Deploy to Vapid's hosting service"
69
+ map %w(d -d --deploy) => :deploy
70
+ def deploy(target = ".")
71
+ inside_target(target) do
72
+ @api_key = ensure_api_key
73
+ site_id = ensure_site_id
74
+
75
+ project_files = files("templates", "assets")
76
+ Deployer.new(@api_key, site_id).deploy(project_files) do |message, color, status|
77
+ if status
78
+ say_status status, message, color
79
+ else
80
+ say "== #{message}", color
81
+ end
82
+ end
83
+ end
84
+ end
85
+
66
86
  desc "version", "Show the Vapid version number"
67
87
  map %w(v -v --version) => :version
68
88
  def version
@@ -75,7 +95,7 @@ module Vapid
75
95
  if !File.exist? File.join(target, "config.ru")
76
96
  say_status :error, "Could not find a Vapid project in #{expanded_target(target)}", :red
77
97
  else
78
- FileUtils.mkdir_p File.join(target, ".cache")
98
+ ensure_cache_exists(target)
79
99
  inside(target, &block)
80
100
  end
81
101
  end
@@ -84,6 +104,61 @@ module Vapid
84
104
  File.expand_path(target)
85
105
  end
86
106
 
107
+ def ensure_cache_exists(target)
108
+ FileUtils.mkdir_p File.join(target, ".cache")
109
+ FileUtils.touch File.join(target, ".cache", "livereload.txt")
110
+ end
111
+
112
+ def ensure_api_key
113
+ email = nil
114
+ token = nil
115
+ invalid = false
116
+
117
+ loop do
118
+ n = ::Netrc.read
119
+ email, token = n[API.base_uri]
120
+ break if token
121
+
122
+ say "== Enter your Vapid credentials, or signup at vapid.com:" unless invalid
123
+ email = ask "Email:", default: email
124
+ password = ask "Password:", echo: false
125
+ say ""
126
+
127
+ response = API.new(token).login(email, password)
128
+ if response.status == 200
129
+ token = ::JSON.parse(response.body)["api_key"]
130
+ n[API.base_uri] = email, token
131
+ n.save
132
+ else
133
+ invalid = true
134
+ say "== Invalid credentials"
135
+ end
136
+ end
137
+
138
+ token
139
+ end
140
+
141
+ def ensure_site_id
142
+ site_id = Settings.site_id
143
+
144
+ loop do
145
+ break if site_id.present?
146
+
147
+ if yes? "== Is this a new website? (yes/no)"
148
+ site_name = ask "Enter a name:"
149
+ response = API.new(@api_key).create_site(site_name)
150
+ if response.status == 200
151
+ site_id = ::JSON.parse(response.body)["id"]
152
+ end
153
+ else
154
+ site_id = ask "Enter the site_id (found on vapid.com):"
155
+ end
156
+ Settings.replace_site_id(site_id) if site_id.present?
157
+ end
158
+
159
+ site_id
160
+ end
161
+
87
162
  def ensure_user_exists(force)
88
163
  return if !force && Models::User.any?
89
164
 
@@ -102,7 +177,7 @@ module Vapid
102
177
  end
103
178
 
104
179
  loop do
105
- user.password = ask("Enter a password:", echo: false)
180
+ user.password = ask "Enter a password:", echo: false
106
181
  user.valid?
107
182
  say ""
108
183
  break unless user.errors[:password].any?
@@ -120,5 +195,10 @@ module Vapid
120
195
  raise
121
196
  end
122
197
  end
198
+
199
+ def files(*directories)
200
+ paths = directories.map { |dir| File.join(Dir.pwd, dir, "**/*") }
201
+ Dir[*paths].reject { |f| File.directory? f }
202
+ end
123
203
  end
124
204
  end
@@ -123,7 +123,10 @@ module Vapid
123
123
  end
124
124
 
125
125
  def livereload
126
- FileUtils.touch(settings.reload) if settings.development?
126
+ if settings.development?
127
+ cache_clear
128
+ FileUtils.touch(settings.reload)
129
+ end
127
130
  end
128
131
 
129
132
  def run_builder
@@ -183,7 +186,7 @@ module Vapid
183
186
  @code = Settings.install_code
184
187
 
185
188
  # TODO: Should display contextually-relevant error message
186
- if (@code.nil? || @code.casecmp(params[:code]) == 0) && user.save
189
+ if (@code.nil? || @code.casecmp(params[:code]).zero?) && user.save
187
190
  run_builder
188
191
  session[:user_id] = user.id
189
192
  flash[:success] = "Successfully created admin account."
@@ -7,11 +7,25 @@ module Vapid
7
7
  # rubocop:disable Metrics/AbcSize, MethodLength
8
8
  def self.registered(app)
9
9
  app.configure do
10
+ root_path = Pathname.new(app.settings.root)
11
+ tmp_path = Pathname.new(app.settings.project_cache)
12
+ relative_path = tmp_path.relative_path_from(root_path)
13
+
14
+ app.set :cache_enabled, false
15
+ app.set :cache_path, File.join(relative_path, "server")
10
16
  app.set :layouts, File.join(app.settings.project_views, "layouts")
11
17
  end
12
18
 
19
+ app.configure :production do
20
+ app.set :cache_enabled, true
21
+ end
22
+
13
23
  # rubocop:disable Lint/NestedMethodDefinition
14
24
  app.helpers do
25
+ def asset_timestamp(*args)
26
+ super(args) unless settings.deploy
27
+ end
28
+
15
29
  def dynamic_layout(path)
16
30
  path_layout = path.split("/")[1]
17
31
  if path_layout && Dir.glob(File.join(settings.layouts, "#{path_layout}.*")).any?
@@ -31,8 +45,16 @@ module Vapid
31
45
 
32
46
  app.get "*" do
33
47
  path = params[:splat].first.to_s
34
- html = render_or_index(path)
35
- Template.new(html).render
48
+
49
+ cache_block "#{path}_" do
50
+ html = render_or_index(path)
51
+ if app.deploy
52
+ headers["Content-Disposition"] = "inline"
53
+ html
54
+ else
55
+ Template.new(html).render
56
+ end
57
+ end
36
58
  end
37
59
  end
38
60
  # rubocop:enable Metrics/AbcSize, MethodLength
@@ -0,0 +1,179 @@
1
+ require "rack/test"
2
+ require "rack/mime"
3
+ require "faraday"
4
+
5
+ # TODO: DRY for path, relative_path, and build_path
6
+
7
+ module Vapid
8
+ # Deploys to Vapid's hosting service
9
+ class Deployer
10
+ MIMES = {
11
+ "text/css" => "css",
12
+ "application/javascript" => "js",
13
+ "text/html" => "html"
14
+ }.freeze
15
+
16
+ def initialize(api_key, site_id)
17
+ @api = API.new(api_key)
18
+ @site_id = site_id
19
+ end
20
+
21
+ def deploy(project_files, &cli)
22
+ @cli = cli
23
+ @project_files = project_files
24
+ @manifest = {}
25
+ @site_changed = false
26
+
27
+ begin
28
+ config_server
29
+ prepare_build_dir
30
+ build_site
31
+ return unless upload_files
32
+ update_site
33
+ rescue Exception => e
34
+ cli_say "Deploy Error: #{e.message}", color: :red
35
+ end
36
+ end
37
+
38
+ private
39
+
40
+ def config_server
41
+ Server.set :deploy, true
42
+ end
43
+
44
+ def prepare_build_dir
45
+ FileUtils.mkdir_p build_dir
46
+ FileUtils.rm_rf "#{build_dir}/."
47
+ end
48
+
49
+ def build_site
50
+ cli_say "Building site"
51
+ @project_files.each do |file|
52
+ path = relative_path(file)
53
+ next unless renderable?(path)
54
+
55
+ save_path = render_and_save(path)
56
+ @manifest["/#{path}"] = Digest::MD5.file(save_path).hexdigest
57
+
58
+ cli_say file, color: :blue, status: :build
59
+ end
60
+ end
61
+
62
+ def upload_files
63
+ presigned_posts = request_presigned_posts
64
+
65
+ if presigned_posts.empty?
66
+ cli_say "Nothing new to deploy"
67
+ return false
68
+ end
69
+
70
+ cli_say "Uploading files"
71
+ @manifest.each do |path, _digest|
72
+ post = presigned_posts[path]
73
+ say_path = path.gsub(/^\//, '')
74
+
75
+ if post
76
+ conn = Faraday.new(post["url"]) do |f|
77
+ f.request :multipart
78
+ f.request :url_encoded
79
+ f.adapter :net_http
80
+ end
81
+
82
+ file_path = File.join(build_dir, path)
83
+ file_mime = Rack::Mime.mime_type(File.extname(path))
84
+ file = Faraday::UploadIO.new(file_path, file_mime)
85
+
86
+ payload = post["fields"].merge file: file
87
+ conn.post "/", payload
88
+
89
+ cli_say say_path, color: :yellow, status: :upload
90
+ else
91
+ cli_say say_path, color: :blue, status: :exists
92
+ end
93
+ end
94
+ end
95
+
96
+ def update_site
97
+ fields = Builder.generate_tree(Dir.glob("#{build_dir}/templates/**/*"))
98
+ response = @api.update_site @site_id, { manifest: @manifest, fields: fields }
99
+ json = ::JSON.parse(response.body)
100
+ if response.status == 200
101
+ site_url = json["url"]
102
+ cli_say "#{site_url} deployed to Vapid"
103
+ else
104
+ cli_say "Deploy Error: #{json["errors"]}", color: :red
105
+ end
106
+ end
107
+
108
+ def render_and_save(path)
109
+ content = render(path)
110
+ write_file(path, content)
111
+ end
112
+
113
+ def request_presigned_posts
114
+ response = @api.presigned_posts @site_id, @manifest
115
+ ::JSON.parse(response.body)["presigned_posts"] if response.status == 200
116
+ end
117
+
118
+ def relative_path(file)
119
+ path = Pathname.new(file).relative_path_from(cwd).to_s
120
+ convert_extensions(path)
121
+ end
122
+
123
+ def convert_extensions(path)
124
+ exts = File.basename(path).split(".")[1..-1].reverse
125
+
126
+ exts.each do |ext|
127
+ template_engine = Tilt.template_for(ext)
128
+ break unless template_engine
129
+
130
+ path.chomp! ".#{ext}"
131
+
132
+ # Special case for the last ext
133
+ if ext == exts[-1]
134
+ # TODO: Replace with Rack::Mime
135
+ ext = MIMES[template_engine.metadata[:mime_type]]
136
+ path += ".#{ext}"
137
+ end
138
+ end
139
+
140
+ path
141
+ end
142
+
143
+ def render(path)
144
+ uri = URI.escape path.sub(/^templates\//, '')
145
+ response = request.get uri
146
+ response.body
147
+ end
148
+
149
+ def write_file(path, contents)
150
+ save_path = File.join(build_dir, path)
151
+ save_dir = File.dirname(save_path)
152
+ FileUtils.mkdir_p(save_dir) unless File.directory?(save_dir)
153
+ File.open(save_path, "wb") { |f| f.write(contents) }
154
+ save_path
155
+ end
156
+
157
+ def renderable?(path)
158
+ !File.basename(path).start_with?("_") && !path.start_with?("templates/layouts")
159
+ end
160
+
161
+ def cwd
162
+ Pathname.new(Dir.pwd)
163
+ end
164
+
165
+ def build_dir
166
+ File.join(Dir.pwd, ".cache", "build")
167
+ end
168
+
169
+ def request
170
+ @request ||= ::Rack::MockRequest.new(Server)
171
+ end
172
+
173
+ def cli_say(message, color: :green, status: nil)
174
+ return unless @cli
175
+
176
+ @cli.call message, color, status
177
+ end
178
+ end
179
+ end
@@ -1,11 +1,12 @@
1
- defaults: &defaults
1
+ shared: &shared
2
2
  debug: false
3
+ site_id: ''
3
4
 
4
5
  development:
5
- <<: *defaults
6
+ <<: *shared
6
7
  secret_key: <%= SecureRandom.hex(64) %>
7
8
 
8
9
  production:
9
- <<: *defaults
10
+ <<: *shared
10
11
  install_code: <%= SecureRandom.hex(3) %>
11
12
  secret_key: <%%= ENV["SECRET_KEY"] %>
@@ -6,13 +6,30 @@
6
6
  <main>
7
7
  <div>
8
8
  <img src="https://cdn.vapid.com/logo.png" class="logo" alt="Vapid logo" onerror="this.style.display='none'">
9
- <p>Welcome to Vapid. This is an example page, to help you get started and understand the basics.</p>
10
- <p>To begin, create two tags anywhere in the HTML of this page:</p>
11
- <pre><code>&lt;h1 vp-text="title"&gt;&lt;/h1&gt;
9
+
10
+ <!-- BEGIN EXAMPLE (delete to uncomment) ->
11
+
12
+ <h1 vp-text="headline"></h1>
13
+ <div vp-richtext="body"></div>
14
+
15
+ <!- END EXAMPLE (delete to uncomment) -->
16
+
17
+ <div vp-hide="headline">
18
+ <p>Welcome to Vapid. This is an example page, to help you get started and understand the basics.</p>
19
+ <p>To begin, open up <code>template/index.html.erb</code> and uncomment the following HTML:</p>
20
+
21
+ <pre><code>&lt;h1 vp-text="headline"&gt;&lt;/h1&gt;
12
22
  &lt;div vp-richtext="body"&gt;&lt;/div&gt;
13
23
  </code></pre>
14
- <p>The <code>vp-</code> attributes you see tell Vapid two things: 1) what type of content you'd like placed inside of the tag (e.g. <code>vp-richtext</code>); and 2) what you'd like to name the variable (e.g. <code>body</code>).</p>
15
- <p>Now visit <a href="/dashboard" target="_blank">the dashboard</a> to see how you can edit content.</p>
24
+
25
+ <p>The <code>vp-</code> attributes you see tell Vapid two things: 1) what type of content you'd like placed inside of the tag (e.g. <code>vp-richtext</code>); and 2) what you'd like to name the variable (e.g. <code>body</code>).</p>
26
+
27
+ <p>Now visit <a href="/dashboard" target="_blank">the dashboard</a> to edit content.</p>
28
+ </div>
29
+
30
+ <div class="congrats" vp-show="headline">
31
+ Congrats, you did it!<br> Now, head on over to <a href="https://www.vapid.com" target="_blank">vapid.com</a> to learn more.
32
+ </div>
16
33
  </div>
17
34
  </main>
18
35
 
@@ -36,6 +53,10 @@
36
53
  text-decoration: underline;
37
54
  }
38
55
 
56
+ h1 {
57
+ margin-bottom: 0.5em;
58
+ }
59
+
39
60
  main {
40
61
  display: flex;
41
62
  height: 100%;
@@ -48,7 +69,8 @@
48
69
  max-width: 100%;
49
70
  }
50
71
 
51
- code {
72
+ code,
73
+ .congrats {
52
74
  display: inline-block;
53
75
  background: #333;
54
76
  padding: 0 0.25em;
@@ -56,12 +78,17 @@
56
78
  vertical-align: bottom;
57
79
  }
58
80
 
59
- pre > code {
81
+ pre > code,
82
+ .congrats {
60
83
  display: block;
61
84
  margin: 2em 0;
62
85
  padding: 1em;
63
86
  }
64
87
 
88
+ .congrats {
89
+ font-size: 14px;
90
+ }
91
+
65
92
  p {
66
93
  margin-bottom: 1em;
67
94
  line-height: 1.3em;
@@ -9,7 +9,7 @@ module Vapid
9
9
  has_many :records, dependent: :destroy
10
10
  accepts_nested_attributes_for :records, allow_destroy: true
11
11
 
12
- default_scope { order("name = '#{DEFAULT_NAME}' DESC, created_at DESC") }
12
+ default_scope { order("groups.name = '#{DEFAULT_NAME}' DESC, groups.created_at DESC") }
13
13
  scope :with_fields, -> { where("fields <> ?", "{}") }
14
14
 
15
15
  def self.named(name)
@@ -1,5 +1,6 @@
1
1
  require "sinatra/base"
2
2
  require "sinatra/activerecord"
3
+ require "sinatra/cacher"
3
4
  require "sinatra/extension"
4
5
  require "sinatra/flash"
5
6
  require "sinatra/namespace"
@@ -19,25 +20,23 @@ module Vapid
19
20
  enable :logging
20
21
  set :quiet, true
21
22
 
22
- set :gem_pwd, File.dirname(__FILE__)
23
- set :gem_assets, File.join(gem_pwd, "assets")
24
- set :gem_views, File.join(gem_pwd, "views")
23
+ set :gem_dir, File.dirname(__FILE__)
24
+ set :gem_assets, File.join(gem_dir, "assets")
25
+ set :gem_views, File.join(gem_dir, "views")
25
26
 
26
- set :project_pwd, Dir.pwd
27
- set :project_assets, File.join(project_pwd, "assets")
28
- set :project_views, File.join(project_pwd, "templates")
27
+ set :project_dir, Dir.pwd
28
+ set :project_assets, File.join(project_dir, "assets")
29
+ set :project_views, File.join(project_dir, "templates")
30
+ set :project_cache, File.join(project_dir, ".cache")
29
31
  set :project_uploads, File.join(project_assets, "uploads")
30
32
 
31
- set :vendor_assets, File.join(gem_pwd, "vendor")
32
-
33
- set :uri_root, "assets"
34
33
  set :public_folder, project_assets
35
-
36
- set :sprockets, Sprockets::Environment.new
37
-
38
- set :cache, File.join(project_pwd, ".cache")
39
- set :reload, File.join(cache, "livereload.txt")
40
34
  set :protect_from_csrf, true
35
+ set :reload, File.join(project_cache, "livereload.txt")
36
+ set :sprockets, Sprockets::Environment.new
37
+ set :uri_root, "assets"
38
+ set :vendor_assets, File.join(gem_dir, "vendor")
39
+ set :deploy, false
41
40
 
42
41
  sprockets.append_path project_assets
43
42
  sprockets.append_path gem_assets
@@ -53,7 +52,6 @@ module Vapid
53
52
  set :show_exceptions, :after_handler
54
53
  use Rack::LiveReload, no_swf: true,
55
54
  ignore: [%r{^/(dashboard)}]
56
- FileUtils.touch settings.reload
57
55
  end
58
56
 
59
57
  configure :production do
@@ -84,6 +82,7 @@ module Vapid
84
82
  render "errors/500", layout: :modal
85
83
  end
86
84
 
85
+ register Sinatra::Cacher
87
86
  register Sinatra::Flash
88
87
  register Sinatra::Namespace
89
88
  register Padrino::Helpers
@@ -1,13 +1,35 @@
1
- # Settings
2
1
  module Vapid
2
+ # Settings
3
3
  class Settings
4
- def self.method_missing(sym, *)
5
- (@settings ||= load_settings)[sym.to_s]
6
- end
4
+ class << self
5
+ def replace_site_id(site_id)
6
+ content = File.read(settings_file)
7
+ new_content = content.gsub(/site_id:(.*)/, "site_id: #{site_id}")
8
+ File.open(settings_file, "w") {|file| file.puts new_content }
9
+ end
10
+
11
+ private
12
+
13
+ def method_missing(sym, *)
14
+ @settings ||= load_settings
15
+ if @settings
16
+ @settings[sym.to_s]
17
+ else
18
+ super
19
+ end
20
+ end
21
+
22
+ def respond_to_missing?(_method_name, _include_private = false)
23
+ super
24
+ end
25
+
26
+ def settings_file
27
+ File.join(Dir.pwd, "config", "settings.yml")
28
+ end
7
29
 
8
- def self.load_settings
9
- settings_file = File.join(Dir.pwd, "config", "settings.yml")
10
- File.exist?(settings_file) ? YAML.load_file(settings_file)[Server.environment.to_s] : {}
30
+ def load_settings
31
+ File.exist?(settings_file) && YAML.load_file(settings_file)[Server.environment.to_s] || {}
32
+ end
11
33
  end
12
34
  end
13
35
  end
@@ -26,8 +26,10 @@ module Vapid
26
26
  branches
27
27
  end
28
28
 
29
+ # rubocop:disable Metrics/AbcSize
29
30
  def render
30
31
  @parser = Parser.new(@html, default_group_content)
32
+
31
33
  @parser.walk set_context: method(:fetch_content) do |node, content|
32
34
  node.clone(content.size - 1) if node.cloneable?
33
35
  record = node.clone? ? content[node.clone_index] : content.first
@@ -38,6 +40,7 @@ module Vapid
38
40
 
39
41
  @parser.to_html
40
42
  end
43
+ # rubocop:enable Metrics/AbcSize
41
44
 
42
45
  private
43
46
 
@@ -64,7 +67,7 @@ module Vapid
64
67
  # TODO: Figure out a better way to do this
65
68
  # Maybe let the directive determine the placeholder?
66
69
  def add_development_styles
67
- (@parser.doc.at("head") || @parser.doc.at("body")).after """
70
+ (@parser.doc.at("head") || @parser.doc.at("body")).after "
68
71
  <style>
69
72
  [vp-placeholder]:before { opacity: 0.5; }
70
73
  [vp-placeholder][vp-text]:before { content: '{ ' attr(vp-text) ' }'; }
@@ -73,7 +76,7 @@ module Vapid
73
76
  [vp-placeholder][vp-audio]:before { content: '{ ' attr(vp-audio) ' }'; }
74
77
  [vp-placeholder][vp-video]:before { content: '{ ' attr(vp-video) ' }'; }
75
78
  </style>
76
- """
79
+ "
77
80
  end
78
81
  end
79
82
  end
@@ -48,9 +48,10 @@ module Vapid
48
48
 
49
49
  # TODO: Abstract this, so that directives only need to pass in
50
50
  # html, text, etc, and don't have to know about Nokogiri methods/concepts
51
+ # rubocop:disable MethodLength
51
52
  def modify(obj)
52
53
  return unless obj
53
-
54
+
54
55
  obj.each do |prop, value|
55
56
  if value.is_a?(String)
56
57
  @node.send "#{prop}=", value
@@ -63,6 +64,7 @@ module Vapid
63
64
  end
64
65
  end
65
66
  end
67
+ # rubocop:enable MethodLength
66
68
 
67
69
  private
68
70
 
@@ -11,6 +11,7 @@ module Vapid
11
11
  @context_stack = [initial_context]
12
12
  end
13
13
 
14
+ # rubocop:disable MethodLength
14
15
  def walk(node = doc_root, set_context: nil, &block)
15
16
  if node.group?
16
17
  context = set_context.present? ? set_context.call(node.group_expr) : node.group_expr
@@ -27,6 +28,7 @@ module Vapid
27
28
 
28
29
  pop_context if node.group?
29
30
  end
31
+ # rubocop:enable MethodLength
30
32
 
31
33
  def to_html
32
34
  @doc.to_html
@@ -1,4 +1,4 @@
1
1
  # Version
2
2
  module Vapid
3
- VERSION = "0.1.2".freeze
3
+ VERSION = "0.1.3".freeze
4
4
  end
@@ -22,8 +22,9 @@ Gem::Specification.new do |spec|
22
22
 
23
23
  spec.add_dependency "thor", "~> 0.20"
24
24
  spec.add_dependency "sinatra", "~> 2.0"
25
- spec.add_dependency "sinatra-contrib", "~> 2.0"
26
25
  spec.add_dependency "sinatra-activerecord", "~> 2.0"
26
+ spec.add_dependency "sinatra-cacher", "~> 1.0"
27
+ spec.add_dependency "sinatra-contrib", "~> 2.0"
27
28
  spec.add_dependency "sinatra-flash", "~> 0.3"
28
29
  spec.add_dependency "padrino-helpers", "~> 0.1"
29
30
  spec.add_dependency "sprockets", "~> 3.7"
@@ -38,6 +39,8 @@ Gem::Specification.new do |spec|
38
39
  spec.add_dependency "rack-livereload", "~> 0.3"
39
40
  spec.add_dependency "guard-livereload", "~> 2.5"
40
41
  spec.add_dependency "ruby-oembed", "~> 0.12"
42
+ spec.add_dependency "netrc", "~> 0.11"
43
+ spec.add_dependency "faraday", "~> 0.13"
41
44
 
42
45
  spec.add_development_dependency "bundler", "~> 1.1"
43
46
  spec.add_development_dependency "rspec", "~> 3.0"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vapid
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Scott Robbin
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-10-06 00:00:00.000000000 Z
11
+ date: 2017-12-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -39,7 +39,7 @@ dependencies:
39
39
  - !ruby/object:Gem::Version
40
40
  version: '2.0'
41
41
  - !ruby/object:Gem::Dependency
42
- name: sinatra-contrib
42
+ name: sinatra-activerecord
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - "~>"
@@ -53,7 +53,21 @@ dependencies:
53
53
  - !ruby/object:Gem::Version
54
54
  version: '2.0'
55
55
  - !ruby/object:Gem::Dependency
56
- name: sinatra-activerecord
56
+ name: sinatra-cacher
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: sinatra-contrib
57
71
  requirement: !ruby/object:Gem::Requirement
58
72
  requirements:
59
73
  - - "~>"
@@ -262,6 +276,34 @@ dependencies:
262
276
  - - "~>"
263
277
  - !ruby/object:Gem::Version
264
278
  version: '0.12'
279
+ - !ruby/object:Gem::Dependency
280
+ name: netrc
281
+ requirement: !ruby/object:Gem::Requirement
282
+ requirements:
283
+ - - "~>"
284
+ - !ruby/object:Gem::Version
285
+ version: '0.11'
286
+ type: :runtime
287
+ prerelease: false
288
+ version_requirements: !ruby/object:Gem::Requirement
289
+ requirements:
290
+ - - "~>"
291
+ - !ruby/object:Gem::Version
292
+ version: '0.11'
293
+ - !ruby/object:Gem::Dependency
294
+ name: faraday
295
+ requirement: !ruby/object:Gem::Requirement
296
+ requirements:
297
+ - - "~>"
298
+ - !ruby/object:Gem::Version
299
+ version: '0.13'
300
+ type: :runtime
301
+ prerelease: false
302
+ version_requirements: !ruby/object:Gem::Requirement
303
+ requirements:
304
+ - - "~>"
305
+ - !ruby/object:Gem::Version
306
+ version: '0.13'
265
307
  - !ruby/object:Gem::Dependency
266
308
  name: bundler
267
309
  requirement: !ruby/object:Gem::Requirement
@@ -353,6 +395,7 @@ files:
353
395
  - bin/setup
354
396
  - exe/vapid
355
397
  - lib/vapid.rb
398
+ - lib/vapid/api.rb
356
399
  - lib/vapid/assets/images/vapid/favicon.ico
357
400
  - lib/vapid/assets/images/vapid/logo.png
358
401
  - lib/vapid/assets/images/vapid/logo_inverse.png
@@ -370,6 +413,7 @@ files:
370
413
  - lib/vapid/db/migrate/20170202182310_create_groups.rb
371
414
  - lib/vapid/db/migrate/20170202183017_create_records.rb
372
415
  - lib/vapid/db/migrate/20170202185150_create_users.rb
416
+ - lib/vapid/deployer.rb
373
417
  - lib/vapid/directive.rb
374
418
  - lib/vapid/directives.rb
375
419
  - lib/vapid/directives/audio.rb