Skip to content

Commit 918e9b5

Browse files
committed
Merge branch 'master' into custom-config-hash
2 parents defd2fa + bc0a697 commit 918e9b5

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

74 files changed

+1323
-372
lines changed

.rubocop.yml

+2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ AllCops:
66
- lib/jekyll-admin/public/**/*
77
- src/**/*
88
- node_modules/**/*
9+
- Gemfile
10+
- jekyll-admin.gemspec
911

1012
Metrics/BlockLength:
1113
Enabled: false

docs/_frontend/actions.md

+6-2
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,15 @@ description: Actions are payloads of information that send data from the applica
77

88
### > `fetchConfig`
99

10-
Async action for fetching Jekyll project configuration (`_config.yml`)
10+
Async action for fetching an object comprised of Jekyll project configuration (from `_config.yml` by default)
1111

1212
### > `putConfig(config)`
1313

14-
Async action for updating Jekyll project configuration
14+
Async action for updating Jekyll project configuration, after ensuring the content is not empty.
15+
16+
### > `validateConfig(config)`
17+
18+
Action for checking whether the YAML editor has content.
1519

1620
### > `onEditorChange`
1721

docs/_frontend/components.md

+21-5
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,21 @@ Generic component for button element.
6868
}
6969
```
7070

71+
## Dropzone
72+
73+
Component for uploading staticfiles.
74+
75+
### PropTypes
76+
77+
```javascript
78+
{
79+
files: Array,
80+
onDrop: Function,
81+
onClickDelete: Function,
82+
onClickItem: Function,
83+
}
84+
```
85+
7186
## FilePreview
7287

7388
Component for previewing the uploaded file. It renders an image or a div according to
@@ -144,16 +159,17 @@ Editable title component for edit views
144159

145160
## Metadata
146161

147-
Set of components for handling documents' front matter(metafields).
162+
Set of components for handling documents' front matters (metafields).
148163

149164
### MetaField
150165

151166
Contains root attributes of the metadata.
152167

153168
### MetaSimple
154169

155-
Leaf component that contains an simple input or date picker depending on the field's
156-
key. If the key is called `date`, it shows date picker for the value.
170+
Leaf component for metadata that contains a simple input, date picker or staticfile
171+
picker depending on the field's key.
172+
Special keys for additional functionalities are `date`, `file` and `image`.
157173

158174
### MetaArray
159175

@@ -165,13 +181,13 @@ Convertible array item. Can be MetaArray, MetaObject or MetaSimple.
165181

166182
### MetaObject
167183

168-
Contains sortable object items. Items are sorted visually, not stored in the state.
184+
Contains object items which allows entering key-value fields.
169185

170186
### MetaObjectItem
171187

172188
Convertible object item. Can be MetaArray, MetaObject or MetaSimple.
173189

174190
### MetaButtons
175191

176-
Contains convert and delete buttons and sort handle. Dynamically shows the possible
192+
Contains `convert` and `delete` buttons and sort handle. Dynamically shows the possible
177193
conversion types.

docs/_frontend/containers.md

+7-2
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ Container for displaying header which includes title and homepage link.
2525
```javascript
2626
{
2727
config: Object,
28-
fetchConfig: Function
28+
fetchConfig: Function,
29+
updated: Boolean \\ optional
2930
}
3031
```
3132

@@ -82,7 +83,11 @@ The button is activated when the editor changes.
8283
putConfig: Function,
8384
error: String,
8485
updated: Boolean,
85-
editorChanged: Boolean
86+
editorChanged: Boolean,
87+
errors: Array,
88+
clearErrors: Function,
89+
router: Object,
90+
route: Object
8691
}
8792
```
8893

docs/api.md

+10-4
Original file line numberDiff line numberDiff line change
@@ -73,12 +73,18 @@ A standard JSON object of a directory looks like this:
7373

7474
#### Data files and the config file
7575

76-
Data files and the config file are direct JSON representations of the underlying YAML File.
76+
Data files are a direct JSON representations of the underlying YAML File.
77+
A JSON object from the config file has the data segregated into two representations:
78+
79+
* `content` - the parsed configuration data as read by Jekyll.
80+
* `raw_content` - the raw data as it sits on the disk.
7781

7882
#### Static files
7983

8084
Static files are non-Jekyll files and may be binary or text.
8185

86+
---
87+
8288
### Collections
8389

8490
#### Parameters
@@ -143,13 +149,13 @@ Delete the requested page from disk.
143149

144150
#### `GET /configuration`
145151

146-
Returns the parsed site configuration.
152+
Returns a hash object comprised of the parsed configuration from the file and the raw unparsed content of the file.
147153

148154
#### `PUT /configuration`
149155

150-
Create or update the site's `_config.yml` file with the requested contents.
156+
Create or update the site's `_config.yml` file with the requested raw file content string.
151157

152-
File will be written to disk in YAML. It will not necessarily preserve whitespace or inline comments.
158+
File will be written to disk verbatim, preserving whitespace and inline comments.
153159

154160
### Static files
155161

docs/architecture.md

+2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ description: Jekyll Admin exists in two parts, a Ruby back end and a Javascript
88

99
Jekyll Admin piggybacks on Jekyll's built-in Webrick server. We monkey patch the `jekyll serve` command to hook in two Sinatra servers, one to serve the static front end that lives in `lib/jekyll-admin/public/dist` via `/admin`, and one to serve the Ruby API via `/_api`. Once the Sinatra servers are mounted, they work just like any other Jekyll server (and we rely on third-party plugins like `sintra-json` and `sinatra-cross_origin`).
1010

11+
**Note:** Since there are two Sinatra servers that might call `site.process` concurrently, Jekyll Admin disables `--watch` flag to prevent a race condition between these servers that might cause incorrect responses for the API. This ensures that the site is regenerated by only the process that Jekyll Admin runs.
12+
1113
## How Jekyll Admin formats Jekyll objects for the API
1214

1315
Whenever possible, we want to stay as close to the `to_liquid.to_json` representation of Jekyll's internal object structure as possible, so that we're (A) using data structure that developers are used to, and (B) so that we can benefit from upstream improvements. To do this, we have the `JekyllAdmin::APIable` module, which gets included in native Jekyll objects like Pages and Documents to add a `to_api` method which we can call to generate hashes for use in the API.

jekyll-admin.gemspec

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ Gem::Specification.new do |spec|
3535
spec.add_development_dependency "bundler", "~> 1.7"
3636
spec.add_development_dependency "rake", "~> 10.0"
3737
spec.add_development_dependency "rspec", "~> 3.4"
38-
spec.add_development_dependency "rubocop", "~> 0.35"
38+
spec.add_development_dependency "rubocop", "~> 0.48.1"
3939
spec.add_development_dependency "sinatra-cross_origin", "~> 0.3"
4040
spec.add_development_dependency "gem-release", "~> 0.7"
4141
end

lib/jekyll-admin.rb

+20-22
Original file line numberDiff line numberDiff line change
@@ -16,29 +16,18 @@
1616
require "sinatra/reloader"
1717
require "sinatra/namespace"
1818

19-
# Jekyll-Admin stuffs
20-
require "jekyll-admin/version"
21-
require "jekyll-admin/server"
22-
require "jekyll-admin/static_server"
23-
require "jekyll-admin/server/collection.rb"
24-
require "jekyll-admin/server/configuration.rb"
25-
require "jekyll-admin/server/data.rb"
26-
require "jekyll-admin/server/page.rb"
27-
require "jekyll-admin/server/static_file.rb"
28-
require "jekyll-admin/apiable.rb"
29-
require "jekyll-admin/urlable.rb"
30-
require "jekyll-admin/data_file.rb"
31-
require "jekyll-admin/directory.rb"
32-
require "jekyll-admin/page_without_a_file.rb"
33-
34-
# Monkey Patches
35-
require_relative "./jekyll/commands/serve"
36-
[Jekyll::Page, Jekyll::Document, Jekyll::StaticFile, Jekyll::Collection].each do |klass|
37-
klass.include JekyllAdmin::APIable
38-
klass.include JekyllAdmin::URLable
39-
end
40-
4119
module JekyllAdmin
20+
autoload :APIable, "jekyll-admin/apiable"
21+
autoload :DataFile, "jekyll-admin/data_file"
22+
autoload :Directory, "jekyll-admin/directory"
23+
autoload :FileHelper, "jekyll-admin/file_helper"
24+
autoload :PageWithoutAFile, "jekyll-admin/page_without_a_file"
25+
autoload :PathHelper, "jekyll-admin/path_helper"
26+
autoload :Server, "jekyll-admin/server"
27+
autoload :StaticServer, "jekyll-admin/static_server"
28+
autoload :URLable, "jekyll-admin/urlable"
29+
autoload :Version, "jekyll-admin/version"
30+
4231
def self.site
4332
@site ||= begin
4433
site = Jekyll.sites.first
@@ -47,3 +36,12 @@ def self.site
4736
end
4837
end
4938
end
39+
40+
# Monkey Patches
41+
require_relative "./jekyll/commands/serve"
42+
require_relative "./jekyll/commands/build"
43+
44+
[Jekyll::Page, Jekyll::Document, Jekyll::StaticFile, Jekyll::Collection].each do |klass|
45+
klass.include JekyllAdmin::APIable
46+
klass.include JekyllAdmin::URLable
47+
end

lib/jekyll-admin/apiable.rb

+1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ def to_api(include_content: false)
4040
# array with each rendered document, which we don't want.
4141
if is_a?(Jekyll::Collection)
4242
output.delete("docs")
43+
output["entries_url"] = entries_url
4344
end
4445

4546
if is_a?(Jekyll::Document)

lib/jekyll-admin/data_file.rb

+11-14
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ class DataFile
55

66
include APIable
77
include URLable
8+
include PathHelper
9+
extend PathHelper
10+
11+
alias_method :path, :relative_path
812

913
# Initialize a new DataFile object
1014
#
@@ -17,17 +21,6 @@ def exists?
1721
@exists ||= File.exist?(absolute_path)
1822
end
1923

20-
def absolute_path
21-
@absolute_path ||= Jekyll.sanitized_path(JekyllAdmin.site.source, relative_path)
22-
end
23-
alias_method :file_path, :absolute_path
24-
25-
# Returns the relative path relative to site source
26-
def relative_path
27-
@relative_path = File.join(DataFile.data_dir, basename_with_extension)
28-
end
29-
alias_method :path, :relative_path
30-
3124
# Returns unparsed content as it exists on disk
3225
def raw_content
3326
@raw_content ||= File.open(absolute_path, "r:UTF-8", &:read)
@@ -65,10 +58,9 @@ def to_liquid
6558
end
6659

6760
def self.all
68-
data_dir = Jekyll.sanitized_path(JekyllAdmin.site.source, DataFile.data_dir)
69-
data_dir = Pathname.new(data_dir)
61+
data_dir = sanitized_path DataFile.data_dir
7062
Dir["#{data_dir}/*.{#{EXTENSIONS.join(",")}}"].map do |path|
71-
new(Pathname.new(path).relative_path_from(data_dir).to_s)
63+
new path_without_site_source(path)
7264
end
7365
end
7466

@@ -90,5 +82,10 @@ def basename
9082
def basename_with_extension
9183
[basename, extension].join
9284
end
85+
alias_method :filename, :basename_with_extension
86+
87+
def namespace
88+
"data"
89+
end
9390
end
9491
end

lib/jekyll-admin/file_helper.rb

+64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
module JekyllAdmin
2+
module FileHelper
3+
4+
# The file the user requested in the URL
5+
def requested_file
6+
find_by_path(path)
7+
end
8+
9+
# The file ultimately written to disk
10+
# This may be the requested file, or in the case of a rename will be read
11+
# from the new path that was actually written to disk
12+
def written_file
13+
find_by_path(write_path)
14+
end
15+
16+
# Write a file to disk with the given content
17+
def write_file(path, content)
18+
Jekyll.logger.debug "WRITING:", path
19+
path = sanitized_path(path)
20+
FileUtils.mkdir_p File.dirname(path)
21+
File.write(path, content)
22+
site.process
23+
end
24+
25+
# Delete the file at the given path
26+
def delete_file(path)
27+
Jekyll.logger.debug "DELETING:", path
28+
FileUtils.rm_f sanitized_path(path)
29+
site.process
30+
end
31+
32+
private
33+
34+
def ensure_requested_file
35+
ensure_file(requested_file)
36+
end
37+
38+
def ensure_written_file
39+
ensure_file(written_file)
40+
end
41+
42+
def find_by_path(path)
43+
files = case namespace
44+
when "collections"
45+
collection.docs
46+
when "data"
47+
DataFile.all
48+
when "pages", "static_files"
49+
site.public_send(namespace.to_sym)
50+
else
51+
[]
52+
end
53+
files.find { |f| sanitized_path(f.path) == path }
54+
end
55+
56+
def ensure_file(file)
57+
render_404 if file.nil?
58+
end
59+
60+
def ensure_directory
61+
render_404 unless Dir.exist?(directory_path)
62+
end
63+
end
64+
end

0 commit comments

Comments
 (0)