github-to-canvas 0.1.5 → 0.1.7.pre

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b18946099c8b4fd23e1c2230f71fac458f932079fd22ada5297732358fec4d0e
4
- data.tar.gz: '092e1b7854f2b4c4026f0713599d423d8eac6431ae16e4f9372c1a00ebb9775c'
3
+ metadata.gz: 53c9c96308fae1d78f27bc68e80fee55baf2ff23d381866edfd1d114b30601ec
4
+ data.tar.gz: bf7570a5be4657e102659454295beb72023864ceb20562b51858fa094997b5f7
5
5
  SHA512:
6
- metadata.gz: d11be9f366fc3a457a671669a57802d6a1a8cc8ff3b0a7e9fa3ee10b4b8b91334cbaa336d39c1e3057c41e787619716d76df3e8523d918393cbb1b6fa9737549
7
- data.tar.gz: 85d91f81000c82d55cb45e02f31c9aa3b2e241c785cb58366f5fbef99b72c7ce76e7e9d70f101cedb7f54c5082b2061926e0453cd8a162227cdba78f96c54e71
6
+ metadata.gz: adbf272b0121b81582d6520bc0c3881980276ede161cb97515d1792563cb29a603c93e7bf35790db1eacc89fb471b68127dccaf24fa43f3205cd758fa53739c2
7
+ data.tar.gz: 45182fbe2c428468ed967650a5e42ad496af4fa8dca236b61ec52ef9aa0ace3c209ece9a52eadd46849252a7dd6f9fa7c047a5017057bb96ca5143ee3155784a
@@ -108,6 +108,10 @@ OptionParser.new do |opts|
108
108
  "Adds additional Flatiron School HTML after markdown conversion") do |f|
109
109
  options[:fis] = true
110
110
  end
111
+ opts.on("-g", "--git-links",
112
+ "Adds additional GitHub after markdown conversion") do |f|
113
+ options[:git_links] = true
114
+ end
111
115
  opts.on("--aaq",
112
116
  "Adds AAQ flag to HTML header appended with --fis-links") do |aaq|
113
117
  options[:aaq] = aaq
@@ -188,6 +192,15 @@ OptionParser.new do |opts|
188
192
  "Escapes all HTML included in source markdown by replacing '<' and '>' with HTML charset values") do |html|
189
193
  options[:contains_html] = html
190
194
  end
195
+ opts.on("--canvas-to-canvas COURSE",
196
+ "Copies an existing Canvas lesson into another Canvas lesson") do |canvas_to_canvas|
197
+ options[:canvas_to_canvas] = canvas_to_canvas
198
+ end
199
+ opts.on("--build-from-csv CSV",
200
+ "Build a course usin a CSV of lesson repos, names, modules, and types") do |csv_build|
201
+ options[:csv_build] = csv_build
202
+ end
203
+
191
204
 
192
205
  end.parse!
193
206
 
@@ -202,6 +215,16 @@ if options[:read_from_canvas]
202
215
  abort
203
216
  end
204
217
 
218
+ if options[:canvas_to_canvas]
219
+ GithubToCanvas.new(mode: 'canvas_copy',
220
+ filepath: options[:canvas_to_canvas],
221
+ course_id: options[:course_id],
222
+ type: options[:type],
223
+ id: options[:id]
224
+ )
225
+ abort
226
+ end
227
+
205
228
  if options[:read_from_github]
206
229
  GithubToCanvas.new(mode: 'github_read',
207
230
  filepath: options[:read_from_github],
@@ -267,13 +290,29 @@ if options[:csv]
267
290
  abort
268
291
  end
269
292
 
293
+ if options[:csv_build]
294
+ GithubToCanvas.new(mode: 'csv_build',
295
+ file_to_convert: options[:csv_build],
296
+ course_id: options[:course_id],
297
+ fis_links: !!options[:fis],
298
+ remove_header_and_footer: !!options[:remove_header_and_footer],
299
+ aaq: !!options[:aaq],
300
+ forkable: !!options[:forkable],
301
+ branch: options[:branch],
302
+ contains_html: options[:contains_html],
303
+ git_links: !!options[:git_links])
304
+ abort
305
+ end
306
+
270
307
  if options[:build_course]
271
308
  GithubToCanvas.new(mode: 'build_course',
272
309
  file_to_convert: options[:build_course],
273
310
  fis_links: !!options[:fis],
274
311
  remove_header_and_footer: !!options[:remove_header_and_footer],
275
312
  aaq: !!options[:aaq],
276
- forkable: !!options[:forkable])
313
+ forkable: !!options[:forkable],
314
+ contains_html: options[:contains_html],
315
+ git_links: !!options[:git_links])
277
316
  abort
278
317
  end
279
318
 
@@ -286,7 +325,8 @@ if options[:add_to_course]
286
325
  remove_header_and_footer: !!options[:remove_header_and_footer],
287
326
  forkable: !!options[:forkable],
288
327
  aaq: !!options[:aaq],
289
- contains_html: options[:contains_html])
328
+ contains_html: options[:contains_html],
329
+ git_links: !!options[:git_links])
290
330
  else
291
331
  puts '--course required'
292
332
  end
@@ -300,7 +340,8 @@ if options[:update_course_lessons]
300
340
  remove_header_and_footer: !!options[:remove_header_and_footer],
301
341
  forkable: !!options[:forkable],
302
342
  aaq: !!options[:aaq],
303
- contains_html: options[:contains_html])
343
+ contains_html: options[:contains_html],
344
+ git_links: !!options[:git_links])
304
345
  abort
305
346
  end
306
347
 
@@ -360,6 +401,7 @@ if options[:create_lesson]
360
401
  type: options[:type],
361
402
  save_to_github: !!options[:save_to_github],
362
403
  fis_links: !!options[:fis],
404
+ git_links: !!options[:git_links],
363
405
  remove_header_and_footer: !!options[:remove_header_and_footer],
364
406
  only_update_content: !!options[:only_content],
365
407
  forkable: !!options[:forkable],
@@ -377,7 +419,8 @@ if options[:align]
377
419
  name: options[:name],
378
420
  type: options[:type],
379
421
  save_to_github: !!options[:save_to_github],
380
- fis_links: !!options[:fis],
422
+ fis_links: !!options[:fis],
423
+ git_links: !!options[:git_links],
381
424
  remove_header_and_footer: !!options[:remove_header_and_footer],
382
425
  only_update_content: !!options[:only_content],
383
426
  forkable: !!options[:forkable],
@@ -1,4 +1,5 @@
1
1
  require 'byebug'
2
+ require 'csv'
2
3
  require_relative './github-to-canvas/create_canvas_lesson'
3
4
  require_relative './github-to-canvas/update_canvas_lesson'
4
5
  require_relative './github-to-canvas/canvas_dotfile'
@@ -26,6 +27,8 @@ class GithubToCanvas
26
27
  CanvasInterface.csv(options[:file_to_convert])
27
28
  when 'canvas_read'
28
29
  puts CanvasInterface.read_lesson(options[:filepath])
30
+ when 'canvas_copy'
31
+ CanvasInterface.copy_lesson(options)
29
32
  when 'github_read'
30
33
  html = RepositoryConverter.remote_file_conversion(options)
31
34
  puts RepositoryConverter.adjust_converted_html(options, html)
@@ -43,16 +46,25 @@ class GithubToCanvas
43
46
  CanvasInterface.update_all_related_lessons(options, name, html)
44
47
 
45
48
  when 'github_create'
49
+ if (!options[:branch])
50
+ options[:branch] = 'master'
51
+ end
46
52
  html = RepositoryConverter.remote_file_conversion(options)
47
- name = options[:name] ? options[:name] : RepositoryInterface.get_name(options[:filepath], html)
48
- html = RepositoryConverter.adjust_converted_html(options, html)
49
53
 
54
+ html = RepositoryConverter.adjust_converted_html(options, html)
55
+ name = options[:name] ? options[:name] : RepositoryInterface.get_name(options[:filepath], html)
56
+ byebug
57
+ puts name
50
58
  response = CanvasInterface.create_lesson(options, name, html)
51
59
 
52
60
  puts "Canvas lesson created. Lesson available at #{response['html_url']}"
53
61
  when 'github_align'
62
+ if (!options[:branch])
63
+ options[:branch] = 'master'
64
+ end
54
65
  html = RepositoryConverter.remote_file_conversion(options)
55
66
  name = options[:name] ? options[:name] : RepositoryInterface.get_name(options[:filepath], html)
67
+
56
68
  html = RepositoryConverter.adjust_converted_html(options, html)
57
69
  response = CanvasInterface.update_existing_lesson(options, name, html)
58
70
  puts "Canvas lesson updated. Lesson available at #{response['html_url']}"
@@ -152,6 +164,60 @@ class GithubToCanvas
152
164
  end
153
165
  }
154
166
  }
167
+ when 'csv_build'
168
+ if !options[:course_id]
169
+ course_info = {
170
+ name: "CSV Build Test",
171
+ course_code: "CSV-TEST"
172
+ }
173
+ created_course_info = CanvasInterface.create_course(course_info)
174
+ puts "Course created - #{created_course_info["id"]}"
175
+ puts "Make sure to add yourself as a teacher to this course before continuing, then press Enter/Return"
176
+ input = gets
177
+ options[:course_id] = created_course_info["id"]
178
+ else
179
+ puts "Adding to course #{options[:course_id]}"
180
+ end
181
+
182
+ csv_data = CSV.read(options[:file_to_convert])
183
+ created_module_info = {
184
+ "id" => "",
185
+ "name" => ""
186
+ }
187
+
188
+ csv_data.each { |lesson|
189
+ # lesson[0] == repo
190
+ # lesson[1] == name
191
+ # lesson[2] == module
192
+ # lesson[3] == type
193
+ # lesson[4] == yes/no contains HTML
194
+ module_info = {
195
+ name: lesson[2]
196
+ }
197
+ if created_module_info["name"] != module_info[:name]
198
+ created_module_info = CanvasInterface.create_module(options[:course_id], module_info)
199
+ puts "New module created - #{created_module_info["id"]} - #{created_module_info["name"]}"
200
+ end
201
+
202
+ options[:filepath] = lesson[0]
203
+ options[:name] = lesson[1]
204
+ options[:type] = lesson[3]
205
+ options[:branch] = "master" if !options[:branch]
206
+ if !options[:contains_html]
207
+ options[:contains_html] = (lesson[4] == "yes" || lesson[4] == "Yes") ? true : false
208
+ end
209
+
210
+
211
+ html = RepositoryConverter.remote_file_conversion(options)
212
+ html = RepositoryConverter.adjust_converted_html(options, html)
213
+ created_lesson_info = CanvasInterface.create_lesson(options, lesson[1], html)
214
+ created_lesson_info["page_url"] = created_lesson_info["url"] if !created_lesson_info["page_url"]
215
+ created_lesson_info["id"] = created_lesson_info["page_url"] if !created_lesson_info["id"]
216
+ created_lesson_info["type"] = options[:type]
217
+ puts "Creating lesson - #{options[:name]}"
218
+ response = CanvasInterface.add_to_module(options[:course_id], created_module_info, created_lesson_info)
219
+
220
+ }
155
221
  else
156
222
  puts VERSION
157
223
  end
@@ -51,21 +51,21 @@ class CanvasInterface
51
51
  # POST /api/v1/courses/:course_id/modules/:module_id/items
52
52
  url = "#{ENV['CANVAS_API_PATH']}/courses/#{course_id}/modules/#{module_info["id"]}/items"
53
53
 
54
- if lesson_info["type"] == "Page"
54
+ if lesson_info["type"] == "Page" || lesson_info["type"] == "page"
55
55
  payload = {
56
- 'module_item[title]' => lesson_info["title"],
57
- 'module_item[type]' => lesson_info["type"],
58
- 'module_item[indent]' => 0,
59
- 'module_item[page_url]' => lesson_info["id"],
60
- 'module_item[completion_requirement][type]' => 'must_view'
61
- }
56
+ 'module_item[title]' => lesson_info["title"],
57
+ 'module_item[type]' => lesson_info["type"].capitalize,
58
+ 'module_item[indent]' => 0,
59
+ 'module_item[page_url]' => lesson_info["id"],
60
+ 'module_item[completion_requirement][type]' => 'must_view'
61
+ }
62
62
  elsif lesson_info["type"] == "Quiz"
63
63
  puts "Quiz needs to be added manually - #{lesson_info['title']} - lesson_info["
64
64
  else
65
65
 
66
66
  payload = {
67
67
  'module_item[title]' => lesson_info["title"],
68
- 'module_item[type]' => lesson_info["type"],
68
+ 'module_item[type]' => lesson_info["type"].capitalize,
69
69
  'module_item[indent]' => 1,
70
70
  'module_item[content_id]' => lesson_info["id"],
71
71
  'module_item[completion_requirement][type]' => 'must_submit'
@@ -74,6 +74,8 @@ class CanvasInterface
74
74
  begin
75
75
  response = RestClient.post(url, payload, self.headers)
76
76
  rescue
77
+ byebug
78
+
77
79
  puts "Something went wrong while adding lesson #{lesson_info["id"]} to module #{module_info["id"]} in course #{course_id}" if lesson_info["type"] == "Assignment"
78
80
  puts "Something went wrong while adding lesson #{lesson_info["page_url"]} to module #{module_info["id"]} in course #{course_id}" if lesson_info["type"] == "Page"
79
81
  abort
@@ -340,8 +342,37 @@ class CanvasInterface
340
342
  puts course_info.to_yaml
341
343
  end
342
344
 
343
-
345
+ def self.copy_lesson(options)
346
+ types = ["page", "assignment", "quiz", "discussion"]
347
+ url = options[:filepath]
348
+ type = types.find {|type| url.match(type)}
349
+ options[:type] = type
350
+ if !url.include?(ENV['CANVAS_API_PATH'])
351
+ url = url.sub(/^.*\/\/.*?\//,"#{ENV['CANVAS_API_PATH']}/")
352
+ end
353
+
354
+ response = RestClient.get(url, headers={
355
+ "Authorization" => "Bearer #{ENV['CANVAS_API_KEY']}"
356
+ })
344
357
 
358
+ lesson_info = JSON.parse(response)
359
+ lesson_info = lesson_info.slice("title",
360
+ "name",
361
+ "description",
362
+ "body",
363
+ "message",
364
+ "shuffle_answers",
365
+ "allowed_attempts",
366
+ "question_count"
367
+ )
368
+ if options[:type] == "page"
369
+ self.update_existing_lesson(options, lesson_info["title"], lesson_info["body"])
370
+ else
371
+ self.update_existing_lesson(options, lesson_info["name"], lesson_info["description"])
372
+ end
373
+
374
+
375
+ end
345
376
 
346
377
  def self.build_payload(options, name, html)
347
378
  if options[:only_update_content]
@@ -66,8 +66,7 @@ class GithubInterface
66
66
  puts 'Error reading ' + url
67
67
  end
68
68
  end
69
-
70
-
69
+ response.body
71
70
  end
72
71
 
73
72
  def self.save_to_github(filepath, branch)
@@ -27,9 +27,15 @@ class RepositoryConverter
27
27
  markdown = GithubInterface.read_remote(options[:filepath])
28
28
  raw_remote_url = self.set_raw_image_remote_url(options[:filepath])
29
29
  if options[:contains_html]
30
- puts "Contains HTML"
31
- puts options[:contains_html]
32
- markdown = self.escape_existing_html(markdown)
30
+ begin
31
+ markdown = self.escape_existing_html(markdown)
32
+ rescue
33
+ puts "Error reading remote markdown"
34
+ abort
35
+ end
36
+ end
37
+ if (!options[:branch])
38
+ options[:branch] = 'master'
33
39
  end
34
40
  markdown = self.fix_local_images(options, markdown, raw_remote_url)
35
41
  html = self.convert_to_html(markdown)
@@ -37,9 +43,10 @@ class RepositoryConverter
37
43
  end
38
44
 
39
45
  def self.convert_to_html(markdown)
40
- redcarpet = Redcarpet::Markdown.new(CustomRender, options={tables: true, autolink: true, fenced_code_blocks: true})
46
+ renderer = CustomRender.new(escape_html: true, prettify: true, hard_wrap: true)
47
+ redcarpet = Redcarpet::Markdown.new(CustomRender, options={tables: true, autolink: true, fenced_code_blocks: true, disable_indented_code_blocks: true})
41
48
  html = redcarpet.render(markdown)
42
- self.remove_line_breaks(html)
49
+ # self.remove_line_breaks(html)
43
50
  end
44
51
 
45
52
  def self.adjust_converted_html(options, html)
@@ -48,7 +55,7 @@ class RepositoryConverter
48
55
  html = self.remove_header_and_footer(html)
49
56
  end
50
57
 
51
- if options[:fis_links]
58
+ if options[:fis_links] || options[:git_links]
52
59
  html = self.add_fis_links(options, html)
53
60
  end
54
61
 
@@ -60,8 +67,31 @@ class RepositoryConverter
60
67
  end
61
68
 
62
69
  def self.fix_escaped_inline_html_code(html)
63
- html = html.gsub("<code>&amp;lt;", "<code>&lt;")
70
+
71
+ # stops HTML/JSX code blocks from rendering as HTML in Canvas
64
72
  html = html.gsub("&amp;gt;</code>", "&gt;</code>")
73
+ html = html.gsub("&amp;gt;</code>", "&gt;</code>")
74
+
75
+ # fixes < and > code snippets
76
+ html = html.gsub("&amp;lt;", "&lt;")
77
+ html = html.gsub("&amp;gt;", "&gt;")
78
+
79
+ # # fixes blockquotes
80
+ # html = html.gsub(/\n<p>&gt\;(.*)\n&gt\;/) { |bq|
81
+ # bq.delete_prefix!("\n<p>&gt;")
82
+ # "\n<blockquote>" + bq
83
+ # }
84
+ # html = html.gsub(/\n&gt\;(.*)\n&gt\;/) { |bq|
85
+ # bq.delete_prefix!("\n&gt;")
86
+ # " " + bq
87
+ # }
88
+ # html = html.gsub(/\n&gt\;(.*)<\/p>/) { |bq|
89
+ # bq.delete_prefix!("\n&gt\;")
90
+ # bq.delete_suffix!("</p>")
91
+ # " " + bq + "</blockquote>"
92
+ # }
93
+
94
+ html
65
95
  end
66
96
 
67
97
 
@@ -84,6 +114,9 @@ class RepositoryConverter
84
114
 
85
115
  def self.remove_footer(readme)
86
116
  readme.gsub(/<p class='util--hide'(.+?)<\/p>/,"")
117
+ readme.gsub(/<p data-visibility='hidden'(.+?)<\/p>/,"")
118
+ readme.gsub(/<p>&lt\;p data-visibility=&#39\;hidden&#39(.+?)<\/p>/,"")
119
+ readme.gsub(/<p>&lt\;p class=&#39;util--hide&#39\;(.+?)<\/p>/,"")
87
120
  end
88
121
 
89
122
  def self.remove_html_header(html)
@@ -155,7 +188,12 @@ class RepositoryConverter
155
188
  image_source = image_source.gsub(/(\'|\")/, "")
156
189
  image_source = image_source.gsub(/src=/, '')
157
190
  image_source = image_source.strip
158
- 'src="' + raw_remote_url + '/' + branch + '/' + image_source + '"'
191
+
192
+ begin
193
+ 'src="' + raw_remote_url + '/' + branch + '/' + image_source + '"'
194
+ rescue
195
+ byebug
196
+ end
159
197
  else
160
198
  image_source
161
199
  end
@@ -185,12 +223,12 @@ class RepositoryConverter
185
223
  def self.add_fis_links(options, html)
186
224
  repo_info = self.get_repo_info(options[:filepath])
187
225
  html = html.sub(/<div id="git-data-element.*<header class="fis-header.*<\/header>/,'') # remove existing fis header
188
- header = self.create_github_link_header(repo_info[:repo_path], options[:forkable])
226
+ header = self.create_github_link_header(repo_info[:repo_path], options)
189
227
  data_element = self.create_data_element(repo_info[:repo_org], repo_info[:repo_name], options[:aaq])
190
228
  data_element + header + html
191
229
  end
192
230
 
193
- def self.create_github_link_header(repo_path, forkable)
231
+ def self.create_github_link_header(repo_path, options)
194
232
  # add link to associated repository
195
233
  github_repo_link = "<a class='fis-git-link' href='#{repo_path}' target='_blank' rel='noopener'><img id='repo-img' title='Open GitHub Repo' alt='GitHub Repo' /></a>"
196
234
 
@@ -198,9 +236,12 @@ class RepositoryConverter
198
236
  github_issue_link = "<a class='fis-git-link' href='#{repo_path}/issues/new' target='_blank' rel='noopener'><img id='issue-img' title='Create New Issue' alt='Create New Issue' /></a>"
199
237
 
200
238
  # add link to fork (forking handled by separate Flatiron server, generation of link handled via custom Canvas JS theme file)
201
- if (forkable)
202
- github_fork_link = "<a class='fis-fork-link' id='fork-link' href='#' target='_blank' rel='noopener'><img id='fork-img' title='Fork This Assignment' alt='Fork This Assignment' /></a>"
239
+
240
+ if (options[:forkable])
241
+ github_fork_link = "<a class='fis-fork-link' id='fork-link' href='#{repo_path}/fork' target='_blank' rel='noopener'><img id='fork-img' title='Fork This Assignment' alt='Fork This Assignment' /></a>"
203
242
  "<header class='fis-header' style='visibility: hidden;'>#{github_fork_link}#{github_repo_link}#{github_issue_link}</header>"
243
+ elsif options[:git_links]
244
+ "<header class='fis-header'>#{github_repo_link}#{github_issue_link}</header>"
204
245
  else
205
246
  "<header class='fis-header' style='visibility: hidden;'>#{github_repo_link}#{github_issue_link}</header>"
206
247
  end
@@ -1,3 +1,3 @@
1
1
  class GithubToCanvas
2
- VERSION = "0.1.5"
2
+ VERSION = "0.1.7"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: github-to-canvas
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.5
4
+ version: 0.1.7.pre
5
5
  platform: ruby
6
6
  authors:
7
7
  - maxwellbenton
@@ -104,11 +104,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
104
104
  version: '0'
105
105
  required_rubygems_version: !ruby/object:Gem::Requirement
106
106
  requirements:
107
- - - ">="
107
+ - - ">"
108
108
  - !ruby/object:Gem::Version
109
- version: '0'
109
+ version: 1.3.1
110
110
  requirements: []
111
- rubygems_version: 3.0.8
111
+ rubygems_version: 3.2.3
112
112
  signing_key:
113
113
  specification_version: 4
114
114
  summary: github-to-canvas is a tool for migrating and aligning GitHub content with