jekyll-admin-jekyll34 0.4.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 +7 -0
- data/LICENSE +21 -0
- data/README.md +37 -0
- data/lib/jekyll-admin.rb +47 -0
- data/lib/jekyll-admin/apiable.rb +153 -0
- data/lib/jekyll-admin/data_file.rb +91 -0
- data/lib/jekyll-admin/directory.rb +68 -0
- data/lib/jekyll-admin/file_helper.rb +64 -0
- data/lib/jekyll-admin/page_without_a_file.rb +7 -0
- data/lib/jekyll-admin/path_helper.rb +74 -0
- data/lib/jekyll-admin/server.rb +91 -0
- data/lib/jekyll-admin/server/collection.rb +82 -0
- data/lib/jekyll-admin/server/configuration.rb +42 -0
- data/lib/jekyll-admin/server/data.rb +45 -0
- data/lib/jekyll-admin/server/page.rb +90 -0
- data/lib/jekyll-admin/server/static_file.rb +61 -0
- data/lib/jekyll-admin/static_server.rb +24 -0
- data/lib/jekyll-admin/urlable.rb +65 -0
- data/lib/jekyll-admin/version.rb +3 -0
- data/lib/jekyll/commands/build.rb +14 -0
- data/lib/jekyll/commands/serve.rb +24 -0
- metadata +207 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: d8124bc411abc6a87061492925eeed477af37be3
|
4
|
+
data.tar.gz: 96b42b2a0e3dbea0fa13d0a3c1992cf5a5f806bc
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 0f90c23700c917732f7c331881c36c96bfcc19b3041b2d3db5d16c61f4de4fcc32695d16e5f86abee191f093d6da2f480371edee4af6fa189fcc0c0b23609261
|
7
|
+
data.tar.gz: 1ac6b6c139cfb3a75d904735ea44ef7787d57777fff95951ac5193631647d01a04731afe3b737f8d5d620398332da07866421284ea0f85d7ea5487d8920a657b
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright 2017 Mert Kahyaoğlu and the Jekyll Admin contributors
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
[](https://rubygems.org/gems/jekyll-admin)
|
2
|
+
[](https://travis-ci.org/jekyll/jekyll-admin)
|
3
|
+
[](https://ci.appveyor.com/project/benbalter/jekyll-admin/branch/master)
|
4
|
+
[](https://david-dm.org/jekyll/jekyll-admin)
|
5
|
+
|
6
|
+
A Jekyll plugin that provides users with a traditional CMS-style graphical interface to author content and administer Jekyll sites. The project is divided into two parts. A Ruby-based HTTP API that handles Jekyll and filesystem operations, and a Javascript-based front end, built on that API.
|
7
|
+
|
8
|
+

|
9
|
+
|
10
|
+
## Installation
|
11
|
+
|
12
|
+
Refer to the [installing plugins](https://jekyllrb.com/docs/plugins/#installing-a-plugin) section of Jekyll's documentation and install the `jekyll-admin` plugin as you would any other plugin. Here's the short version:
|
13
|
+
|
14
|
+
1. Add the following to your site's Gemfile:
|
15
|
+
|
16
|
+
```ruby
|
17
|
+
gem 'jekyll-admin', group: :jekyll_plugins
|
18
|
+
```
|
19
|
+
|
20
|
+
2. Run `bundle install`
|
21
|
+
|
22
|
+
## Usage
|
23
|
+
|
24
|
+
1. Start Jekyll as you would normally (`bundle exec jekyll serve`)
|
25
|
+
2. Navigate to `http://localhost:4000/admin` to access the administrative interface
|
26
|
+
|
27
|
+
## Contributing
|
28
|
+
|
29
|
+
Interested in contributing to Jekyll Admin? We’d love your help. Jekyll Admin is an open source project, built one contribution at a time by users like you. See [the contributing instructions](.github/CONTRIBUTING.md), and [the development docs](http://jekyll.github.io/jekyll-admin/development/) for more information.
|
30
|
+
|
31
|
+
## Looking for a hosted version?
|
32
|
+
|
33
|
+
Jekyll Admin is intended to be run on your computer alongside your local Jekyll installation. If you're looking for a hosted version, we'd recommend checking out [Siteleaf](https://www.siteleaf.com/) a hosted Jekyll editor with deep GitHub integration (whom we'd also like to thank for inspiring parts of Jekyll Admin itself!).
|
34
|
+
|
35
|
+
## License
|
36
|
+
|
37
|
+
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
data/lib/jekyll-admin.rb
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
# Default Sinatra to "production" mode (surpress errors) unless
|
2
|
+
# otherwise specified by the `RACK_ENV` environmental variable.
|
3
|
+
# Must be done prior to requiring Sinatra, or we'll get a LoadError
|
4
|
+
# as it looks for sinatra/cross-origin, which is development only
|
5
|
+
ENV["RACK_ENV"] = "production" if ENV["RACK_ENV"].to_s.empty?
|
6
|
+
|
7
|
+
require "json"
|
8
|
+
require "jekyll"
|
9
|
+
require "base64"
|
10
|
+
require "webrick"
|
11
|
+
require "sinatra"
|
12
|
+
require "fileutils"
|
13
|
+
require "sinatra/base"
|
14
|
+
require "sinatra/json"
|
15
|
+
require "addressable/uri"
|
16
|
+
require "sinatra/reloader"
|
17
|
+
require "sinatra/namespace"
|
18
|
+
|
19
|
+
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
|
+
|
31
|
+
def self.site
|
32
|
+
@site ||= begin
|
33
|
+
site = Jekyll.sites.first
|
34
|
+
site.future = true
|
35
|
+
site
|
36
|
+
end
|
37
|
+
end
|
38
|
+
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
|
@@ -0,0 +1,153 @@
|
|
1
|
+
module JekyllAdmin
|
2
|
+
# Abstract module to be included in Convertible and Document to provide
|
3
|
+
# additional, API-specific functionality without duplicating logic
|
4
|
+
module APIable
|
5
|
+
|
6
|
+
CONTENT_FIELDS = %w(next previous content excerpt).freeze
|
7
|
+
|
8
|
+
# Returns a hash suitable for use as an API response.
|
9
|
+
#
|
10
|
+
# For Documents and Pages:
|
11
|
+
#
|
12
|
+
# 1. Adds the file's raw content to the `raw_content` field
|
13
|
+
# 2. Adds the file's raw YAML front matter to the `front_matter` field
|
14
|
+
#
|
15
|
+
# For Static Files it addes the Base64 `encoded_content` field
|
16
|
+
#
|
17
|
+
# Options:
|
18
|
+
#
|
19
|
+
# include_content - if true, includes the content in the respond, false by default
|
20
|
+
# to support mapping on indexes where we only want metadata
|
21
|
+
#
|
22
|
+
#
|
23
|
+
# Returns a hash (which can then be to_json'd)
|
24
|
+
def to_api(include_content: false)
|
25
|
+
output = hash_for_api
|
26
|
+
output = output.merge(url_fields)
|
27
|
+
|
28
|
+
# Include content, if requested, otherwise remove it
|
29
|
+
if include_content
|
30
|
+
output = output.merge(content_fields)
|
31
|
+
else
|
32
|
+
CONTENT_FIELDS.each { |field| output.delete(field) }
|
33
|
+
end
|
34
|
+
|
35
|
+
# Documents have duplicate output and content fields, Pages do not
|
36
|
+
# Since it's an API, use `content` in both for consistency
|
37
|
+
output.delete("output")
|
38
|
+
|
39
|
+
# By default, calling to_liquid on a collection will return a docs
|
40
|
+
# array with each rendered document, which we don't want.
|
41
|
+
if is_a?(Jekyll::Collection)
|
42
|
+
output.delete("docs")
|
43
|
+
output["entries_url"] = entries_url
|
44
|
+
end
|
45
|
+
|
46
|
+
if is_a?(Jekyll::Document)
|
47
|
+
output["name"] = basename
|
48
|
+
end
|
49
|
+
|
50
|
+
output
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
# Pages don't have a hash method, but Documents do
|
56
|
+
def file_path
|
57
|
+
if is_a?(Jekyll::Document)
|
58
|
+
path
|
59
|
+
else
|
60
|
+
File.join(@base, @dir, name)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# StaticFiles don't have `attr_accesor` set for @site or @name
|
65
|
+
def site
|
66
|
+
@site
|
67
|
+
end
|
68
|
+
|
69
|
+
def name
|
70
|
+
@name
|
71
|
+
end
|
72
|
+
|
73
|
+
def file_contents
|
74
|
+
@file_contents ||= File.read(file_path, file_read_options) if file_exists?
|
75
|
+
end
|
76
|
+
|
77
|
+
def file_read_options
|
78
|
+
Jekyll::Utils.merged_file_read_opts(site, {})
|
79
|
+
end
|
80
|
+
|
81
|
+
def front_matter
|
82
|
+
return unless file_exists?
|
83
|
+
@front_matter ||= if file_contents =~ Jekyll::Document::YAML_FRONT_MATTER_REGEXP
|
84
|
+
SafeYAML.load(Regexp.last_match(1))
|
85
|
+
else
|
86
|
+
{}
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def raw_content
|
91
|
+
return unless file_exists?
|
92
|
+
@raw_content ||= if file_contents =~ Jekyll::Document::YAML_FRONT_MATTER_REGEXP
|
93
|
+
$POSTMATCH
|
94
|
+
else
|
95
|
+
file_contents
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def encoded_content
|
100
|
+
@encoded_content ||= Base64.encode64(file_contents) if file_exists?
|
101
|
+
end
|
102
|
+
|
103
|
+
def file_exists?
|
104
|
+
return @file_exists if defined? @file_exists
|
105
|
+
@file_exists = File.exist?(file_path)
|
106
|
+
end
|
107
|
+
|
108
|
+
# Base hash from which to generate the API output
|
109
|
+
def hash_for_api
|
110
|
+
output = to_liquid
|
111
|
+
if output.respond_to?(:hash_for_json)
|
112
|
+
output.hash_for_json
|
113
|
+
else
|
114
|
+
output.to_h
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
# Returns a hash of content fields for inclusion in the API output
|
119
|
+
def content_fields
|
120
|
+
output = {}
|
121
|
+
|
122
|
+
# Include file content-related fields
|
123
|
+
if is_a?(Jekyll::StaticFile)
|
124
|
+
output["encoded_content"] = encoded_content
|
125
|
+
elsif is_a?(JekyllAdmin::DataFile)
|
126
|
+
output["content"] = content
|
127
|
+
output["raw_content"] = raw_content
|
128
|
+
else
|
129
|
+
output["raw_content"] = raw_content
|
130
|
+
output["front_matter"] = front_matter
|
131
|
+
end
|
132
|
+
|
133
|
+
# Include next and previous documents non-recursively
|
134
|
+
if is_a?(Jekyll::Document)
|
135
|
+
%w(next previous).each do |direction|
|
136
|
+
method = "#{direction}_doc".to_sym
|
137
|
+
doc = public_send(method)
|
138
|
+
output[direction] = doc.to_api if doc
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
output
|
143
|
+
end
|
144
|
+
|
145
|
+
def url_fields
|
146
|
+
return {} unless respond_to?(:http_url) && respond_to?(:api_url)
|
147
|
+
{
|
148
|
+
"http_url" => http_url,
|
149
|
+
"api_url" => api_url,
|
150
|
+
}
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
module JekyllAdmin
|
2
|
+
class DataFile
|
3
|
+
METHODS_FOR_LIQUID = %w(path relative_path slug ext title).freeze
|
4
|
+
EXTENSIONS = %w(yaml yml json csv).freeze
|
5
|
+
|
6
|
+
include APIable
|
7
|
+
include URLable
|
8
|
+
include PathHelper
|
9
|
+
extend PathHelper
|
10
|
+
|
11
|
+
alias_method :path, :relative_path
|
12
|
+
|
13
|
+
# Initialize a new DataFile object
|
14
|
+
#
|
15
|
+
# id - the file ID as passed from the API. This may or may not have an extension
|
16
|
+
def initialize(id)
|
17
|
+
@id ||= id
|
18
|
+
end
|
19
|
+
|
20
|
+
def exists?
|
21
|
+
@exists ||= File.exist?(absolute_path)
|
22
|
+
end
|
23
|
+
|
24
|
+
# Returns unparsed content as it exists on disk
|
25
|
+
def raw_content
|
26
|
+
@raw_content ||= File.open(absolute_path, "r:UTF-8", &:read)
|
27
|
+
end
|
28
|
+
|
29
|
+
# Returnes (re)parsed content using Jekyll's native parsing mechanism
|
30
|
+
def content
|
31
|
+
@content ||= data_reader.read_data_file(absolute_path)
|
32
|
+
end
|
33
|
+
|
34
|
+
# Returns the file's extension with preceeding `.`
|
35
|
+
def ext
|
36
|
+
@ext ||= if File.extname(@id).to_s.empty?
|
37
|
+
".yml"
|
38
|
+
else
|
39
|
+
File.extname(@id)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
alias_method :extension, :ext
|
43
|
+
|
44
|
+
# Returns the file's sanitized slug (as used in `site.data[slug]`)
|
45
|
+
def slug
|
46
|
+
@slug ||= data_reader.sanitize_filename(basename)
|
47
|
+
end
|
48
|
+
|
49
|
+
# Returns the human-readable title of the data file
|
50
|
+
def title
|
51
|
+
@title ||= Jekyll::Utils.titleize_slug(slug.tr("_", "-"))
|
52
|
+
end
|
53
|
+
|
54
|
+
# Mimics Jekyll's native to_liquid functionality by returning a hash
|
55
|
+
# of data file metadata
|
56
|
+
def to_liquid
|
57
|
+
@to_liquid ||= METHODS_FOR_LIQUID.map { |key| [key, public_send(key)] }.to_h
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.all
|
61
|
+
data_dir = sanitized_path DataFile.data_dir
|
62
|
+
Dir["#{data_dir}/*.{#{EXTENSIONS.join(",")}}"].map do |path|
|
63
|
+
new path_without_site_source(path)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# Relative path to data directory within site source
|
68
|
+
def self.data_dir
|
69
|
+
JekyllAdmin.site.config["data_dir"]
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
def data_reader
|
75
|
+
@data_reader = Jekyll::DataReader.new(JekyllAdmin.site)
|
76
|
+
end
|
77
|
+
|
78
|
+
def basename
|
79
|
+
@basename ||= File.basename(@id, ".*")
|
80
|
+
end
|
81
|
+
|
82
|
+
def basename_with_extension
|
83
|
+
[basename, extension].join
|
84
|
+
end
|
85
|
+
alias_method :filename, :basename_with_extension
|
86
|
+
|
87
|
+
def namespace
|
88
|
+
"data"
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
module JekyllAdmin
|
2
|
+
class Directory
|
3
|
+
extend Forwardable
|
4
|
+
def_delegator :@path, :basename, :name
|
5
|
+
def_delegator :@path, :mtime, :modified_time
|
6
|
+
attr_reader :path, :splat, :content_type, :base
|
7
|
+
|
8
|
+
include Enumerable
|
9
|
+
include JekyllAdmin::URLable
|
10
|
+
include JekyllAdmin::APIable
|
11
|
+
|
12
|
+
TYPE = :directory
|
13
|
+
|
14
|
+
# Arguments:
|
15
|
+
#
|
16
|
+
# path - full path of the directory which its entries will be listed
|
17
|
+
#
|
18
|
+
# base - passes site.source to generate `relative_path` needed for `to_api`
|
19
|
+
#
|
20
|
+
# content_type - type of the requested directory entries, this is used to generate
|
21
|
+
# API endpoint of the directory along with `splat`
|
22
|
+
#
|
23
|
+
# splat - the requested directory path relative to content namespace
|
24
|
+
def initialize(path, base: nil, content_type: nil, splat: nil)
|
25
|
+
@base = Pathname.new base
|
26
|
+
@content_type = content_type
|
27
|
+
@splat = Pathname.new splat
|
28
|
+
@path = Pathname.new path
|
29
|
+
end
|
30
|
+
|
31
|
+
def to_liquid
|
32
|
+
{
|
33
|
+
:name => name,
|
34
|
+
:modified_time => modified_time,
|
35
|
+
:path => relative_path,
|
36
|
+
:type => TYPE,
|
37
|
+
}
|
38
|
+
end
|
39
|
+
|
40
|
+
def relative_path
|
41
|
+
path.relative_path_from(base).to_s
|
42
|
+
end
|
43
|
+
|
44
|
+
def resource_path
|
45
|
+
if content_type == "pages"
|
46
|
+
"/pages/#{splat}/#{name}"
|
47
|
+
else
|
48
|
+
"/collections/#{content_type}/entries/#{splat}/#{name}"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
alias_method :url, :resource_path
|
52
|
+
|
53
|
+
def http_url
|
54
|
+
nil
|
55
|
+
end
|
56
|
+
|
57
|
+
def directories
|
58
|
+
path.entries.map do |entry|
|
59
|
+
next if [".", ".."].include? entry.to_s
|
60
|
+
next unless path.join(entry).directory?
|
61
|
+
self.class.new(
|
62
|
+
path.join(entry),
|
63
|
+
:base => base, :content_type => content_type, :splat => splat
|
64
|
+
)
|
65
|
+
end.compact!
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -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,0 +1,74 @@
|
|
1
|
+
module JekyllAdmin
|
2
|
+
module PathHelper
|
3
|
+
def sanitized_path(path)
|
4
|
+
path = path_without_site_source(path)
|
5
|
+
Jekyll.sanitized_path JekyllAdmin.site.source, path
|
6
|
+
end
|
7
|
+
|
8
|
+
# Returns the basename + extension for the requested file
|
9
|
+
def filename
|
10
|
+
params["ext"] ||= "yml" if namespace == "data"
|
11
|
+
"#{params["path"]}.#{params["ext"]}"
|
12
|
+
end
|
13
|
+
|
14
|
+
# Returns the sanitized path relative to the site source
|
15
|
+
def sanitized_relative_path(path)
|
16
|
+
path_without_site_source sanitized_path(path)
|
17
|
+
end
|
18
|
+
|
19
|
+
# Returns the sanitized absolute path to the requested object
|
20
|
+
def absolute_path
|
21
|
+
sanitized_path File.join(directory_path, filename)
|
22
|
+
end
|
23
|
+
alias_method :path, :absolute_path
|
24
|
+
|
25
|
+
# Returns the sanitized relative path to the requested object
|
26
|
+
def relative_path
|
27
|
+
sanitized_relative_path absolute_path
|
28
|
+
end
|
29
|
+
|
30
|
+
# Returns the sanitized absolute path to write the requested object
|
31
|
+
def write_path
|
32
|
+
if renamed?
|
33
|
+
sanitized_path request_payload["path"]
|
34
|
+
else
|
35
|
+
path
|
36
|
+
end
|
37
|
+
end
|
38
|
+
alias_method :request_path, :write_path
|
39
|
+
|
40
|
+
# Returns the sanitized relative path to write the requested object
|
41
|
+
def relative_write_path
|
42
|
+
sanitized_relative_path write_path
|
43
|
+
end
|
44
|
+
|
45
|
+
# Is this request renaming a file?
|
46
|
+
def renamed?
|
47
|
+
return false unless request_payload["path"]
|
48
|
+
ensure_leading_slash(request_payload["path"]) != relative_path
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
# Returns the path to the requested file's containing directory
|
54
|
+
def directory_path
|
55
|
+
case namespace
|
56
|
+
when "collections"
|
57
|
+
sanitized_path File.join(collection.relative_directory, params["splat"].first)
|
58
|
+
when "data"
|
59
|
+
sanitized_path File.join(DataFile.data_dir)
|
60
|
+
else
|
61
|
+
sanitized_path params["splat"].first
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def ensure_leading_slash(input)
|
66
|
+
return input if input.nil? || input.empty? || input.start_with?("/")
|
67
|
+
"/#{input}"
|
68
|
+
end
|
69
|
+
|
70
|
+
def path_without_site_source(path)
|
71
|
+
path.to_s.gsub(%r!\A#{Regexp.escape(JekyllAdmin.site.source)}!, "")
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
module JekyllAdmin
|
2
|
+
class Server < Sinatra::Base
|
3
|
+
ROUTES = %w(collections configuration data pages static_files).freeze
|
4
|
+
include JekyllAdmin::PathHelper
|
5
|
+
include JekyllAdmin::FileHelper
|
6
|
+
|
7
|
+
register Sinatra::Namespace
|
8
|
+
|
9
|
+
configure :development do
|
10
|
+
register Sinatra::Reloader
|
11
|
+
enable :logging
|
12
|
+
end
|
13
|
+
|
14
|
+
configure :development, :test do
|
15
|
+
require "sinatra/cross_origin"
|
16
|
+
register Sinatra::CrossOrigin
|
17
|
+
enable :cross_origin
|
18
|
+
disable :allow_credentials
|
19
|
+
set :allow_methods, %i(delete get options post put)
|
20
|
+
end
|
21
|
+
|
22
|
+
get "/" do
|
23
|
+
json ROUTES.map { |r| ["#{r}_api", URI.join(base_url, "/_api/", r)] }.to_h
|
24
|
+
end
|
25
|
+
|
26
|
+
# CORS preflight
|
27
|
+
options "*" do
|
28
|
+
render_404 unless settings.development? || settings.test?
|
29
|
+
status 204
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def site
|
35
|
+
JekyllAdmin.site
|
36
|
+
end
|
37
|
+
|
38
|
+
def render_404
|
39
|
+
status 404
|
40
|
+
content_type :json
|
41
|
+
halt
|
42
|
+
end
|
43
|
+
|
44
|
+
def request_payload
|
45
|
+
@request_payload ||= if request_body.to_s.empty?
|
46
|
+
{}
|
47
|
+
else
|
48
|
+
JSON.parse(request_body)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def base_url
|
53
|
+
"#{request.scheme}://#{request.host_with_port}"
|
54
|
+
end
|
55
|
+
|
56
|
+
def front_matter
|
57
|
+
request_payload["front_matter"]
|
58
|
+
end
|
59
|
+
|
60
|
+
def document_body
|
61
|
+
body = if front_matter && !front_matter.empty?
|
62
|
+
YAML.dump(front_matter).strip
|
63
|
+
else
|
64
|
+
"---"
|
65
|
+
end
|
66
|
+
body << "\n---\n\n"
|
67
|
+
body << request_payload["raw_content"].to_s
|
68
|
+
end
|
69
|
+
alias page_body document_body
|
70
|
+
|
71
|
+
private
|
72
|
+
|
73
|
+
def request_body
|
74
|
+
@request_body ||= begin
|
75
|
+
request.body.rewind
|
76
|
+
request.body.read
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def namespace
|
81
|
+
namespace = request.path_info.split("/")[1].to_s.downcase
|
82
|
+
namespace if ROUTES.include?(namespace)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
require "jekyll-admin/server/collection"
|
88
|
+
require "jekyll-admin/server/configuration"
|
89
|
+
require "jekyll-admin/server/data"
|
90
|
+
require "jekyll-admin/server/page"
|
91
|
+
require "jekyll-admin/server/static_file"
|
@@ -0,0 +1,82 @@
|
|
1
|
+
module JekyllAdmin
|
2
|
+
class Server < Sinatra::Base
|
3
|
+
namespace "/collections" do
|
4
|
+
get do
|
5
|
+
json(site.collections.map { |c| c[1].to_api })
|
6
|
+
end
|
7
|
+
|
8
|
+
get "/:collection_id" do
|
9
|
+
ensure_collection
|
10
|
+
json collection.to_api
|
11
|
+
end
|
12
|
+
|
13
|
+
get "/:collection_id/*?/?:path.:ext" do
|
14
|
+
ensure_requested_file
|
15
|
+
json requested_file.to_api(:include_content => true)
|
16
|
+
end
|
17
|
+
|
18
|
+
get "/:collection_id/entries/?*" do
|
19
|
+
ensure_directory
|
20
|
+
json entries.map(&:to_api)
|
21
|
+
end
|
22
|
+
|
23
|
+
put "/:collection_id/*?/?:path.:ext" do
|
24
|
+
ensure_collection
|
25
|
+
|
26
|
+
if renamed?
|
27
|
+
ensure_requested_file
|
28
|
+
delete_file path
|
29
|
+
end
|
30
|
+
|
31
|
+
write_file write_path, document_body
|
32
|
+
json written_file.to_api(:include_content => true)
|
33
|
+
end
|
34
|
+
|
35
|
+
delete "/:collection_id/*?/?:path.:ext" do
|
36
|
+
ensure_requested_file
|
37
|
+
delete_file path
|
38
|
+
content_type :json
|
39
|
+
status 200
|
40
|
+
halt
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def collection
|
46
|
+
collection = site.collections.find { |l, _c| l == params["collection_id"] }
|
47
|
+
collection[1] if collection
|
48
|
+
end
|
49
|
+
|
50
|
+
def document_id
|
51
|
+
path = "#{params["splat"].first}/#{filename}"
|
52
|
+
path.gsub(%r!(\d{4})/(\d{2})/(\d{2})/(.*)!, '\1-\2-\3-\4')
|
53
|
+
end
|
54
|
+
|
55
|
+
def directory_docs
|
56
|
+
collection.docs.find_all { |d| File.dirname(d.path) == directory_path }
|
57
|
+
end
|
58
|
+
|
59
|
+
def ensure_collection
|
60
|
+
render_404 if collection.nil?
|
61
|
+
end
|
62
|
+
|
63
|
+
def ensure_directory
|
64
|
+
ensure_collection
|
65
|
+
render_404 unless Dir.exist?(directory_path)
|
66
|
+
end
|
67
|
+
|
68
|
+
def entries
|
69
|
+
args = {
|
70
|
+
:base => site.source,
|
71
|
+
:content_type => params["collection_id"],
|
72
|
+
:splat => params["splat"].first,
|
73
|
+
}
|
74
|
+
# get the directories inside the requested directory
|
75
|
+
directory = JekyllAdmin::Directory.new(directory_path, args)
|
76
|
+
directories = directory.directories
|
77
|
+
# merge directories with the documents at the same level
|
78
|
+
directories.concat(directory_docs.sort_by(&:date).reverse)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module JekyllAdmin
|
2
|
+
class Server < Sinatra::Base
|
3
|
+
namespace "/configuration" do
|
4
|
+
get do
|
5
|
+
json raw_configuration.to_liquid
|
6
|
+
end
|
7
|
+
|
8
|
+
put do
|
9
|
+
write_file(configuration_path, configuration_body)
|
10
|
+
json raw_configuration.to_liquid
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def overrides
|
16
|
+
{
|
17
|
+
"source" => sanitized_path("/"),
|
18
|
+
}
|
19
|
+
end
|
20
|
+
|
21
|
+
# Computed configuration, with updates and defaults
|
22
|
+
def configuration
|
23
|
+
@configuration ||= Jekyll.configuration(overrides)
|
24
|
+
end
|
25
|
+
|
26
|
+
# Raw configuration, as it sits on disk
|
27
|
+
def raw_configuration
|
28
|
+
configuration.read_config_file(configuration_path)
|
29
|
+
end
|
30
|
+
|
31
|
+
# Returns the path to the *first* config file discovered
|
32
|
+
def configuration_path
|
33
|
+
sanitized_path configuration.config_files(overrides).first
|
34
|
+
end
|
35
|
+
|
36
|
+
# The user's uploaded configuration for updates
|
37
|
+
def configuration_body
|
38
|
+
YAML.dump request_payload
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module JekyllAdmin
|
2
|
+
class Server < Sinatra::Base
|
3
|
+
# supported extensions, in order of preference, for now, no .csv
|
4
|
+
EXTENSIONS = %w(yml json).freeze
|
5
|
+
|
6
|
+
namespace "/data" do
|
7
|
+
get do
|
8
|
+
json DataFile.all.map(&:to_api)
|
9
|
+
end
|
10
|
+
|
11
|
+
get "/:path.?:ext?" do
|
12
|
+
ensure_requested_file
|
13
|
+
json requested_file.to_api(:include_content => true)
|
14
|
+
end
|
15
|
+
|
16
|
+
put "/:path.?:ext?" do
|
17
|
+
if renamed?
|
18
|
+
ensure_requested_file
|
19
|
+
delete_file path
|
20
|
+
end
|
21
|
+
|
22
|
+
write_file write_path, data_file_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
|
+
def data_file_body
|
37
|
+
if !request_payload["raw_content"].to_s.empty?
|
38
|
+
request_payload["raw_content"]
|
39
|
+
elsif !request_payload["content"].to_s.empty?
|
40
|
+
YAML.dump(request_payload["content"]).sub(%r!\A---\n!, "")
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
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,61 @@
|
|
1
|
+
module JekyllAdmin
|
2
|
+
class Server < Sinatra::Base
|
3
|
+
namespace "/static_files" do
|
4
|
+
get do
|
5
|
+
json static_files.map(&:to_api)
|
6
|
+
end
|
7
|
+
|
8
|
+
get "/*" do
|
9
|
+
if requested_file
|
10
|
+
json requested_file.to_api(:include_content => true)
|
11
|
+
elsif !static_files_for_path.empty?
|
12
|
+
json static_files_for_path.map(&:to_api)
|
13
|
+
else
|
14
|
+
render_404
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
put "/*" do
|
19
|
+
if renamed?
|
20
|
+
ensure_requested_file
|
21
|
+
delete_file path
|
22
|
+
end
|
23
|
+
|
24
|
+
write_file(write_path, static_file_body)
|
25
|
+
json written_file.to_api(:include_content => true)
|
26
|
+
end
|
27
|
+
|
28
|
+
delete "/*" do
|
29
|
+
ensure_requested_file
|
30
|
+
delete_file path
|
31
|
+
content_type :json
|
32
|
+
status 200
|
33
|
+
halt
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def static_file_body
|
39
|
+
if !request_payload["raw_content"].to_s.empty?
|
40
|
+
request_payload["raw_content"].to_s
|
41
|
+
else
|
42
|
+
Base64.decode64 request_payload["encoded_content"].to_s
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def static_files
|
47
|
+
site.static_files
|
48
|
+
end
|
49
|
+
|
50
|
+
def file_list_dir(path) end
|
51
|
+
|
52
|
+
def static_files_for_path
|
53
|
+
# Joined with / to ensure user can't do partial paths
|
54
|
+
base_path = File.join(path, "/")
|
55
|
+
static_files.select do |f|
|
56
|
+
f.path.start_with? base_path
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module JekyllAdmin
|
2
|
+
class StaticServer < Sinatra::Base
|
3
|
+
set :public_dir, File.expand_path("./public", File.dirname(__FILE__))
|
4
|
+
|
5
|
+
MUST_BUILD_MESSAGE = "Front end not yet built. Run `script/build` to build.".freeze
|
6
|
+
|
7
|
+
# Allow `/admin` and `/admin/`, and `/admin/*` to serve `/public/dist/index.html`
|
8
|
+
get "/*" do
|
9
|
+
send_file index_path
|
10
|
+
end
|
11
|
+
|
12
|
+
# Provide a descriptive error message in dev. if frontend is not build
|
13
|
+
not_found do
|
14
|
+
status 404
|
15
|
+
MUST_BUILD_MESSAGE if settings.development? || settings.test?
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def index_path
|
21
|
+
@index_path ||= File.join(settings.public_folder, "index.html")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module JekyllAdmin
|
2
|
+
# Abstract module to be included in Convertible and Document to provide
|
3
|
+
# additional, URL-specific functionality without duplicating logic
|
4
|
+
module URLable
|
5
|
+
|
6
|
+
# Absolute URL to the HTTP(S) rendered/served representation of this resource
|
7
|
+
def http_url
|
8
|
+
return if is_a?(Jekyll::Collection) || is_a?(JekyllAdmin::DataFile)
|
9
|
+
return if is_a?(Jekyll::Document) && !collection.write?
|
10
|
+
@http_url ||= Addressable::URI.new(
|
11
|
+
:scheme => scheme, :host => host, :port => port,
|
12
|
+
:path => path_with_base(JekyllAdmin.site.config["baseurl"], url)
|
13
|
+
).normalize.to_s
|
14
|
+
end
|
15
|
+
|
16
|
+
# Absolute URL to the API representation of this resource
|
17
|
+
def api_url
|
18
|
+
@api_url ||= Addressable::URI.new(
|
19
|
+
:scheme => scheme, :host => host, :port => port,
|
20
|
+
:path => path_with_base("/_api", resource_path)
|
21
|
+
).normalize.to_s
|
22
|
+
end
|
23
|
+
|
24
|
+
def entries_url
|
25
|
+
return unless is_a?(Jekyll::Collection)
|
26
|
+
"#{api_url}/entries"
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
# URL path relative to `_api/` to retreive the given resource via the API
|
32
|
+
# Note: we can't use a case statement here, because === doesn't like includes
|
33
|
+
def resource_path
|
34
|
+
if is_a?(Jekyll::Document)
|
35
|
+
"/collections/#{relative_path.sub(%r!\A_!, "")}"
|
36
|
+
elsif is_a?(Jekyll::Collection)
|
37
|
+
"/collections/#{label}"
|
38
|
+
elsif is_a?(JekyllAdmin::DataFile)
|
39
|
+
relative_path.sub(%r!\A/#{DataFile.data_dir}!, "/data")
|
40
|
+
elsif is_a?(Jekyll::StaticFile)
|
41
|
+
"/static_files/#{relative_path}"
|
42
|
+
elsif is_a?(Jekyll::Page)
|
43
|
+
"/pages/#{relative_path}"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# URI.join doesn't like joining two relative paths, and File.join may join
|
48
|
+
# with `\` rather than with `/` on windows
|
49
|
+
def path_with_base(base, path)
|
50
|
+
[base, path].join("/").squeeze("/")
|
51
|
+
end
|
52
|
+
|
53
|
+
def scheme
|
54
|
+
JekyllAdmin.site.config["scheme"] || "http"
|
55
|
+
end
|
56
|
+
|
57
|
+
def host
|
58
|
+
JekyllAdmin.site.config["host"].sub("127.0.0.1", "localhost")
|
59
|
+
end
|
60
|
+
|
61
|
+
def port
|
62
|
+
JekyllAdmin.site.config["port"]
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Jekyll
|
2
|
+
module Commands
|
3
|
+
class Serve < Command
|
4
|
+
class << self
|
5
|
+
def start_up_webrick(opts, destination)
|
6
|
+
server = WEBrick::HTTPServer.new(webrick_opts(opts)).tap { |o| o.unmount("") }
|
7
|
+
server.mount(opts["baseurl"], Servlet, destination, file_handler_opts)
|
8
|
+
|
9
|
+
jekyll_admin_monkey_patch(server)
|
10
|
+
|
11
|
+
Jekyll.logger.info "Server address:", server_address(server, opts)
|
12
|
+
launch_browser server, opts if opts["open_url"]
|
13
|
+
boot_or_detach server, opts
|
14
|
+
end
|
15
|
+
|
16
|
+
def jekyll_admin_monkey_patch(server)
|
17
|
+
server.mount "/admin", Rack::Handler::WEBrick, JekyllAdmin::StaticServer
|
18
|
+
server.mount "/_api", Rack::Handler::WEBrick, JekyllAdmin::Server
|
19
|
+
Jekyll.logger.info "JekyllAdmin mode:", ENV["RACK_ENV"] || "production"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
metadata
ADDED
@@ -0,0 +1,207 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: jekyll-admin-jekyll34
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.4.3
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Mert Kahyaoğlu
|
8
|
+
- GitHub Open Source
|
9
|
+
autorequire:
|
10
|
+
bindir: exe
|
11
|
+
cert_chain: []
|
12
|
+
date: 2017-04-19 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: jekyll
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - ">="
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '3.4'
|
21
|
+
type: :runtime
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: '3.4'
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: sinatra
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - ">="
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '1.4'
|
35
|
+
type: :runtime
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '1.4'
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: sinatra-contrib
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - ">="
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '1.4'
|
49
|
+
type: :runtime
|
50
|
+
prerelease: false
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '1.4'
|
56
|
+
- !ruby/object:Gem::Dependency
|
57
|
+
name: addressable
|
58
|
+
requirement: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '2.4'
|
63
|
+
type: :runtime
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '2.4'
|
70
|
+
- !ruby/object:Gem::Dependency
|
71
|
+
name: bundler
|
72
|
+
requirement: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - ">="
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '1.7'
|
77
|
+
type: :development
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - ">="
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '1.7'
|
84
|
+
- !ruby/object:Gem::Dependency
|
85
|
+
name: rake
|
86
|
+
requirement: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - ">="
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: '10.0'
|
91
|
+
type: :development
|
92
|
+
prerelease: false
|
93
|
+
version_requirements: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - ">="
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '10.0'
|
98
|
+
- !ruby/object:Gem::Dependency
|
99
|
+
name: rspec
|
100
|
+
requirement: !ruby/object:Gem::Requirement
|
101
|
+
requirements:
|
102
|
+
- - ">="
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: '3.4'
|
105
|
+
type: :development
|
106
|
+
prerelease: false
|
107
|
+
version_requirements: !ruby/object:Gem::Requirement
|
108
|
+
requirements:
|
109
|
+
- - ">="
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
version: '3.4'
|
112
|
+
- !ruby/object:Gem::Dependency
|
113
|
+
name: rubocop
|
114
|
+
requirement: !ruby/object:Gem::Requirement
|
115
|
+
requirements:
|
116
|
+
- - ">="
|
117
|
+
- !ruby/object:Gem::Version
|
118
|
+
version: '0.35'
|
119
|
+
type: :development
|
120
|
+
prerelease: false
|
121
|
+
version_requirements: !ruby/object:Gem::Requirement
|
122
|
+
requirements:
|
123
|
+
- - ">="
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: '0.35'
|
126
|
+
- !ruby/object:Gem::Dependency
|
127
|
+
name: sinatra-cross_origin
|
128
|
+
requirement: !ruby/object:Gem::Requirement
|
129
|
+
requirements:
|
130
|
+
- - ">="
|
131
|
+
- !ruby/object:Gem::Version
|
132
|
+
version: '0.3'
|
133
|
+
type: :development
|
134
|
+
prerelease: false
|
135
|
+
version_requirements: !ruby/object:Gem::Requirement
|
136
|
+
requirements:
|
137
|
+
- - ">="
|
138
|
+
- !ruby/object:Gem::Version
|
139
|
+
version: '0.3'
|
140
|
+
- !ruby/object:Gem::Dependency
|
141
|
+
name: gem-release
|
142
|
+
requirement: !ruby/object:Gem::Requirement
|
143
|
+
requirements:
|
144
|
+
- - ">="
|
145
|
+
- !ruby/object:Gem::Version
|
146
|
+
version: '0.7'
|
147
|
+
type: :development
|
148
|
+
prerelease: false
|
149
|
+
version_requirements: !ruby/object:Gem::Requirement
|
150
|
+
requirements:
|
151
|
+
- - ">="
|
152
|
+
- !ruby/object:Gem::Version
|
153
|
+
version: '0.7'
|
154
|
+
description: Jekyll::Admin is a drop in administrative framework for Jekyll sites.
|
155
|
+
email:
|
156
|
+
- mertkahyaoglu93@gmail.com
|
157
|
+
- opensource@github.com
|
158
|
+
executables: []
|
159
|
+
extensions: []
|
160
|
+
extra_rdoc_files: []
|
161
|
+
files:
|
162
|
+
- LICENSE
|
163
|
+
- README.md
|
164
|
+
- lib/jekyll-admin.rb
|
165
|
+
- lib/jekyll-admin/apiable.rb
|
166
|
+
- lib/jekyll-admin/data_file.rb
|
167
|
+
- lib/jekyll-admin/directory.rb
|
168
|
+
- lib/jekyll-admin/file_helper.rb
|
169
|
+
- lib/jekyll-admin/page_without_a_file.rb
|
170
|
+
- lib/jekyll-admin/path_helper.rb
|
171
|
+
- lib/jekyll-admin/server.rb
|
172
|
+
- lib/jekyll-admin/server/collection.rb
|
173
|
+
- lib/jekyll-admin/server/configuration.rb
|
174
|
+
- lib/jekyll-admin/server/data.rb
|
175
|
+
- lib/jekyll-admin/server/page.rb
|
176
|
+
- lib/jekyll-admin/server/static_file.rb
|
177
|
+
- lib/jekyll-admin/static_server.rb
|
178
|
+
- lib/jekyll-admin/urlable.rb
|
179
|
+
- lib/jekyll-admin/version.rb
|
180
|
+
- lib/jekyll/commands/build.rb
|
181
|
+
- lib/jekyll/commands/serve.rb
|
182
|
+
homepage: https://github.com/honey-be/jekyll-admin-jekyll34
|
183
|
+
licenses:
|
184
|
+
- MIT
|
185
|
+
metadata:
|
186
|
+
allowed_push_host: https://rubygems.org
|
187
|
+
post_install_message:
|
188
|
+
rdoc_options: []
|
189
|
+
require_paths:
|
190
|
+
- lib
|
191
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
192
|
+
requirements:
|
193
|
+
- - ">="
|
194
|
+
- !ruby/object:Gem::Version
|
195
|
+
version: '0'
|
196
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
197
|
+
requirements:
|
198
|
+
- - ">="
|
199
|
+
- !ruby/object:Gem::Version
|
200
|
+
version: '0'
|
201
|
+
requirements: []
|
202
|
+
rubyforge_project:
|
203
|
+
rubygems_version: 2.6.11
|
204
|
+
signing_key:
|
205
|
+
specification_version: 4
|
206
|
+
summary: wp-admin for Jekyll, but better
|
207
|
+
test_files: []
|