jekyll-github-pages-gem 1.0.1 → 1.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.
@@ -41,7 +41,7 @@ end
41
41
 
42
42
  module Services
43
43
  ##
44
- # This class contains all operations with interacting with the kramdown engine
44
+ # This class contains operations related to the kramdown engine
45
45
  class KramdownService
46
46
  DEFAULT_HERO = 'https://source.unsplash.com/collection/145103/'
47
47
  ##
@@ -91,75 +91,8 @@ module Services
91
91
  result.compact
92
92
  end
93
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
94
  private
135
95
 
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
96
  def get_document_descendants(current_element, result)
164
97
  current_element.children.each do |element|
165
98
  result << element
@@ -170,17 +103,5 @@ published: true
170
103
  def get_filename_for_image_tag(image_el)
171
104
  File.basename(image_el.attr['src'])
172
105
  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
106
  end
186
107
  end
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../factories/page_factory'
4
+
5
+ module Services
6
+ ##
7
+ # This class contains all operations related to pages on a Jekyll website
8
+ class PageService < BaseEditingService
9
+ def initialize(repo_name, access_token)
10
+ super(repo_name, access_token)
11
+ @page_factory = Factories::PageFactory.new
12
+ end
13
+
14
+ ##
15
+ # Returns a given page from a Jekyll website from the default branch unless a pull request body
16
+ # is specified. In that case then it will return the page from the source branch of the first open
17
+ # pull request matching the given body
18
+ #
19
+ # Params:
20
+ # +file_path+:: the path to the file in a GitHub repository
21
+ # +pr_body+:: an optional parameter indicating the pull request body of any updates to a given page, defaults to nil
22
+ def get_markdown_page(file_path, pr_body = nil)
23
+ if pr_body
24
+ open_prs = @github_service.get_open_pull_requests_with_body(pr_body)
25
+ unless open_prs.empty?
26
+ pr_files = @github_service.get_pr_files(open_prs[0][:number])
27
+ markdown_file = pr_files.find { |file| file[:filename].end_with?('.md') }
28
+ if markdown_file
29
+ ref = @github_service.get_ref_from_contents_url(markdown_file[:contents_url])
30
+ text_contents = @github_service.get_text_contents_from_file(file_path, ref)
31
+ return @page_factory.create_page(text_contents, ref, open_prs[0][:html_url])
32
+ end
33
+ end
34
+ end
35
+
36
+ text_contents = @github_service.get_text_contents_from_file(file_path)
37
+ @page_factory.create_page(text_contents, nil, nil)
38
+ end
39
+
40
+ ##
41
+ # Saves a given page update by updating the page contents and creating a pull request into master
42
+ # if a ref is not given. Otherwise if a ref is supplied it will update the branch matching the given ref without creating a pull request.
43
+ #
44
+ # Params:
45
+ # +file_path+:: the path to the file in a GitHub repository
46
+ # +page_title+:: the title of the page
47
+ # +ref+::an optional branch indicating the page should be updated on a branch that's not the default branch, defaults to nil
48
+ # +pr_body+::an optional pull request body when updating the page on the default branch, defaults to an empty string
49
+ # +reviewers+::an optional array of reviewers for opening a pull request when updating the page on the default branch, defaults to no reviewers
50
+ def save_page_update(file_path, page_title, file_contents, ref = nil, pr_body = '', reviewers = [])
51
+ if ref
52
+ ref_name = @github_service.get_ref_name_by_sha(ref)
53
+ sha_base_tree = @github_service.get_base_tree_for_branch(ref)
54
+
55
+ new_tree_sha = create_new_tree(file_contents, page_title, file_path, sha_base_tree)
56
+ @github_service.commit_and_push_to_repo("Edited page #{page_title}", new_tree_sha, ref, ref_name)
57
+ nil
58
+ else
59
+ branch_name = "editPage#{page_title.gsub(/\s+/, '')}"
60
+ ref_name = "heads/#{branch_name}"
61
+
62
+ master_head_sha = @github_service.get_master_head_sha
63
+ sha_base_tree = @github_service.get_base_tree_for_branch(master_head_sha)
64
+
65
+ @github_service.create_ref_if_necessary(ref_name, master_head_sha)
66
+ new_tree_sha = create_new_tree(file_contents, page_title, file_path, sha_base_tree)
67
+
68
+ ref_sha = @github_service.commit_and_push_to_repo("Edited page #{page_title}", new_tree_sha, master_head_sha, ref_name)
69
+ pull_request_url = @github_service.create_pull_request(branch_name, 'master', "Edited page #{page_title}",
70
+ pr_body,
71
+ reviewers)
72
+ create_save_page_update_result(ref_sha, pull_request_url)
73
+ end
74
+ end
75
+
76
+ private
77
+
78
+ def create_save_page_update_result(ref_sha, pull_request_url)
79
+ result = Page.new
80
+ result.github_ref = ref_sha
81
+ result.pull_request_url = pull_request_url
82
+ result
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,184 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../factories/post_factory'
4
+
5
+ module Services
6
+ ##
7
+ # This class contains all operations related to posts on a Jekyll website
8
+ class PostService < BaseEditingService
9
+ def initialize(repo_name, access_token)
10
+ super(repo_name, access_token)
11
+ @post_factory = Factories::PostFactory.new
12
+ @kramdown_service = Services::KramdownService.new
13
+ end
14
+
15
+ ##
16
+ # This method fetches all the markdown contents of all the posts on a Jekyll website
17
+ # that have been written and returns a list of models representing a Post.
18
+ def get_all_posts
19
+ result = []
20
+ api_posts = @github_service.get_contents_from_path('_posts')
21
+ api_posts.each do |api_post|
22
+ post_text_contents = @github_service.get_text_contents_from_file(api_post.path)
23
+ post_model = @post_factory.create_post(post_text_contents, api_post.path, nil)
24
+ image_paths = @kramdown_service.get_all_image_paths(post_model.contents)
25
+
26
+ images = []
27
+ image_paths.each do |image_path|
28
+ image_content = @github_service.get_contents_from_path(image_path)
29
+ images << create_post_image(image_path, image_content.content)
30
+ end
31
+
32
+ post_model.images = images
33
+
34
+ result << post_model
35
+ end
36
+ result
37
+ end
38
+
39
+ ##
40
+ # This method fetches all of the posts that have been written but have not been merged into master yet
41
+ #
42
+ # Params
43
+ # +pr_body+::the pr body for the posts in PR
44
+ def get_all_posts_in_pr(pr_body)
45
+ result = []
46
+ pull_requests = @github_service.get_open_pull_requests_with_body(pr_body)
47
+ pull_requests.each do |pull_request|
48
+ pull_request_files = @github_service.get_pr_files(pull_request[:number])
49
+
50
+ post = nil
51
+ images = []
52
+ pull_request_files.each do |pull_request_file|
53
+ ref = @github_service.get_ref_from_contents_url(pull_request_file[:contents_url])
54
+ pr_file_contents = @github_service.get_contents_from_path(pull_request_file[:filename], ref)
55
+
56
+ if pull_request_file[:filename].end_with?('.md')
57
+ post_text_contents = @github_service.get_text_content_from_file(pr_file_contents.path, ref)
58
+ post = @post_factory.create_post(post_text_contents, pr_file_contents.path, ref)
59
+ result << post
60
+ else
61
+ images << create_post_image(pr_file_contents.path, pr_file_contents.content)
62
+ end
63
+ end
64
+
65
+ post.images = images
66
+ end
67
+ result
68
+ end
69
+
70
+ ##
71
+ # This method fetches a single post from a Jekyll website given a post title
72
+ # and returns a Post model
73
+ #
74
+ # Params:
75
+ # +title+:: A title of a Jekyll website post
76
+ # +ref+::a sha for a ref indicating the head of a branch a post is pushed to on the GitHub server
77
+ def get_post_by_title(title, ref)
78
+ result = nil
79
+ result = get_all_posts_in_pr.find { |x| x.title == title } if ref
80
+ result = get_all_posts.find { |x| x.title == title } unless ref
81
+ result&.images&.each { |x| PostImageManager.instance.add_downloaded_image(x) }
82
+ result
83
+ end
84
+
85
+ ##
86
+ # This method submits a new post to GitHub by checking out a new branch for the post,
87
+ # if the branch already doesn't exist. Commiting and pushing the markdown and any photos
88
+ # attached to the post to the branch. And then finally opening a pull request into master
89
+ # for the new post.
90
+ #
91
+ # Params
92
+ # +oauth_token+::a user's oauth access token
93
+ # +post_markdown+:: the markdown contents of a post
94
+ # +pull_request_body+::an optional pull request body for the post, it will be blank if nothing is provided
95
+ # +reviewers+:: an optional list of reviewers for the post PR
96
+ def create_post(post_markdown, post_title, pull_request_body = '', reviewers = [])
97
+ # This ref_name variable represents the branch name
98
+ # for creating a post. At the end we strip out all of the whitespace in
99
+ # the post_title to create a valid branch name
100
+ branch_name = "createPost#{post_title.gsub(/\s+/, '')}"
101
+ ref_name = "heads/#{branch_name}"
102
+
103
+ master_head_sha = @github_service.get_master_head_sha
104
+ sha_base_tree = @github_service.get_base_tree_for_branch(master_head_sha)
105
+
106
+ @github_service.create_ref_if_necessary(ref_name, master_head_sha)
107
+
108
+ new_post_path = create_new_filepath_for_post(post_title)
109
+ new_tree_sha = create_new_tree(post_markdown, post_title, new_post_path, sha_base_tree)
110
+
111
+ @github_service.commit_and_push_to_repo("Created post #{post_title}",
112
+ new_tree_sha, master_head_sha, ref_name)
113
+ @github_service.create_pull_request(branch_name, 'master', "Created Post #{post_title}",
114
+ pull_request_body,
115
+ reviewers)
116
+
117
+ PostImageManager.instance.clear
118
+ end
119
+
120
+ ##
121
+ # This method submits changes to an existing post to GitHub by checking out a new branch for the post,
122
+ # if the branch already doesn't exist. Commiting and pushing the markdown changes and any added photos
123
+ # for the existing post to the branch. And the finally opening a pull request into master for the new post.
124
+ #
125
+ # Params
126
+ # +post_markdown+::the modified markdown to submit
127
+ # +post_title+::the title for the existing post
128
+ # +existing_post_file_path+::the file path to the existing post on GitHub
129
+ # +pull_request_body+::an optional pull request body for the post, it will be blank if nothing is provided
130
+ # +reviewers+:: an optional list of reviewers for the post PR
131
+ def edit_post(post_markdown, post_title, existing_post_file_path, pull_request_body = '', reviewers = [])
132
+ # This ref_name variable represents the branch name
133
+ # for editing a post. At the end we strip out all of the whitespace in
134
+ # the post_title to create a valid branch name
135
+ branch_name = "editPost#{post_title.gsub(/\s+/, '')}"
136
+ ref_name = "heads/#{branch_name}"
137
+
138
+ master_head_sha = @github_service.get_master_head_sha
139
+ sha_base_tree = @github_service.get_base_tree_for_branch(master_head_sha)
140
+
141
+ @github_service.create_ref_if_necessary(ref_name, master_head_sha)
142
+ new_tree_sha = create_new_tree(post_markdown, post_title, existing_post_file_path, sha_base_tree)
143
+
144
+ @github_service.commit_and_push_to_repo("Edited post #{post_title}", new_tree_sha, master_head_sha, ref_name)
145
+ @github_service.create_pull_request(branch_name, 'master', "Edited Post #{post_title}",
146
+ pull_request_body,
147
+ reviewers)
148
+
149
+ PostImageManager.instance.clear
150
+ end
151
+
152
+ ##
153
+ # This method submits changes to a post that is already in PR, commiting and pushing the markdown changes
154
+ # and any added photos to the branch. Since the post is in PR these changes will be a PR updated to the given branch
155
+ #
156
+ # Params:
157
+ # +post_markdown+::the modified markdown to submit
158
+ # +post_title+::the title for the existing post
159
+ # +existing_post_file_path+::the file path to the existing post on GitHub
160
+ # +ref+::the ref to update
161
+ def edit_post_in_pr(post_markdown, post_title, existing_post_file_path, ref)
162
+ ref_name = @github_service.get_ref_name_by_sha(ref)
163
+ sha_base_tree = @github_service.get_base_tree_for_branch(ref)
164
+
165
+ new_tree_sha = create_new_tree(post_markdown, post_title, existing_post_file_path, sha_base_tree)
166
+ @github_service.commit_and_push_to_repo("Edited post #{post_title}", new_tree_sha, ref, ref_name)
167
+
168
+ PostImageManager.instance.clear
169
+ end
170
+
171
+ private
172
+
173
+ def create_new_filepath_for_post(post_title)
174
+ "_posts/#{DateTime.now.strftime('%Y-%m-%d')}-#{post_title.gsub(/\s+/, '')}.md"
175
+ end
176
+
177
+ def create_post_image(filename, contents)
178
+ result = PostImage.new
179
+ result.filename = filename
180
+ result.contents = contents
181
+ result
182
+ end
183
+ end
184
+ end
metadata CHANGED
@@ -1,15 +1,63 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jekyll-github-pages-gem
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - MSOE SSE Web Team
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-05-31 00:00:00.000000000 Z
12
- dependencies: []
11
+ date: 2020-08-24 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: carrierwave
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 2.0.0.rc
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '3.0'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: 2.0.0.rc
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '3.0'
33
+ - !ruby/object:Gem::Dependency
34
+ name: kramdown
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: 2.3.0
40
+ type: :runtime
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: 2.3.0
47
+ - !ruby/object:Gem::Dependency
48
+ name: octokit
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '4.18'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '4.18'
13
61
  description:
14
62
  email:
15
63
  executables: []
@@ -21,16 +69,18 @@ files:
21
69
  - README.md
22
70
  - Rakefile
23
71
  - jekyll_github_pages.gemspec
72
+ - lib/factories/base_factory.rb
73
+ - lib/factories/page_factory.rb
24
74
  - lib/factories/post_factory.rb
25
75
  - lib/jekyll_github_pages.rb
76
+ - lib/models/page.rb
26
77
  - lib/models/post.rb
27
78
  - lib/models/post_image_manager.rb
79
+ - lib/services/base_editing_service.rb
28
80
  - lib/services/github_service.rb
29
81
  - 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
82
+ - lib/services/page_service.rb
83
+ - lib/services/post_service.rb
34
84
  - lib/uploaders/post_image_uploader.rb
35
85
  homepage:
36
86
  licenses:
@@ -44,7 +94,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
44
94
  requirements:
45
95
  - - ">="
46
96
  - !ruby/object:Gem::Version
47
- version: '0'
97
+ version: 2.5.1
48
98
  required_rubygems_version: !ruby/object:Gem::Requirement
49
99
  requirements:
50
100
  - - ">="