jekyll-github-pages-gem 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Gemfile +23 -0
- data/Gemfile.lock +97 -0
- data/README.md +16 -0
- data/Rakefile +9 -0
- data/jekyll_github_pages.gemspec +11 -0
- data/lib/factories/post_factory.rb +70 -0
- data/lib/jekyll_github_pages.rb +19 -0
- data/lib/models/post.rb +30 -0
- data/lib/models/post_image_manager.rb +58 -0
- data/lib/services/github_service.rb +237 -0
- data/lib/services/kramdown_service.rb +186 -0
- data/lib/services/post_services/base_post_service.rb +42 -0
- data/lib/services/post_services/post_creation_service.rb +55 -0
- data/lib/services/post_services/post_editing_service.rb +46 -0
- data/lib/services/post_services/post_pull_request_editing_service.rb +33 -0
- data/lib/uploaders/post_image_uploader.rb +43 -0
- metadata +59 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 1e96acc9371c59ba0163040fc42595a54ec2dc7602b9d128313cb1b05d2c4106
|
4
|
+
data.tar.gz: 5310d22171f0150137e9abdbac7c0d3147f47f27f84f1c3c240c664e0033baef
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 07c6be16e280cd410f7a0f5c25e16ea7fdbd69611a2a7fb61ec19846428b4ca2fe53a48eb0aec9504b8532b17bb6de815bbde38fc0ce82c6a71e83f0e47881c3
|
7
|
+
data.tar.gz: d9cdef19e6748af33fcd01c8dd1a30fb6a032b38839b924d168b26789720e63aeb032002e7cdbc699fb55f2bf58b45ea13fb6ca7a0c395e4c368a245da4743e8
|
data/Gemfile
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
source 'https://rubygems.org'
|
4
|
+
gemspec
|
5
|
+
|
6
|
+
gem 'kramdown'
|
7
|
+
|
8
|
+
gem 'octokit', '~> 4.18'
|
9
|
+
|
10
|
+
gem 'rubocop', '~> 0.71'
|
11
|
+
|
12
|
+
gem 'carrierwave', '>= 2.0.0.rc', '< 3.0'
|
13
|
+
|
14
|
+
# Octokit does not work with the most recent version of faraday so this locks it to a version that works.
|
15
|
+
gem 'faraday', '~> 0.17.1'
|
16
|
+
|
17
|
+
gem 'rake'
|
18
|
+
|
19
|
+
group :test do
|
20
|
+
gem 'minitest'
|
21
|
+
gem 'mocha'
|
22
|
+
gem 'simplecov'
|
23
|
+
end
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
jekyll-github-pages-gem (1.0.0)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: https://rubygems.org/
|
8
|
+
specs:
|
9
|
+
activemodel (6.0.2.2)
|
10
|
+
activesupport (= 6.0.2.2)
|
11
|
+
activesupport (6.0.2.2)
|
12
|
+
concurrent-ruby (~> 1.0, >= 1.0.2)
|
13
|
+
i18n (>= 0.7, < 2)
|
14
|
+
minitest (~> 5.1)
|
15
|
+
tzinfo (~> 1.1)
|
16
|
+
zeitwerk (~> 2.2)
|
17
|
+
addressable (2.7.0)
|
18
|
+
public_suffix (>= 2.0.2, < 5.0)
|
19
|
+
ast (2.4.0)
|
20
|
+
carrierwave (2.1.0)
|
21
|
+
activemodel (>= 5.0.0)
|
22
|
+
activesupport (>= 5.0.0)
|
23
|
+
addressable (~> 2.6)
|
24
|
+
image_processing (~> 1.1)
|
25
|
+
mimemagic (>= 0.3.0)
|
26
|
+
mini_mime (>= 0.1.3)
|
27
|
+
concurrent-ruby (1.1.6)
|
28
|
+
docile (1.3.2)
|
29
|
+
faraday (0.17.3)
|
30
|
+
multipart-post (>= 1.2, < 3)
|
31
|
+
ffi (1.12.2)
|
32
|
+
ffi (1.12.2-x64-mingw32)
|
33
|
+
i18n (1.8.2)
|
34
|
+
concurrent-ruby (~> 1.0)
|
35
|
+
image_processing (1.10.3)
|
36
|
+
mini_magick (>= 4.9.5, < 5)
|
37
|
+
ruby-vips (>= 2.0.17, < 3)
|
38
|
+
jaro_winkler (1.5.4)
|
39
|
+
kramdown (2.1.0)
|
40
|
+
mimemagic (0.3.4)
|
41
|
+
mini_magick (4.10.1)
|
42
|
+
mini_mime (1.0.2)
|
43
|
+
minitest (5.14.0)
|
44
|
+
mocha (1.11.2)
|
45
|
+
multipart-post (2.1.1)
|
46
|
+
octokit (4.18.0)
|
47
|
+
faraday (>= 0.9)
|
48
|
+
sawyer (~> 0.8.0, >= 0.5.3)
|
49
|
+
parallel (1.19.1)
|
50
|
+
parser (2.7.1.0)
|
51
|
+
ast (~> 2.4.0)
|
52
|
+
public_suffix (4.0.4)
|
53
|
+
rainbow (3.0.0)
|
54
|
+
rake (13.0.1)
|
55
|
+
rexml (3.2.4)
|
56
|
+
rubocop (0.81.0)
|
57
|
+
jaro_winkler (~> 1.5.1)
|
58
|
+
parallel (~> 1.10)
|
59
|
+
parser (>= 2.7.0.1)
|
60
|
+
rainbow (>= 2.2.2, < 4.0)
|
61
|
+
rexml
|
62
|
+
ruby-progressbar (~> 1.7)
|
63
|
+
unicode-display_width (>= 1.4.0, < 2.0)
|
64
|
+
ruby-progressbar (1.10.1)
|
65
|
+
ruby-vips (2.0.17)
|
66
|
+
ffi (~> 1.9)
|
67
|
+
sawyer (0.8.2)
|
68
|
+
addressable (>= 2.3.5)
|
69
|
+
faraday (> 0.8, < 2.0)
|
70
|
+
simplecov (0.18.5)
|
71
|
+
docile (~> 1.1)
|
72
|
+
simplecov-html (~> 0.11)
|
73
|
+
simplecov-html (0.12.2)
|
74
|
+
thread_safe (0.3.6)
|
75
|
+
tzinfo (1.2.7)
|
76
|
+
thread_safe (~> 0.1)
|
77
|
+
unicode-display_width (1.7.0)
|
78
|
+
zeitwerk (2.3.0)
|
79
|
+
|
80
|
+
PLATFORMS
|
81
|
+
ruby
|
82
|
+
x64-mingw32
|
83
|
+
|
84
|
+
DEPENDENCIES
|
85
|
+
carrierwave (>= 2.0.0.rc, < 3.0)
|
86
|
+
faraday (~> 0.17.1)
|
87
|
+
jekyll-github-pages-gem!
|
88
|
+
kramdown
|
89
|
+
minitest
|
90
|
+
mocha
|
91
|
+
octokit (~> 4.18)
|
92
|
+
rake
|
93
|
+
rubocop (~> 0.71)
|
94
|
+
simplecov
|
95
|
+
|
96
|
+
BUNDLED WITH
|
97
|
+
2.1.4
|
data/README.md
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
[![Build Status](https://travis-ci.org/msoe-sg/jekyll-github-pages-gem.svg?branch=master)](https://travis-ci.org/msoe-sg/jekyll-github-pages-gem)
|
2
|
+
|
3
|
+
## Setup
|
4
|
+
1. Follow the instructions from the wiki article [here](https://github.com/msoe-sg/msoe-sg-website/wiki/Environment-Setup) to setup your development environment.
|
5
|
+
2. Open up a terminal to the folder where you want to clone the repo and run the command `git@github.com:msoe-sg/jekyll-github-pages-gem.git`
|
6
|
+
3. After run the clone change into the project directory by running the command `cd jekyll-github-pages-gem`
|
7
|
+
4. Next install the dependencies for the project by running the command `bundle install`
|
8
|
+
5. Contribute
|
9
|
+
Our git flow process is typical--we have a master branch that gets released to the public, and feature branches for individual tasks. We don't have a development branch yet since this isn't used in production yet.
|
10
|
+
If you have questions on how to contribute, please contact admin@msoe-sse.com or msoe.sg.hosting@gmail.com and we will get back to you at our earliest convenience.
|
11
|
+
|
12
|
+
## Continuous Integration
|
13
|
+
There are checks that will be performed whenever Pull Requests are opened. To save time on the build server, please run the tests locally to check for errors that will occur in the CI builds.
|
14
|
+
|
15
|
+
1. To run [Rubocop](https://github.com/ashmaroli/rubocop-jekyll), run the command `bundle exec rubocop`
|
16
|
+
2. To run all unit tests, run the command `rake`
|
data/Rakefile
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = 'jekyll-github-pages-gem'
|
5
|
+
s.version = '1.0.0'
|
6
|
+
s.summary = 'A gem that uses the github API to make edits with a jekyll blog'
|
7
|
+
s.files = Dir['*', 'lib/**/*']
|
8
|
+
s.require_paths = ['lib']
|
9
|
+
s.licenses = ['MIT']
|
10
|
+
s.authors = ['MSOE SSE Web Team']
|
11
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../models/post'
|
4
|
+
|
5
|
+
module Factories
|
6
|
+
##
|
7
|
+
# This class is a factory for parsing post text and creating a correseponding post model
|
8
|
+
class PostFactory
|
9
|
+
LEAD = '{: .lead}'
|
10
|
+
BREAK = '<!–-break-–>'
|
11
|
+
|
12
|
+
# serves as the default hero for a post if none is provided.
|
13
|
+
DEFAULT_HERO = 'https://source.unsplash.com/collection/145103/'
|
14
|
+
|
15
|
+
##
|
16
|
+
# This method parses markdown in a post a returns a post model
|
17
|
+
#
|
18
|
+
# Params:
|
19
|
+
# +post_contents+::markdown in a given post
|
20
|
+
# +file_path+::the path on GitHub to the post
|
21
|
+
# +ref+::a sha for a ref indicating the head of a branch a post is pushed to on the GitHub server
|
22
|
+
def create_post(post_contents, file_path, ref)
|
23
|
+
create_post_model(post_contents, file_path, ref) if !post_contents.nil? && post_contents.is_a?(String)
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def parse_tags(header)
|
29
|
+
result = []
|
30
|
+
header.lines.each do |line|
|
31
|
+
tag_match = line.match(/\s*-\s*(.*)/)
|
32
|
+
result << tag_match.captures.first if tag_match
|
33
|
+
end
|
34
|
+
result.join(', ')
|
35
|
+
end
|
36
|
+
|
37
|
+
def create_post_model(post_contents, file_path, ref)
|
38
|
+
result = Post.new
|
39
|
+
|
40
|
+
result.file_path = file_path
|
41
|
+
result.github_ref = ref
|
42
|
+
|
43
|
+
# What this regular expression does is it matches three groups
|
44
|
+
# The first group represents the header of the post which appears
|
45
|
+
# between the two --- lines. The second group is for helping capture newline characters
|
46
|
+
# correctly and the third group is the actual post contents
|
47
|
+
match_obj = post_contents.match(/---(.*)---(\r\n|\r|\n)(.*)/m)
|
48
|
+
header = match_obj.captures[0]
|
49
|
+
|
50
|
+
parse_post_header(header, result)
|
51
|
+
result.contents = match_obj.captures[2]
|
52
|
+
.remove("#{LEAD}\r\n")
|
53
|
+
.remove("#{LEAD}\n")
|
54
|
+
.remove("#{BREAK}\r\n")
|
55
|
+
.remove("#{BREAK}\n")
|
56
|
+
result.tags = parse_tags(header)
|
57
|
+
result
|
58
|
+
end
|
59
|
+
|
60
|
+
def parse_post_header(header, post_model)
|
61
|
+
# The following regular expressions in this method look for specific properities
|
62
|
+
# located in the post header.
|
63
|
+
post_model.title = header.match(/title:\s*(.*)(\r\n|\r|\n)/).captures.first
|
64
|
+
post_model.author = header.match(/author:\s*(.*)(\r\n|\r|\n)/).captures.first
|
65
|
+
post_model.hero = header.match(/hero:\s*(.*)(\r\n|\r|\n)/).captures.first
|
66
|
+
post_model.hero = '' if post_model.hero == DEFAULT_HERO
|
67
|
+
post_model.overlay = header.match(/overlay:\s*(.*)(\r\n|\r|\n)/).captures.first
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Third Party Dependencies
|
4
|
+
require 'carrierwave'
|
5
|
+
|
6
|
+
# Source Files
|
7
|
+
require 'factories/post_factory'
|
8
|
+
require 'services/post_services/base_post_service'
|
9
|
+
require 'services/post_services/post_creation_service'
|
10
|
+
require 'services/post_services/post_editing_service'
|
11
|
+
require 'services/post_services/post_pull_request_editing_service'
|
12
|
+
require 'services/github_service'
|
13
|
+
|
14
|
+
require 'services/kramdown_service'
|
15
|
+
|
16
|
+
require 'models/post'
|
17
|
+
require 'models/post_image_manager'
|
18
|
+
|
19
|
+
require 'uploaders/post_image_uploader'
|
data/lib/models/post.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
##
|
4
|
+
# An object representing an image that is on a post
|
5
|
+
class PostImage
|
6
|
+
attr_accessor :filename
|
7
|
+
# The binary contents of an image as a Base64 string
|
8
|
+
attr_accessor :contents
|
9
|
+
end
|
10
|
+
|
11
|
+
##
|
12
|
+
# An object representing a post on the Jekyll website
|
13
|
+
class Post
|
14
|
+
attr_accessor :title
|
15
|
+
attr_accessor :author
|
16
|
+
attr_accessor :hero
|
17
|
+
attr_accessor :overlay
|
18
|
+
attr_accessor :contents
|
19
|
+
attr_accessor :tags
|
20
|
+
# Path to the markdown post starting at the root of the repository
|
21
|
+
attr_accessor :file_path
|
22
|
+
# The GitHub ref the post's markdown is at. This is used to indicate
|
23
|
+
# whether a post is in PR or not
|
24
|
+
attr_accessor :github_ref
|
25
|
+
attr_accessor :images
|
26
|
+
|
27
|
+
def initialize
|
28
|
+
@images = []
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'singleton'
|
4
|
+
|
5
|
+
##
|
6
|
+
# A singleton class for managing all image attachments for a post
|
7
|
+
class PostImageManager
|
8
|
+
include Singleton
|
9
|
+
|
10
|
+
attr_reader :uploaders
|
11
|
+
attr_reader :downloaded_images
|
12
|
+
attr_accessor :root_dir
|
13
|
+
|
14
|
+
##
|
15
|
+
# The constructor for PostImageManager which initializes the array of Carrierware
|
16
|
+
# image uploaders to use when submiting a post and the array of downloaded images
|
17
|
+
def initialize
|
18
|
+
@uploaders = []
|
19
|
+
@downloaded_images = []
|
20
|
+
@root_dir = ''
|
21
|
+
end
|
22
|
+
|
23
|
+
##
|
24
|
+
# Adds an image to be uploaded in a Jekyll website post
|
25
|
+
#
|
26
|
+
# Params:
|
27
|
+
# +file+:: A ActionDispatch::Http::UploadedFile object containing the file to be used in a post
|
28
|
+
def add_file(file)
|
29
|
+
uploader_to_add = PostImageUploader.new
|
30
|
+
uploader_to_add.cache!(file)
|
31
|
+
@uploaders.delete_if { |x| x.filename == file.original_filename }
|
32
|
+
@uploaders << uploader_to_add
|
33
|
+
end
|
34
|
+
|
35
|
+
##
|
36
|
+
# Adds an image that was downloaded from the Jekyll website repo
|
37
|
+
#
|
38
|
+
# Params:
|
39
|
+
# +downloaded_image+:: A PostImage object representing the downloaded image
|
40
|
+
def add_downloaded_image(downloaded_image)
|
41
|
+
@downloaded_images << downloaded_image
|
42
|
+
end
|
43
|
+
|
44
|
+
##
|
45
|
+
# Clears the manager of all currently exisiting image uploaders and delete's their cache directories.
|
46
|
+
# Also clears the manager of all of the downloaded images
|
47
|
+
def clear(_root_dir)
|
48
|
+
@uploaders.each do |uploader|
|
49
|
+
full_preview_path = "#{@root_dir}/public/uploads/tmp/#{uploader.preview.cache_name}"
|
50
|
+
cache_dir = File.expand_path('..', full_preview_path)
|
51
|
+
uploader.remove!
|
52
|
+
Dir.delete(cache_dir)
|
53
|
+
end
|
54
|
+
|
55
|
+
@uploaders.clear
|
56
|
+
@downloaded_images.clear
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,237 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'octokit'
|
4
|
+
require 'base64'
|
5
|
+
require 'date'
|
6
|
+
require 'cgi'
|
7
|
+
require_relative 'kramdown_service'
|
8
|
+
require_relative '../factories/post_factory'
|
9
|
+
|
10
|
+
module Services
|
11
|
+
##
|
12
|
+
# This class contains all operations involving interacting with the GitHub API
|
13
|
+
class GithubService
|
14
|
+
def initialize(full_repo_name, access_token)
|
15
|
+
@full_repo_name = full_repo_name
|
16
|
+
@access_token = access_token
|
17
|
+
|
18
|
+
@kramdown_service = Services::KramdownService.new
|
19
|
+
@post_factory = Factories::PostFactory.new
|
20
|
+
end
|
21
|
+
|
22
|
+
##
|
23
|
+
# This method fetches all the markdown contents of all the posts on a Jekyll website
|
24
|
+
# that have been written and returns a list of models representing a Post.
|
25
|
+
def get_all_posts
|
26
|
+
result = []
|
27
|
+
client = create_octokit_client
|
28
|
+
posts = client.contents(@full_repo_name, path: '_posts')
|
29
|
+
posts.each do |post|
|
30
|
+
post_api_response = client.contents(@full_repo_name, path: post.path)
|
31
|
+
|
32
|
+
post_model = create_post_from_api_response(post_api_response, nil)
|
33
|
+
image_paths = @kramdown_service.get_all_image_paths(post_model.contents)
|
34
|
+
|
35
|
+
images = []
|
36
|
+
image_paths.each do |image_path|
|
37
|
+
image_content = client.contents(@full_repo_name, path: image_path)
|
38
|
+
images << create_post_image(image_path, image_content.content)
|
39
|
+
end
|
40
|
+
|
41
|
+
post_model.images = images
|
42
|
+
|
43
|
+
result << post_model
|
44
|
+
end
|
45
|
+
result
|
46
|
+
end
|
47
|
+
|
48
|
+
##
|
49
|
+
# This method fetches all of the posts that have been written but have not been merged into master yet.
|
50
|
+
def get_all_posts_in_pr(pr_body)
|
51
|
+
result = []
|
52
|
+
client = create_octokit_client
|
53
|
+
pull_requests_for_user = get_open_jekyll_pull_requests(pr_body)
|
54
|
+
|
55
|
+
pull_requests_for_user.each do |pull_request|
|
56
|
+
pull_request_files = client.pull_request_files(@full_repo_name, pull_request[:number])
|
57
|
+
|
58
|
+
post = nil
|
59
|
+
images = []
|
60
|
+
pull_request_files.each do |pull_request_file|
|
61
|
+
contents_url_params = CGI.parse(pull_request_file[:contents_url])
|
62
|
+
|
63
|
+
# The CGI.parse method returns a hash with the key being the URL and the value being an array of
|
64
|
+
# URI parameters so in order to get the ref we need to grab the first value in the hash and the first
|
65
|
+
# URI parameter in the first hash value
|
66
|
+
ref = contents_url_params.values.first.first
|
67
|
+
file_contents = client.contents(@full_repo_name, path: pull_request_file[:filename], ref: ref)
|
68
|
+
|
69
|
+
if pull_request_file[:filename].end_with?('.md')
|
70
|
+
post = create_post_from_api_response(file_contents, ref)
|
71
|
+
result << post
|
72
|
+
else
|
73
|
+
images << create_post_image(pull_request_file[:filename], file_contents.content)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
post.images = images
|
78
|
+
end
|
79
|
+
result
|
80
|
+
end
|
81
|
+
|
82
|
+
##
|
83
|
+
# This method fetches a single post from a Jekyll website given a post title
|
84
|
+
# and returns a Post model
|
85
|
+
#
|
86
|
+
# Params:
|
87
|
+
# +title+:: A title of a Jekyll website post
|
88
|
+
# +ref+::a sha for a ref indicating the head of a branch a post is pushed to on the GitHub server
|
89
|
+
def get_post_by_title(title, ref)
|
90
|
+
result = nil
|
91
|
+
result = get_all_posts_in_pr.find { |x| x.title == title } if ref
|
92
|
+
result = get_all_posts.find { |x| x.title == title } unless ref
|
93
|
+
result&.images&.each { |x| PostImageManager.instance.add_downloaded_image(x) }
|
94
|
+
result
|
95
|
+
end
|
96
|
+
|
97
|
+
##
|
98
|
+
# This method gets the sha of the commit at the head of master in a Jekyll website repo
|
99
|
+
def get_master_head_sha
|
100
|
+
client = create_octokit_client
|
101
|
+
client.ref(@full_repo_name, 'heads/master')[:object][:sha]
|
102
|
+
end
|
103
|
+
|
104
|
+
##
|
105
|
+
# This method gets the sha of the base tree for a given branch in a Jekyll website repo
|
106
|
+
#
|
107
|
+
# Params
|
108
|
+
# +head_sha+::the sha of the head of a certain branch
|
109
|
+
def get_base_tree_for_branch(head_sha)
|
110
|
+
client = create_octokit_client
|
111
|
+
client.commit(@full_repo_name, head_sha)[:commit][:tree][:sha]
|
112
|
+
end
|
113
|
+
|
114
|
+
##
|
115
|
+
# This method create a new blob in a Jekyll website repo with text content
|
116
|
+
#
|
117
|
+
# Params
|
118
|
+
# +text+::the text content to create a blob for
|
119
|
+
def create_text_blob(text)
|
120
|
+
client = create_octokit_client
|
121
|
+
client.create_blob(@full_repo_name, text)
|
122
|
+
end
|
123
|
+
|
124
|
+
##
|
125
|
+
# This method creates a new blob in a Jekyll website with base 64 encoded content
|
126
|
+
#
|
127
|
+
# Params
|
128
|
+
# +content+::the base 64 encoded content to create a blob for
|
129
|
+
def create_base64_encoded_blob(content)
|
130
|
+
client = create_octokit_client
|
131
|
+
client.create_blob(@full_repo_name, content, 'base64')
|
132
|
+
end
|
133
|
+
|
134
|
+
##
|
135
|
+
# This method creates a new tree in a Jekyll website repo and returns the tree's sha.
|
136
|
+
# The method assumes that the paths passed into the method have corresponding blobs
|
137
|
+
# created for the files
|
138
|
+
#
|
139
|
+
# Params:
|
140
|
+
# +file_information+::an array of hashes containing the file path and the blob sha for a file
|
141
|
+
# +sha_base_tree+::the sha of the base tree
|
142
|
+
def create_new_tree_with_blobs(file_information, sha_base_tree)
|
143
|
+
client = create_octokit_client
|
144
|
+
blob_information = []
|
145
|
+
file_information.each do |file|
|
146
|
+
# This mode property on this hash represents the file mode for a GitHub tree.
|
147
|
+
# The mode is 100644 for a file blob. See https://developer.github.com/v3/git/trees/ for more information
|
148
|
+
blob_information << { path: file[:path],
|
149
|
+
mode: '100644',
|
150
|
+
type: 'blob',
|
151
|
+
sha: file[:blob_sha] }
|
152
|
+
end
|
153
|
+
client.create_tree(@full_repo_name, blob_information, base_tree: sha_base_tree)[:sha]
|
154
|
+
end
|
155
|
+
|
156
|
+
##
|
157
|
+
# This method commits and pushes a tree to a Jekyll website repo
|
158
|
+
#
|
159
|
+
# Params:
|
160
|
+
# +commit_message+::the message for the new commit
|
161
|
+
# +tree_sha+::the sha of the tree to commit
|
162
|
+
# +head_sha+::the sha of the head to commit from
|
163
|
+
def commit_and_push_to_repo(commit_message, tree_sha, head_sha, ref_name)
|
164
|
+
client = create_octokit_client
|
165
|
+
sha_new_commit = client.create_commit(@full_repo_name, commit_message, tree_sha, head_sha)[:sha]
|
166
|
+
client.update_ref(@full_repo_name, ref_name, sha_new_commit)
|
167
|
+
end
|
168
|
+
|
169
|
+
##
|
170
|
+
# This method creates a pull request for a branch in a Jekyll website repo
|
171
|
+
#
|
172
|
+
# Params:
|
173
|
+
# +source_branch+::the source branch for the PR
|
174
|
+
# +base_branch+::the base branch for the PR
|
175
|
+
# +pr_title+::the title for the PR
|
176
|
+
# +pr_body+::the body for the PR
|
177
|
+
# +reviewers+::an array of pull request reviewers for the PR
|
178
|
+
def create_pull_request(source_branch, base_branch, pr_title, pr_body, reviewers)
|
179
|
+
client = create_octokit_client
|
180
|
+
pull_number = client.create_pull_request(@full_repo_name, base_branch, source_branch, pr_title, pr_body)[:number]
|
181
|
+
client.request_pull_request_review(@full_repo_name, pull_number, reviewers: reviewers)
|
182
|
+
end
|
183
|
+
|
184
|
+
##
|
185
|
+
# This method will create a branch in a Jekyll website repo
|
186
|
+
# if it already doesn't exist
|
187
|
+
#
|
188
|
+
# Params:
|
189
|
+
# +ref_name+:: the name of the branch to create if necessary
|
190
|
+
# +master_head_sha+:: the sha representing the head of master
|
191
|
+
def create_ref_if_necessary(ref_name, master_head_sha)
|
192
|
+
client = create_octokit_client
|
193
|
+
client.ref(@full_repo_name, ref_name)
|
194
|
+
rescue Octokit::NotFound
|
195
|
+
client.create_ref(@full_repo_name, ref_name, master_head_sha)
|
196
|
+
end
|
197
|
+
|
198
|
+
##
|
199
|
+
# This method will fetch a GitHub's ref name given it's sha identifier.
|
200
|
+
# It will also strip off the starting refs portion of the name
|
201
|
+
#
|
202
|
+
# Params:
|
203
|
+
# +oauth_token+::a user's oauth access token
|
204
|
+
# +ref_sha+:: the sha of the ref to fetch
|
205
|
+
def get_ref_name_by_sha(ref_sha)
|
206
|
+
client = create_octokit_client
|
207
|
+
ref_response = client.refs(@full_repo_name).find { |x| x[:object][:sha] == ref_sha }
|
208
|
+
ref_response[:ref].match(%r{refs/(.*)}).captures.first
|
209
|
+
end
|
210
|
+
|
211
|
+
private
|
212
|
+
|
213
|
+
def create_post_from_api_response(post, ref)
|
214
|
+
# Base64.decode64 will convert our string into a ASCII string
|
215
|
+
# calling force_encoding('UTF-8') will fix that problem
|
216
|
+
text_contents = Base64.decode64(post.content).dup.force_encoding('UTF-8')
|
217
|
+
@post_factory.create_post(text_contents, post.path, ref)
|
218
|
+
end
|
219
|
+
|
220
|
+
def get_open_jekyll_pull_requests(pull_request_body)
|
221
|
+
client = create_octokit_client
|
222
|
+
open_pull_requests = client.pull_requests(@full_repo_name, state: 'open')
|
223
|
+
open_pull_requests.select { |x| x[:body] == pull_request_body }
|
224
|
+
end
|
225
|
+
|
226
|
+
def create_post_image(filename, contents)
|
227
|
+
result = PostImage.new
|
228
|
+
result.filename = filename
|
229
|
+
result.contents = contents
|
230
|
+
result
|
231
|
+
end
|
232
|
+
|
233
|
+
def create_octokit_client
|
234
|
+
Octokit::Client.new(access_token: @access_token)
|
235
|
+
end
|
236
|
+
end
|
237
|
+
end
|
@@ -0,0 +1,186 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'kramdown'
|
4
|
+
|
5
|
+
##
|
6
|
+
# This modules contains extentions of the Kramdown::Convert module for custom kramdown converters
|
7
|
+
module Kramdown
|
8
|
+
module Converter
|
9
|
+
##
|
10
|
+
# A custom kramdown HTML converter for getting the HTML preview for a post
|
11
|
+
class Preview < Html
|
12
|
+
##
|
13
|
+
# An override of the convert_img tag which converts all image sources to pull
|
14
|
+
# from the CarrierWare cache location if an uploader exists with the image's filename.
|
15
|
+
# Or the Base64 contents of a downloaded image are replaced in the src attribute if the image
|
16
|
+
# was downloaded for the post
|
17
|
+
#
|
18
|
+
# Params:
|
19
|
+
# +el+::the image element to convert to html
|
20
|
+
# +indent+::the indent of the HTML
|
21
|
+
def convert_img(element, indent)
|
22
|
+
formatted_filename = File.basename(element.attr['src']).tr(' ', '_')
|
23
|
+
uploader = PostImageManager.instance.uploaders.find { |x| x.filename == formatted_filename }
|
24
|
+
if uploader
|
25
|
+
element.attr['src'] = "/uploads/tmp/#{uploader.preview.cache_name}"
|
26
|
+
else
|
27
|
+
downloaded_image = PostImageManager.instance.downloaded_images
|
28
|
+
.find { |x| File.basename(x.filename) == File.basename(element.attr['src']) }
|
29
|
+
if downloaded_image
|
30
|
+
extension = File.extname(downloaded_image.filename)
|
31
|
+
extension[0] = ''
|
32
|
+
element.attr['src'] = "data:image/#{extension};base64,#{downloaded_image.contents}"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
super(element, indent)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
module Services
|
43
|
+
##
|
44
|
+
# This class contains all operations with interacting with the kramdown engine
|
45
|
+
class KramdownService
|
46
|
+
DEFAULT_HERO = 'https://source.unsplash.com/collection/145103/'
|
47
|
+
##
|
48
|
+
# This method takes given markdown and converts it to HTML for the post preview
|
49
|
+
#
|
50
|
+
# Params:
|
51
|
+
# +text+:: markdown to convert to html
|
52
|
+
def get_preview(text)
|
53
|
+
Kramdown::Document.new(text).to_preview
|
54
|
+
end
|
55
|
+
|
56
|
+
##
|
57
|
+
# This method returns the image filename given some markdown
|
58
|
+
#
|
59
|
+
# Params:
|
60
|
+
# +image_file_name+:: a filename of a image to look for in markdown
|
61
|
+
# +markdown+:: text of a markdown post
|
62
|
+
def get_image_filename_from_markdown(image_file_name, markdown)
|
63
|
+
document = Kramdown::Document.new(markdown)
|
64
|
+
document_descendants = []
|
65
|
+
|
66
|
+
get_document_descendants(document.root, document_descendants)
|
67
|
+
all_img_tags = document_descendants.select { |x| x.type == :img }
|
68
|
+
matching_image_tag = all_img_tags.find { |x| get_filename_for_image_tag(x).tr(' ', '_') == image_file_name }
|
69
|
+
|
70
|
+
return get_filename_for_image_tag(matching_image_tag) if matching_image_tag
|
71
|
+
|
72
|
+
nil
|
73
|
+
end
|
74
|
+
|
75
|
+
##
|
76
|
+
# This method returns an array of all image paths given some markdown
|
77
|
+
#
|
78
|
+
# Params:
|
79
|
+
# +markdown+:: text of a markdown post
|
80
|
+
def get_all_image_paths(markdown)
|
81
|
+
document = Kramdown::Document.new(markdown)
|
82
|
+
document_descendants = []
|
83
|
+
|
84
|
+
get_document_descendants(document.root, document_descendants)
|
85
|
+
all_img_tags = document_descendants.select { |x| x.type == :img }
|
86
|
+
|
87
|
+
result = all_img_tags.map do |img_tag|
|
88
|
+
img_tag.attr['src'][1..-1] if img_tag.attr['src'] !~ URI::DEFAULT_PARSER.make_regexp
|
89
|
+
end
|
90
|
+
|
91
|
+
result.compact
|
92
|
+
end
|
93
|
+
|
94
|
+
##
|
95
|
+
# This method takes parameters for a given post and formats them
|
96
|
+
# as a valid jekyll post for a Jekyll website
|
97
|
+
#
|
98
|
+
# Params:
|
99
|
+
# +text+:: the markdown contents of the post
|
100
|
+
# +author+:: the author of the post
|
101
|
+
# +title+:: the title of the post
|
102
|
+
# +tags+:: tags specific to the post
|
103
|
+
# +overlay+:: the overlay color of the post
|
104
|
+
# +hero+:: a link to an optional background image for a post
|
105
|
+
def create_jekyll_post_text(text, author, title, tags, overlay, hero)
|
106
|
+
header_converted_text = fix_header_syntax(text)
|
107
|
+
header_converted_text = add_line_break_to_markdown_if_necessary(header_converted_text)
|
108
|
+
|
109
|
+
parsed_tags = parse_tags(tags)
|
110
|
+
|
111
|
+
tag_section = %(tags:
|
112
|
+
#{parsed_tags})
|
113
|
+
|
114
|
+
lead_break_section = "{: .lead}\r\n<!–-break-–>"
|
115
|
+
|
116
|
+
hero_to_use = hero
|
117
|
+
hero_to_use = DEFAULT_HERO if hero_to_use.empty?
|
118
|
+
result = %(---
|
119
|
+
layout: post
|
120
|
+
title: #{title}
|
121
|
+
author: #{author}\r\n)
|
122
|
+
|
123
|
+
result += "#{tag_section}\r\n" unless parsed_tags.empty?
|
124
|
+
result += %(hero: #{hero_to_use}
|
125
|
+
overlay: #{overlay.downcase}
|
126
|
+
published: true
|
127
|
+
---
|
128
|
+
#{lead_break_section}
|
129
|
+
#{header_converted_text})
|
130
|
+
|
131
|
+
result
|
132
|
+
end
|
133
|
+
|
134
|
+
private
|
135
|
+
|
136
|
+
def parse_tags(tags)
|
137
|
+
tag_array = tags.split(',')
|
138
|
+
result = ''
|
139
|
+
tag_array.each do |tag|
|
140
|
+
result += " - #{tag.strip}"
|
141
|
+
result += "\r\n" if tag != tag_array.last
|
142
|
+
end
|
143
|
+
result
|
144
|
+
end
|
145
|
+
|
146
|
+
def fix_header_syntax(text)
|
147
|
+
document = Kramdown::Document.new(text)
|
148
|
+
header_elements = document.root.children.select { |x| x.type == :header }
|
149
|
+
lines = text.split("\n")
|
150
|
+
lines = lines.map do |line|
|
151
|
+
if header_elements.any? { |x| line.include? x.options[:raw_text] }
|
152
|
+
# This regex matches the line into 2 groups with the first group being the repeating #
|
153
|
+
# characters and the beginning of the string and the second group being the rest of the string
|
154
|
+
line_match = line.match(/(#*)(.*)/)
|
155
|
+
line = "#{line_match.captures.first} #{line_match.captures.last.strip}"
|
156
|
+
else
|
157
|
+
line.delete("\r\n")
|
158
|
+
end
|
159
|
+
end
|
160
|
+
lines.join("\r\n")
|
161
|
+
end
|
162
|
+
|
163
|
+
def get_document_descendants(current_element, result)
|
164
|
+
current_element.children.each do |element|
|
165
|
+
result << element
|
166
|
+
get_document_descendants(element, result)
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
def get_filename_for_image_tag(image_el)
|
171
|
+
File.basename(image_el.attr['src'])
|
172
|
+
end
|
173
|
+
|
174
|
+
def add_line_break_to_markdown_if_necessary(markdown)
|
175
|
+
lines = markdown.split("\n")
|
176
|
+
# The regular expression in the if statement looks for a markdown reference to a link like
|
177
|
+
# [logo]: https://ieeextreme.org/wp-content/uploads/2019/05/Xtreme_colour-e1557478323964.png
|
178
|
+
# If a post starts with that reference in jekyll followed by an image using that reference
|
179
|
+
# the line below will be interperted as a paragraph tag instead of an image tag. To fix that
|
180
|
+
# we add a line break to the start of the markdown.
|
181
|
+
return "\r\n#{markdown}" if lines.first&.match?(/\[(.*)\]: (.*)/)
|
182
|
+
|
183
|
+
markdown
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Services
|
4
|
+
##
|
5
|
+
# The base class for service classes responsible for performing operations on posts
|
6
|
+
class BasePostService
|
7
|
+
def initialize(repo_name, access_token)
|
8
|
+
@github_service = GithubService.new(repo_name, access_token)
|
9
|
+
@kramdown_service = KramdownService.new
|
10
|
+
end
|
11
|
+
|
12
|
+
protected
|
13
|
+
|
14
|
+
def create_new_tree(post_markdown, post_title, post_file_path, sha_base_tree)
|
15
|
+
file_information = [create_blob_for_post(post_markdown, post_title, post_file_path)]
|
16
|
+
create_image_blobs(post_markdown, file_information)
|
17
|
+
@github_service.create_new_tree_with_blobs(file_information, sha_base_tree)
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def create_blob_for_post(post_markdown, _post_title, post_file_path)
|
23
|
+
blob_sha = @github_service.create_text_blob(post_markdown)
|
24
|
+
{ path: post_file_path, blob_sha: blob_sha }
|
25
|
+
end
|
26
|
+
|
27
|
+
def create_image_blobs(post_markdown, current_file_information)
|
28
|
+
PostImageManager.instance.uploaders.each do |uploader|
|
29
|
+
# This check prevents against images that have been removed from the markdown
|
30
|
+
markdown_file_name = @kramdown_service.get_image_filename_from_markdown(uploader.filename, post_markdown)
|
31
|
+
next unless markdown_file_name
|
32
|
+
|
33
|
+
# This line uses .file.file since the first .file returns a carrierware object
|
34
|
+
File.open(uploader.post_image.file.file, 'rb') do |file|
|
35
|
+
base_64_encoded_image = Base64.encode64(file.read)
|
36
|
+
image_blob_sha = @github_service.create_base64_encoded_blob(base_64_encoded_image)
|
37
|
+
current_file_information << { path: "assets/img/#{markdown_file_name}", blob_sha: image_blob_sha }
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative './base_post_service'
|
4
|
+
require_relative '../github_service'
|
5
|
+
|
6
|
+
module Services
|
7
|
+
##
|
8
|
+
# This class is responsible for creating posts on a Jekyll website
|
9
|
+
class PostCreationService < BasePostService
|
10
|
+
def initialize(repo_name, access_token)
|
11
|
+
super(repo_name, access_token)
|
12
|
+
end
|
13
|
+
|
14
|
+
##
|
15
|
+
# This method submits a new post to GitHub by checking out a new branch for the post,
|
16
|
+
# if the branch already doesn't exist. Commiting and pushing the markdown and any photos
|
17
|
+
# attached to the post to the branch. And then finally opening a pull request into master
|
18
|
+
# for the new post.
|
19
|
+
#
|
20
|
+
# Params
|
21
|
+
# +oauth_token+::a user's oauth access token
|
22
|
+
# +post_markdown+:: the markdown contents of a post
|
23
|
+
# +pull_request_body+::an optional pull request body for the post, it will be blank if nothing is provided
|
24
|
+
# +reviewers+:: an optional list of reviewers for the post PR
|
25
|
+
def create_post(post_markdown, post_title, pull_request_body = '', reviewers = [])
|
26
|
+
# This ref_name variable represents the branch name
|
27
|
+
# for creating a post. At the end we strip out all of the whitespace in
|
28
|
+
# the post_title to create a valid branch name
|
29
|
+
branch_name = "createPost#{post_title.gsub(/\s+/, '')}"
|
30
|
+
ref_name = "heads/#{branch_name}"
|
31
|
+
|
32
|
+
master_head_sha = @github_service.get_master_head_sha
|
33
|
+
sha_base_tree = @github_service.get_base_tree_for_branch(master_head_sha)
|
34
|
+
|
35
|
+
@github_service.create_ref_if_necessary(ref_name, master_head_sha)
|
36
|
+
|
37
|
+
new_post_path = create_new_filepath_for_post(post_title)
|
38
|
+
new_tree_sha = create_new_tree(post_markdown, post_title, new_post_path, sha_base_tree)
|
39
|
+
|
40
|
+
@github_service.commit_and_push_to_repo("Created post #{post_title}",
|
41
|
+
new_tree_sha, master_head_sha, ref_name)
|
42
|
+
@github_service.create_pull_request(branch_name, 'master', "Created Post #{post_title}",
|
43
|
+
pull_request_body,
|
44
|
+
reviewers)
|
45
|
+
|
46
|
+
PostImageManager.instance.clear
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def create_new_filepath_for_post(post_title)
|
52
|
+
"_posts/#{DateTime.now.strftime('%Y-%m-%d')}-#{post_title.gsub(/\s+/, '')}.md"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative './base_post_service'
|
4
|
+
require_relative '../github_service'
|
5
|
+
|
6
|
+
module Services
|
7
|
+
##
|
8
|
+
# This class is responsible for editing posts on a Jekyll website
|
9
|
+
class PostEditingService < BasePostService
|
10
|
+
def initialize(repo_name, access_token)
|
11
|
+
super(repo_name, access_token)
|
12
|
+
end
|
13
|
+
|
14
|
+
##
|
15
|
+
# This method submits changes to an existing post to GitHub by checking out a new branch for the post,
|
16
|
+
# if the branch already doesn't exist. Commiting and pushing the markdown changes and any added photos
|
17
|
+
# for the existing post to the branch. And the finally opening a pull request into master for the new post.
|
18
|
+
#
|
19
|
+
# Params
|
20
|
+
# +post_markdown+::the modified markdown to submit
|
21
|
+
# +post_title+::the title for the existing post
|
22
|
+
# +existing_post_file_path+::the file path to the existing post on GitHub
|
23
|
+
# +pull_request_body+::an optional pull request body for the post, it will be blank if nothing is provided
|
24
|
+
# +reviewers+:: an optional list of reviewers for the post PR
|
25
|
+
def edit_post(post_markdown, post_title, existing_post_file_path, pull_request_body = '', reviewers = [])
|
26
|
+
# This ref_name variable represents the branch name
|
27
|
+
# for editing a post. At the end we strip out all of the whitespace in
|
28
|
+
# the post_title to create a valid branch name
|
29
|
+
branch_name = "editPost#{post_title.gsub(/\s+/, '')}"
|
30
|
+
ref_name = "heads/#{branch_name}"
|
31
|
+
|
32
|
+
master_head_sha = @github_service.get_master_head_sha
|
33
|
+
sha_base_tree = @github_service.get_base_tree_for_branch(master_head_sha)
|
34
|
+
|
35
|
+
@github_service.create_ref_if_necessary(ref_name, master_head_sha)
|
36
|
+
new_tree_sha = create_new_tree(post_markdown, post_title, existing_post_file_path, sha_base_tree)
|
37
|
+
|
38
|
+
@github_service.commit_and_push_to_repo("Edited post #{post_title}", new_tree_sha, master_head_sha, ref_name)
|
39
|
+
@github_service.create_pull_request(branch_name, 'master', "Edited Post #{post_title}",
|
40
|
+
pull_request_body,
|
41
|
+
reviewers)
|
42
|
+
|
43
|
+
PostImageManager.instance.clear
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative './base_post_service'
|
4
|
+
require_relative '../github_service'
|
5
|
+
|
6
|
+
module Services
|
7
|
+
##
|
8
|
+
# This class is responsible for editing posts that are in PR on a Jekyll website
|
9
|
+
class PostPullRequestEditingService < BasePostService
|
10
|
+
def initialize(repo_name, access_token)
|
11
|
+
super(repo_name, access_token)
|
12
|
+
end
|
13
|
+
|
14
|
+
##
|
15
|
+
# This method submits changes to a post that is already in PR, commiting and pushing the markdown changes
|
16
|
+
# and any added photos to the branch. Since the post is in PR these changes will be a PR updated to the given branch
|
17
|
+
#
|
18
|
+
# Params:
|
19
|
+
# +post_markdown+::the modified markdown to submit
|
20
|
+
# +post_title+::the title for the existing post
|
21
|
+
# +existing_post_file_path+::the file path to the existing post on GitHub
|
22
|
+
# +ref+::the ref to update
|
23
|
+
def edit_post_in_pr(post_markdown, post_title, existing_post_file_path, ref)
|
24
|
+
ref_name = @github_service.get_ref_name_by_sha(ref)
|
25
|
+
sha_base_tree = @github_service.get_base_tree_for_branch(ref)
|
26
|
+
|
27
|
+
new_tree_sha = create_new_tree(post_markdown, post_title, existing_post_file_path, sha_base_tree)
|
28
|
+
@github_service.commit_and_push_to_repo("Edited post #{post_title}", new_tree_sha, ref, ref_name)
|
29
|
+
|
30
|
+
PostImageManager.instance.clear
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'carrierwave'
|
4
|
+
##
|
5
|
+
# The file uploader class for uploading images to a Jekyll website post
|
6
|
+
class PostImageUploader < CarrierWave::Uploader::Base
|
7
|
+
include CarrierWave::MiniMagick
|
8
|
+
# These constants represent the maximum width and height an uploaded can be for the post preview
|
9
|
+
# and for actually appearing on a Jekyll website. These numbers were initially determined by testing
|
10
|
+
# with a 1920x1080 image. If you find a reason to change these numbers please document the reason
|
11
|
+
# below
|
12
|
+
PREVIEW_LIMIT = [800, 800].freeze
|
13
|
+
POST_LIMIT = [800, 700].freeze
|
14
|
+
|
15
|
+
storage :file
|
16
|
+
|
17
|
+
##
|
18
|
+
# Limits only images to be uploaded to an SSE website post
|
19
|
+
def extension_whitelist
|
20
|
+
%w[jpg jpeg gif png]
|
21
|
+
end
|
22
|
+
|
23
|
+
def size_range
|
24
|
+
# 5 mb is a very large photo it will probably never be reached. But
|
25
|
+
# this will prevent people from passing off very large files as an image.
|
26
|
+
# If you change this limit please document the reason for changing it below
|
27
|
+
(1..5).step { |x| bytes_to_megabytes x }
|
28
|
+
end
|
29
|
+
|
30
|
+
version :preview do
|
31
|
+
process resize_to_limit: PREVIEW_LIMIT
|
32
|
+
end
|
33
|
+
|
34
|
+
version :post_image do
|
35
|
+
process resize_to_limit: POST_LIMIT
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def bytes_to_megabytes(bytes)
|
41
|
+
bytes * (1024.0 * 1024.0)
|
42
|
+
end
|
43
|
+
end
|
metadata
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: jekyll-github-pages-gem
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- MSOE SSE Web Team
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2020-05-12 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description:
|
14
|
+
email:
|
15
|
+
executables: []
|
16
|
+
extensions: []
|
17
|
+
extra_rdoc_files: []
|
18
|
+
files:
|
19
|
+
- Gemfile
|
20
|
+
- Gemfile.lock
|
21
|
+
- README.md
|
22
|
+
- Rakefile
|
23
|
+
- jekyll_github_pages.gemspec
|
24
|
+
- lib/factories/post_factory.rb
|
25
|
+
- lib/jekyll_github_pages.rb
|
26
|
+
- lib/models/post.rb
|
27
|
+
- lib/models/post_image_manager.rb
|
28
|
+
- lib/services/github_service.rb
|
29
|
+
- lib/services/kramdown_service.rb
|
30
|
+
- lib/services/post_services/base_post_service.rb
|
31
|
+
- lib/services/post_services/post_creation_service.rb
|
32
|
+
- lib/services/post_services/post_editing_service.rb
|
33
|
+
- lib/services/post_services/post_pull_request_editing_service.rb
|
34
|
+
- lib/uploaders/post_image_uploader.rb
|
35
|
+
homepage:
|
36
|
+
licenses:
|
37
|
+
- MIT
|
38
|
+
metadata: {}
|
39
|
+
post_install_message:
|
40
|
+
rdoc_options: []
|
41
|
+
require_paths:
|
42
|
+
- lib
|
43
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
49
|
+
requirements:
|
50
|
+
- - ">="
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: '0'
|
53
|
+
requirements: []
|
54
|
+
rubyforge_project:
|
55
|
+
rubygems_version: 2.7.6.2
|
56
|
+
signing_key:
|
57
|
+
specification_version: 4
|
58
|
+
summary: A gem that uses the github API to make edits with a jekyll blog
|
59
|
+
test_files: []
|