jekyll-manager 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.
- checksums.yaml +7 -0
- data/LICENSE +22 -0
- data/README.md +63 -0
- data/lib/jekyll-admin.rb +47 -0
- data/lib/jekyll-admin/apiable.rb +167 -0
- data/lib/jekyll-admin/data_file.rb +103 -0
- data/lib/jekyll-admin/directory.rb +73 -0
- data/lib/jekyll-admin/file_helper.rb +68 -0
- data/lib/jekyll-admin/page_without_a_file.rb +7 -0
- data/lib/jekyll-admin/path_helper.rb +78 -0
- data/lib/jekyll-admin/public/bundle.js +58 -0
- data/lib/jekyll-admin/public/bundle.js.map +1 -0
- data/lib/jekyll-admin/public/favicon.ico +0 -0
- data/lib/jekyll-admin/public/fonts/fontawesome-webfont.eot +0 -0
- data/lib/jekyll-admin/public/fonts/fontawesome-webfont.ttf +0 -0
- data/lib/jekyll-admin/public/fonts/fontawesome-webfont.woff +0 -0
- data/lib/jekyll-admin/public/fonts/fontawesome-webfont.woff2 +0 -0
- data/lib/jekyll-admin/public/fonts/lato-bold.ttf +0 -0
- data/lib/jekyll-admin/public/fonts/lato-regular.ttf +0 -0
- data/lib/jekyll-admin/public/fonts/rw-widgets.eot +0 -0
- data/lib/jekyll-admin/public/fonts/rw-widgets.ttf +0 -0
- data/lib/jekyll-admin/public/fonts/rw-widgets.woff +0 -0
- data/lib/jekyll-admin/public/images/fontawesome-webfont.svg +685 -0
- data/lib/jekyll-admin/public/images/loader-big.gif +0 -0
- data/lib/jekyll-admin/public/images/loading.gif +0 -0
- data/lib/jekyll-admin/public/images/logo-black-red.png +0 -0
- data/lib/jekyll-admin/public/images/logo.png +0 -0
- data/lib/jekyll-admin/public/images/no-image.svg +1 -0
- data/lib/jekyll-admin/public/images/rw-widgets.svg +18 -0
- data/lib/jekyll-admin/public/index.html +13 -0
- data/lib/jekyll-admin/public/styles.css +5 -0
- data/lib/jekyll-admin/public/styles.css.map +1 -0
- data/lib/jekyll-admin/server.rb +119 -0
- data/lib/jekyll-admin/server/collection.rb +88 -0
- data/lib/jekyll-admin/server/configuration.rb +57 -0
- data/lib/jekyll-admin/server/dashboard.rb +113 -0
- data/lib/jekyll-admin/server/data.rb +82 -0
- data/lib/jekyll-admin/server/draft.rb +110 -0
- data/lib/jekyll-admin/server/page.rb +90 -0
- data/lib/jekyll-admin/server/static_file.rb +82 -0
- data/lib/jekyll-admin/server/template.rb +196 -0
- data/lib/jekyll-admin/server/theme.rb +135 -0
- data/lib/jekyll-admin/static_server.rb +24 -0
- data/lib/jekyll-admin/urlable.rb +67 -0
- data/lib/jekyll-admin/version.rb +3 -0
- data/lib/jekyll-manager.rb +5 -0
- data/lib/jekyll/commands/build.rb +14 -0
- data/lib/jekyll/commands/serve.rb +26 -0
- metadata +253 -0
@@ -0,0 +1,110 @@
|
|
1
|
+
module JekyllAdmin
|
2
|
+
class Server < Sinatra::Base
|
3
|
+
namespace "/drafts" do
|
4
|
+
get "/*?/?:path.:ext" do
|
5
|
+
ensure_requested_file
|
6
|
+
json requested_file.to_api(:include_content => true)
|
7
|
+
end
|
8
|
+
|
9
|
+
get "/?*" do
|
10
|
+
ensure_directory
|
11
|
+
json entries.map(&:to_api)
|
12
|
+
end
|
13
|
+
|
14
|
+
put "/*?/?:path.:ext" do
|
15
|
+
ensure_html_content
|
16
|
+
|
17
|
+
if renamed?
|
18
|
+
ensure_requested_file
|
19
|
+
delete_file path
|
20
|
+
end
|
21
|
+
|
22
|
+
write_file write_path, document_body
|
23
|
+
json written_file.to_api(:include_content => true)
|
24
|
+
end
|
25
|
+
|
26
|
+
delete "/*?/?:path.:ext" do
|
27
|
+
ensure_requested_file
|
28
|
+
delete_file path
|
29
|
+
content_type :json
|
30
|
+
status 200
|
31
|
+
halt
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
# return all documents in the 'posts' collection that output to an html
|
37
|
+
# file but reside in a separate directory, `<source_dir>/_drafts/`
|
38
|
+
def drafts
|
39
|
+
posts = site.collections.find { |l, _c| l == "posts" }
|
40
|
+
if posts
|
41
|
+
posts[1].docs.find_all { |d| d.output_ext == ".html" && d.draft? }
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# return drafts at the same level as directory
|
46
|
+
def directory_drafts
|
47
|
+
drafts.find_all { |d| File.dirname(d.path) == directory_path }
|
48
|
+
end
|
49
|
+
|
50
|
+
def reverse_sorted_drafts
|
51
|
+
directory_drafts.sort_by(&:date).reverse
|
52
|
+
end
|
53
|
+
|
54
|
+
# returns directories at the root of `/_drafts/` that contain drafts
|
55
|
+
def relevant_directory_paths
|
56
|
+
drafts.map { |doc| relative_draft_path(doc).split("/")[0] }.uniq
|
57
|
+
end
|
58
|
+
|
59
|
+
def relative_draft_path(document)
|
60
|
+
File.dirname(document.relative_path.sub("_drafts/", ""))
|
61
|
+
end
|
62
|
+
|
63
|
+
def ensure_directory
|
64
|
+
ensure_drafts
|
65
|
+
render_404 unless Dir.exist?(directory_path)
|
66
|
+
end
|
67
|
+
|
68
|
+
def ensure_drafts
|
69
|
+
render_404 if drafts.nil?
|
70
|
+
end
|
71
|
+
|
72
|
+
def ensure_html_content
|
73
|
+
return if html_content?
|
74
|
+
content_type :json
|
75
|
+
halt 422, json("error_message" => "Invalid file extension for drafts")
|
76
|
+
end
|
77
|
+
|
78
|
+
def entries
|
79
|
+
args = {
|
80
|
+
:base => site.source,
|
81
|
+
:content_type => "drafts",
|
82
|
+
:splat => params["splat"].first,
|
83
|
+
}
|
84
|
+
# get the directories inside the requested directory
|
85
|
+
directory = JekyllAdmin::Directory.new(directory_path, args)
|
86
|
+
directories = directory.directories
|
87
|
+
|
88
|
+
# exclude root level directories which do not have drafts
|
89
|
+
if params["splat"].first.empty?
|
90
|
+
directories = directories.select do |d|
|
91
|
+
relevant_directory_paths.include? d.name.to_s
|
92
|
+
end
|
93
|
+
end
|
94
|
+
# merge directories with the drafts at the same level
|
95
|
+
directories.concat(reverse_sorted_drafts)
|
96
|
+
end
|
97
|
+
|
98
|
+
def html_content?
|
99
|
+
draft = JekyllAdmin::PageWithoutAFile.new(
|
100
|
+
site,
|
101
|
+
site.source,
|
102
|
+
"_drafts",
|
103
|
+
request_payload["path"] || filename
|
104
|
+
)
|
105
|
+
draft.data = request_payload["front_matter"]
|
106
|
+
draft.html?
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
module JekyllAdmin
|
2
|
+
class Server < Sinatra::Base
|
3
|
+
namespace "/pages" do
|
4
|
+
get "/*?/?:path.:ext" do
|
5
|
+
ensure_requested_file
|
6
|
+
json requested_file.to_api(:include_content => true)
|
7
|
+
end
|
8
|
+
|
9
|
+
get "/?*" do
|
10
|
+
ensure_directory
|
11
|
+
json entries.map(&:to_api)
|
12
|
+
end
|
13
|
+
|
14
|
+
put "/*?/?:path.:ext" do
|
15
|
+
ensure_html_content
|
16
|
+
|
17
|
+
if renamed?
|
18
|
+
ensure_requested_file
|
19
|
+
delete_file path
|
20
|
+
end
|
21
|
+
|
22
|
+
write_file write_path, page_body
|
23
|
+
|
24
|
+
json written_file.to_api(:include_content => true)
|
25
|
+
end
|
26
|
+
|
27
|
+
delete "/*?/?:path.:ext" do
|
28
|
+
ensure_requested_file
|
29
|
+
delete_file path
|
30
|
+
content_type :json
|
31
|
+
status 200
|
32
|
+
halt
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def ensure_html_content
|
38
|
+
return if html_content?
|
39
|
+
content_type :json
|
40
|
+
halt 422, json("error_message" => "Invalid file extension for pages")
|
41
|
+
end
|
42
|
+
|
43
|
+
def html_content?
|
44
|
+
page = JekyllAdmin::PageWithoutAFile.new(
|
45
|
+
site,
|
46
|
+
site.source,
|
47
|
+
"",
|
48
|
+
request_payload["path"] || filename
|
49
|
+
)
|
50
|
+
page.data = request_payload["front_matter"]
|
51
|
+
page.html?
|
52
|
+
end
|
53
|
+
|
54
|
+
def pages
|
55
|
+
site.pages.select(&:html?)
|
56
|
+
end
|
57
|
+
|
58
|
+
def directory_pages
|
59
|
+
pages.find_all do |p|
|
60
|
+
sanitized_path(File.dirname(p.path)) == directory_path
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# returns relative path of root level directories that contain pages
|
65
|
+
def directory_paths
|
66
|
+
pages.map { |p| File.dirname(p.path).split("/")[0] }.uniq
|
67
|
+
end
|
68
|
+
|
69
|
+
def entries
|
70
|
+
args = {
|
71
|
+
:base => site.source,
|
72
|
+
:content_type => "pages",
|
73
|
+
:splat => params["splat"].first,
|
74
|
+
}
|
75
|
+
# get all directories inside the requested directory
|
76
|
+
directory = JekyllAdmin::Directory.new(directory_path, args)
|
77
|
+
directories = directory.directories
|
78
|
+
|
79
|
+
# exclude root level directories which do not have pages
|
80
|
+
if params["splat"].first.empty?
|
81
|
+
directories = directories.select do |d|
|
82
|
+
directory_paths.include? d.name.to_s
|
83
|
+
end
|
84
|
+
end
|
85
|
+
# merge directories with the pages at the same level
|
86
|
+
directories.concat(directory_pages)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
module JekyllAdmin
|
2
|
+
class Server < Sinatra::Base
|
3
|
+
namespace "/static_files" do
|
4
|
+
get "/index" do
|
5
|
+
json site.static_files.map(&:to_api)
|
6
|
+
end
|
7
|
+
|
8
|
+
get "/?*" do
|
9
|
+
render_404 unless File.exist?(path)
|
10
|
+
if requested_file
|
11
|
+
json requested_file.to_api(:include_content => true)
|
12
|
+
else
|
13
|
+
json entries.map(&:to_api)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
put "/*" do
|
18
|
+
if renamed?
|
19
|
+
ensure_requested_file
|
20
|
+
delete_file path
|
21
|
+
end
|
22
|
+
|
23
|
+
write_file(write_path, static_file_body)
|
24
|
+
json written_file.to_api(:include_content => true)
|
25
|
+
end
|
26
|
+
|
27
|
+
delete "/*" do
|
28
|
+
ensure_requested_file
|
29
|
+
delete_file path
|
30
|
+
content_type :json
|
31
|
+
status 200
|
32
|
+
halt
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
# returns relative path of root level directories that contain static files
|
38
|
+
def directory_names
|
39
|
+
static_files.map do |f|
|
40
|
+
File.dirname(f.path.sub("#{site.source}/", "")).split("/")[0]
|
41
|
+
end.uniq
|
42
|
+
end
|
43
|
+
|
44
|
+
def directory_files
|
45
|
+
static_files.find_all do |p|
|
46
|
+
sanitized_path(File.dirname(p.path)) == directory_path
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def entries
|
51
|
+
args = {
|
52
|
+
:base => site.source,
|
53
|
+
:content_type => "static_files",
|
54
|
+
:splat => params["splat"].first,
|
55
|
+
}
|
56
|
+
# get all directories inside the requested directory
|
57
|
+
directory = JekyllAdmin::Directory.new(directory_path, args)
|
58
|
+
directories = directory.directories
|
59
|
+
|
60
|
+
# exclude root level directories which do not have static files
|
61
|
+
if params["splat"].first.empty?
|
62
|
+
directories = directories.select do |d|
|
63
|
+
directory_names.include? d.name.to_s
|
64
|
+
end
|
65
|
+
end
|
66
|
+
directories.concat(directory_files)
|
67
|
+
end
|
68
|
+
|
69
|
+
def static_file_body
|
70
|
+
if !request_payload["raw_content"].to_s.empty?
|
71
|
+
request_payload["raw_content"].to_s
|
72
|
+
else
|
73
|
+
Base64.decode64 request_payload["encoded_content"].to_s
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def static_files
|
78
|
+
site.static_files.select { |f| f.path.start_with? site.source }
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,196 @@
|
|
1
|
+
module JekyllAdmin
|
2
|
+
class Server < Sinatra::Base
|
3
|
+
namespace "/templates" do
|
4
|
+
get "/?" do
|
5
|
+
json template_directories.map(&:to_api)
|
6
|
+
end
|
7
|
+
|
8
|
+
get "/*?/?:path.:ext" do
|
9
|
+
ensure_requested_file
|
10
|
+
api_hash = {
|
11
|
+
:name => filename,
|
12
|
+
:path => written_path,
|
13
|
+
:http_url => http_url,
|
14
|
+
:api_url => url,
|
15
|
+
:has_front_matter => front_matter?(written_path),
|
16
|
+
:front_matter => front_matter,
|
17
|
+
:raw_content => raw_content,
|
18
|
+
}
|
19
|
+
api_hash.merge!(front_matter) if front_matter
|
20
|
+
json api_hash
|
21
|
+
end
|
22
|
+
|
23
|
+
get "/?*" do
|
24
|
+
ensure_directory
|
25
|
+
json dirs.reject { |dir| page_entries_in(dir).empty? }
|
26
|
+
.map(&:to_api)
|
27
|
+
.concat(subdir_entries)
|
28
|
+
end
|
29
|
+
|
30
|
+
put "/*?/?:path.:ext" do
|
31
|
+
if renamed?
|
32
|
+
ensure_requested_file
|
33
|
+
delete_file path
|
34
|
+
end
|
35
|
+
|
36
|
+
write_file write_path, template_body
|
37
|
+
json({
|
38
|
+
:name => filename,
|
39
|
+
:path => written_path,
|
40
|
+
:raw_content => request_payload["raw_content"],
|
41
|
+
:http_url => http_url,
|
42
|
+
:api_url => url,
|
43
|
+
:has_front_matter => write_front_matter?,
|
44
|
+
}.merge!(payload_front_matter))
|
45
|
+
end
|
46
|
+
|
47
|
+
delete "/*?/?:path.:ext" do
|
48
|
+
ensure_requested_file
|
49
|
+
delete_file path
|
50
|
+
content_type :json
|
51
|
+
status 200
|
52
|
+
halt
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def source_dir(dir = "")
|
58
|
+
site.in_source_dir(dir)
|
59
|
+
end
|
60
|
+
|
61
|
+
def requested_file
|
62
|
+
@requested_file = path
|
63
|
+
end
|
64
|
+
|
65
|
+
def dirs
|
66
|
+
args = {
|
67
|
+
:base => site.source,
|
68
|
+
:content_type => "templates",
|
69
|
+
:splat => splats.first,
|
70
|
+
}
|
71
|
+
Directory.new(directory_path, args).directories
|
72
|
+
end
|
73
|
+
|
74
|
+
def template_directories
|
75
|
+
regex = %r!(assets|_(includes|layouts|sass))!
|
76
|
+
dirs.find_all do |f|
|
77
|
+
f.name.to_s =~ regex
|
78
|
+
end.sort_by!(&:name)
|
79
|
+
end
|
80
|
+
|
81
|
+
def subdir_entries
|
82
|
+
Dir["#{directory_path}/*"]
|
83
|
+
.reject { |e| File.directory?(e) }
|
84
|
+
.reject { |f| site.static_files.map(&:path).include?(f) }
|
85
|
+
.map! do |e|
|
86
|
+
{
|
87
|
+
:name => File.basename(e),
|
88
|
+
:path => sanitized_relative_path(e).sub("/#{splats.first}/", ""),
|
89
|
+
:http_url => http_url(e),
|
90
|
+
:api_url => api_url(e),
|
91
|
+
}
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def front_matter?(file)
|
96
|
+
file_path = sanitized_path(file)
|
97
|
+
if file_contents(file_path) =~ Jekyll::Document::YAML_FRONT_MATTER_REGEXP
|
98
|
+
true
|
99
|
+
else
|
100
|
+
false
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def write_front_matter?
|
105
|
+
return false unless request_payload["front_matter"]
|
106
|
+
true
|
107
|
+
end
|
108
|
+
|
109
|
+
def front_matter
|
110
|
+
@front_matter ||= if file_contents =~ Jekyll::Document::YAML_FRONT_MATTER_REGEXP
|
111
|
+
SafeYAML.load(Regexp.last_match(1))
|
112
|
+
else
|
113
|
+
{}
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def raw_content
|
118
|
+
@raw_content ||= if file_contents =~ Jekyll::Document::YAML_FRONT_MATTER_REGEXP
|
119
|
+
$POSTMATCH
|
120
|
+
else
|
121
|
+
file_contents
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def payload_front_matter
|
126
|
+
request_payload["front_matter"] || {}
|
127
|
+
end
|
128
|
+
|
129
|
+
def written_path
|
130
|
+
renamed? ? request_payload["path"] : relative_write_path.sub("/", "")
|
131
|
+
end
|
132
|
+
|
133
|
+
def page_body
|
134
|
+
body = if payload_front_matter && !payload_front_matter.empty?
|
135
|
+
YAML.dump(payload_front_matter).strip
|
136
|
+
else
|
137
|
+
"---"
|
138
|
+
end
|
139
|
+
body << "\n---\n\n"
|
140
|
+
body << request_payload["raw_content"].to_s
|
141
|
+
body << "\n"
|
142
|
+
end
|
143
|
+
|
144
|
+
def template_body
|
145
|
+
if request_payload["front_matter"]
|
146
|
+
page_body
|
147
|
+
else
|
148
|
+
body = request_payload["raw_content"].to_s
|
149
|
+
body << "\n"
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def directory_path
|
154
|
+
source_dir(splats.first)
|
155
|
+
end
|
156
|
+
|
157
|
+
def splats
|
158
|
+
params["splat"] || ["/"]
|
159
|
+
end
|
160
|
+
|
161
|
+
def api_url(entry)
|
162
|
+
File.join(base_url, "_api", "templates", sanitized_relative_path(entry))
|
163
|
+
end
|
164
|
+
|
165
|
+
def http_url(entry = requested_file)
|
166
|
+
if splats.first.include?("assets") && !Jekyll::Utils.has_yaml_header?(entry)
|
167
|
+
File.join(base_url, sanitized_relative_path(entry))
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
def ensure_requested_file
|
172
|
+
render_404 unless File.exist?(requested_file)
|
173
|
+
end
|
174
|
+
|
175
|
+
def file_contents(file = requested_file)
|
176
|
+
@file_contents ||= File.read(
|
177
|
+
file, Jekyll::Utils.merged_file_read_opts(site, {})
|
178
|
+
)
|
179
|
+
end
|
180
|
+
|
181
|
+
def page_entries_in(dir)
|
182
|
+
dir.path.children.select do |entry|
|
183
|
+
front_matter?(entry) || in_sass_dir?(entry)
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
# Jekyll does not consider files without front matter, within `_sass`
|
188
|
+
# to be 'static files' as of Jekyll 3.5.x, ergo they should be
|
189
|
+
# editable via the admin interface.
|
190
|
+
def in_sass_dir?(entry)
|
191
|
+
parent_dir = File.dirname(File.dirname(entry)).sub(source_dir, "")
|
192
|
+
parent_dir == "_sass"
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|