vapid 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
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