github-to-canvas 0.1.2 → 0.1.8

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f5628681c8cda313989c521770b0b7f2a20e9b7a0aa0f661446d25d1040eca8d
4
- data.tar.gz: da78038dd5492dbb897c9fb6d65e05c76f02e7e57df952630c859d9b446d6c79
3
+ metadata.gz: 18f61edcbd53e1e26f59fe6767ae09b3bb227dee2f6529797a1f0fc6ace94b00
4
+ data.tar.gz: 0757bd6b39a7fd9e4bb996156db33309cd96afbe2f8274c1261e95b4aad210e4
5
5
  SHA512:
6
- metadata.gz: abc12344a24c0c7d67980dc4911462e7c7eb3aba0c31e18b42e5f95fda97fef7b60a994c4ce59fc6da3d6fb7db044fc47ae443979e06455a82906e4ae863f4cd
7
- data.tar.gz: 467e1d799b929fccf52cb155d27411050232c30b704fde8d216516c1bc7891d69c6617252cfdd8782ceb35a10fd05b2d5efdf5dd6754bfb097f22ee740876f36
6
+ metadata.gz: 593e15eb02ee30c7d45b3ffb479efcd69ab3b80436a23b81f6f731e3ad7a2a3a81d05601baf15cd893a86a54029a919ac45617a20cdb4a2c5ad4e441b8529c4e
7
+ data.tar.gz: 8306e5d652b5e61c3aba33e09a70e0f8aa3a1455dea60269c685983793c443f7065944cf157aa365c693cec9ae12d49a579aec66efc73e390e2643c3fa07b198
data/README.md CHANGED
@@ -294,29 +294,45 @@ includes HTML that is not meant to be rendered, the content will be rendered as
294
294
  part of the page's HTML, resulting in unusual display errors in Canvas. Examples of
295
295
  this would be lessons on HTML or JavaScript that include HTML code snippets.
296
296
 
297
- To fix any rendering issues in Canvas, go to the Canvas WYSIWYG editor for the
298
- afflicted lesson. Click the HTML editor option (`</>` button in the lower right) to
299
- switch to HTML.
300
-
301
- Read the GitHub repo as HTML:
302
-
303
- ```sh
304
- github-to-canvas --read-from-github URL
305
- ```
306
-
307
- Copy the output HTML and paste it in to the Canvas editor. This should clear up
308
- some larger page rendering issues, but may not fix all code snippets issues. To
309
- fix these, switch back to the regular Canvas WYSIWYG editor, then open a second
310
- tab to the GitHub repo you're converting from. Copy any HTML code snippets from
311
- GitHub and paste them into the Canvas editor where they should be displayed.
297
+ To prevent HTML from being rendered, include the `--contains-html` option when
298
+ running the GitHub to Canvas gem. This replaces `<` and `>` characters with HTML
299
+ charset values wrapped in `span` elements. This will stop Canvas from rendering
300
+ the HTML.
301
+
302
+ If your markdown contains a mix of HTML that should and should not be rendered,
303
+ you will need to either replace HTML that you want to be rendered with markdown
304
+ syntax equivalents. For example, HTML you want to display as code and an `<img>`
305
+ element you want to render as the image itself, replace the `<img>` tag with
306
+ markdown syntax (`![alt text](url)`).
307
+
308
+ The one exception is the `<iframe>` element. There is no way to easily embed
309
+ videos in GitHub markdown without HTML, so this tag will always be allowed to
310
+ render in Canvas, whether or not you use `--contains-html`.
311
+
312
+ If you have HTML related rendering issues in Canvas that can't be fixed with
313
+ `--contains-html`:
314
+
315
+ - Go to the Canvas WYSIWYG editor for the afflicted lesson.
316
+ - Click the HTML editor option (`</>` button in the lower right) to switch to
317
+ HTML.
318
+ - Read the GitHub repo as HTML:
319
+
320
+ ```sh
321
+ github-to-canvas --read-from-github URL
322
+ ```
323
+
324
+ - Copy the output HTML and paste it in to the Canvas editor. This should clear up
325
+ some larger page rendering issues, but may not fix all code snippets issues.
326
+ - Switch back to the regular Canvas WYSIWYG editor
327
+ - Open a second tab to the GitHub repo you're converting from.
328
+ - Copy any HTML code snippets from GitHub and paste them into the Canvas editor
329
+ where they should be displayed.
312
330
 
313
331
  The Canvas editor will treat the pasted HTML content as code and will
314
332
  automatically replace some characters, escaping the code from the
315
333
  normal rendering process.
316
334
 
317
- Note that realigning after fixing this content with the gem will break the
318
- rendering for these lessons again. A fix is planned for this issue, but has not
319
- been implemented.
335
+ Note that realigning after fixing this content may overwrite fixes.
320
336
 
321
337
  ### Multi-Line Code Snippets Render as a Single Line
322
338
 
data/bin/github-to-canvas CHANGED
@@ -1,5 +1,7 @@
1
- require 'byebug'
2
1
  #!/usr/bin/env ruby
2
+
3
+ require 'byebug'
4
+
3
5
  require 'optparse'
4
6
  require 'github-to-canvas'
5
7
 
@@ -77,7 +79,6 @@ OptionParser.new do |opts|
77
79
  opts.on("-tTYPE", "--type TYPE",
78
80
  "Sets the type Canvas lesson to be created (page or assignment). If no type, type decided based on repository structure") do |type|
79
81
  # byebug
80
- puts type.downcase
81
82
  options[:type] = type.downcase
82
83
  abort if type == 'quiz' || type == 'discussion'
83
84
  # if type == 'page' || type == 'assignment' || type == 'discussion' || type == 'quiz' || type == 'Page' || type == 'Assignment' || type == 'Discussion' || type == 'Quiz'
@@ -107,6 +108,18 @@ OptionParser.new do |opts|
107
108
  "Adds additional Flatiron School HTML after markdown conversion") do |f|
108
109
  options[:fis] = true
109
110
  end
111
+ opts.on("-g", "--git-links",
112
+ "Adds additional GitHub after markdown conversion") do |f|
113
+ options[:git_links] = true
114
+ end
115
+ opts.on("--aaq",
116
+ "Adds AAQ flag to HTML header appended with --fis-links") do |aaq|
117
+ options[:aaq] = aaq
118
+ end
119
+ opts.on("--prework",
120
+ "Adds prework flag to HTML header appended with --fis-links") do |prework|
121
+ options[:prework] = prework
122
+ end
110
123
  opts.on("--forkable",
111
124
  "Used with --fis-links, adds fork button to HTML header injected into Canvas lesson") do |remote|
112
125
  options[:forkable] = true
@@ -135,10 +148,14 @@ OptionParser.new do |opts|
135
148
  "REQUIRES -f or --file Associates canvas lessons with repositories. Use query to create required YAML file") do |file|
136
149
  options[:map] = file
137
150
  end
138
- opts.on("--csv COURSE",
139
- "Returns a course's lesson struction as CSV") do |course|
140
- options[:csv] = course
151
+ opts.on("--urls-only",
152
+ "Use with --map. Outputs repo URLs instead of YAML") do |urls|
153
+ options[:urls_only] = urls
141
154
  end
155
+ # opts.on("--csv COURSE",
156
+ # "Returns a course's lesson struction as CSV") do |course|
157
+ # options[:csv] = course
158
+ # end
142
159
  opts.on("--read-from-canvas CANVAS_URL",
143
160
  "Retrieves an existing Canvas lesson using the provided URL") do |url|
144
161
  options[:read_from_canvas] = url
@@ -175,6 +192,19 @@ OptionParser.new do |opts|
175
192
  "Iterates over provided course YAML file and clones repos locally") do |file|
176
193
  options[:clone_from_yaml] = file
177
194
  end
195
+ opts.on("--contains-html",
196
+ "Escapes all HTML included in source markdown by replacing '<' and '>' with HTML charset values") do |html|
197
+ options[:contains_html] = html
198
+ end
199
+ opts.on("--canvas-to-canvas COURSE",
200
+ "Copies an existing Canvas lesson into another Canvas lesson") do |canvas_to_canvas|
201
+ options[:canvas_to_canvas] = canvas_to_canvas
202
+ end
203
+ opts.on("--build-from-csv CSV",
204
+ "Build a course usin a CSV of lesson repos, names, modules, and types") do |csv_build|
205
+ options[:csv_build] = csv_build
206
+ end
207
+
178
208
 
179
209
  end.parse!
180
210
 
@@ -184,12 +214,30 @@ if options[:version]
184
214
  end
185
215
 
186
216
  if options[:read_from_canvas]
187
- GithubToCanvas.new(mode: 'canvas_read', filepath: options[:read_from_canvas])
217
+ GithubToCanvas.new(mode: 'canvas_read',
218
+ filepath: options[:read_from_canvas])
219
+ abort
220
+ end
221
+
222
+ if options[:canvas_to_canvas]
223
+ GithubToCanvas.new(mode: 'canvas_copy',
224
+ filepath: options[:canvas_to_canvas],
225
+ course_id: options[:course_id],
226
+ type: options[:type],
227
+ id: options[:id]
228
+ )
188
229
  abort
189
230
  end
190
231
 
191
232
  if options[:read_from_github]
192
- GithubToCanvas.new(mode: 'github_read', filepath: options[:read_from_github])
233
+ GithubToCanvas.new(mode: 'github_read',
234
+ filepath: options[:read_from_github],
235
+ remove_header_and_footer: !!options[:remove_header_and_footer],
236
+ forkable: !!options[:forkable],
237
+ fis_links: !!options[:fis],
238
+ aaq: !!options[:aaq],
239
+ prework: !!options[:prework],
240
+ contains_html: options[:contains_html])
193
241
  abort
194
242
  end
195
243
 
@@ -199,9 +247,13 @@ if options[:create_from_github]
199
247
  filepath: options[:create_from_github],
200
248
  course_id: options[:course_id],
201
249
  type: options[:type],
250
+ name: options[:name],
202
251
  remove_header_and_footer: !!options[:remove_header_and_footer],
203
252
  forkable: !!options[:forkable],
204
- fis_links: !!options[:fis])
253
+ fis_links: !!options[:fis],
254
+ aaq: !!options[:aaq],
255
+ prework: !!options[:prework],
256
+ contains_html: options[:contains_html])
205
257
  else
206
258
  puts 'Canvas course ID and lesson type required. Example: github-to-canvas --create-from-github URL --course ID --type TYPE'
207
259
  end
@@ -218,7 +270,10 @@ if options[:align_from_github]
218
270
  name: options[:name],
219
271
  remove_header_and_footer: !!options[:remove_header_and_footer],
220
272
  forkable: !!options[:forkable],
221
- fis_links: !!options[:fis])
273
+ fis_links: !!options[:fis],
274
+ aaq: !!options[:aaq],
275
+ prework: !!options[:prework],
276
+ contains_html: options[:contains_html])
222
277
  else
223
278
  puts 'Canvas course ID, lesson ID, and type required. Example: github-to-canvas --create-from-github URL --course COURSE_ID --id LESSON_ID --type TYPE'
224
279
  end
@@ -231,7 +286,9 @@ if options[:query]
231
286
  end
232
287
 
233
288
  if options[:map]
234
- GithubToCanvas.new(mode: 'map', file_to_convert: options[:map])
289
+ GithubToCanvas.new(mode: 'map',
290
+ file_to_convert: options[:map],
291
+ urls_only: !!options[:urls_only])
235
292
  abort
236
293
  end
237
294
 
@@ -240,12 +297,30 @@ if options[:csv]
240
297
  abort
241
298
  end
242
299
 
300
+ if options[:csv_build]
301
+ GithubToCanvas.new(mode: 'csv_build',
302
+ file_to_convert: options[:csv_build],
303
+ course_id: options[:course_id],
304
+ fis_links: !!options[:fis],
305
+ remove_header_and_footer: !!options[:remove_header_and_footer],
306
+ aaq: !!options[:aaq],
307
+ forkable: !!options[:forkable],
308
+ branch: options[:branch],
309
+ contains_html: options[:contains_html],
310
+ git_links: !!options[:git_links])
311
+ abort
312
+ end
313
+
243
314
  if options[:build_course]
244
315
  GithubToCanvas.new(mode: 'build_course',
245
316
  file_to_convert: options[:build_course],
246
317
  fis_links: !!options[:fis],
247
318
  remove_header_and_footer: !!options[:remove_header_and_footer],
248
- forkable: !!options[:forkable])
319
+ aaq: !!options[:aaq],
320
+ prework: !!options[:prework],
321
+ forkable: !!options[:forkable],
322
+ contains_html: options[:contains_html],
323
+ git_links: !!options[:git_links])
249
324
  abort
250
325
  end
251
326
 
@@ -256,7 +331,11 @@ if options[:add_to_course]
256
331
  file_to_convert: options[:add_to_course],
257
332
  fis_links: !!options[:fis],
258
333
  remove_header_and_footer: !!options[:remove_header_and_footer],
259
- forkable: !!options[:forkable])
334
+ forkable: !!options[:forkable],
335
+ aaq: !!options[:aaq],
336
+ prework: !!options[:prework],
337
+ contains_html: options[:contains_html],
338
+ git_links: !!options[:git_links])
260
339
  else
261
340
  puts '--course required'
262
341
  end
@@ -268,7 +347,11 @@ if options[:update_course_lessons]
268
347
  file_to_convert: options[:update_course_lessons],
269
348
  fis_links: !!options[:fis],
270
349
  remove_header_and_footer: !!options[:remove_header_and_footer],
271
- forkable: !!options[:forkable])
350
+ forkable: !!options[:forkable],
351
+ aaq: !!options[:aaq],
352
+ prework: !!options[:prework],
353
+ contains_html: options[:contains_html],
354
+ git_links: !!options[:git_links])
272
355
  abort
273
356
  end
274
357
 
@@ -328,9 +411,13 @@ if options[:create_lesson]
328
411
  type: options[:type],
329
412
  save_to_github: !!options[:save_to_github],
330
413
  fis_links: !!options[:fis],
414
+ git_links: !!options[:git_links],
331
415
  remove_header_and_footer: !!options[:remove_header_and_footer],
332
416
  only_update_content: !!options[:only_content],
333
- forkable: !!options[:forkable])
417
+ forkable: !!options[:forkable],
418
+ aaq: !!options[:aaq],
419
+ prework: !!options[:prework],
420
+ contains_html: options[:contains_html])
334
421
  end
335
422
 
336
423
  if options[:align]
@@ -343,8 +430,12 @@ if options[:align]
343
430
  name: options[:name],
344
431
  type: options[:type],
345
432
  save_to_github: !!options[:save_to_github],
346
- fis_links: !!options[:fis],
433
+ fis_links: !!options[:fis],
434
+ git_links: !!options[:git_links],
347
435
  remove_header_and_footer: !!options[:remove_header_and_footer],
348
436
  only_update_content: !!options[:only_content],
349
- forkable: !!options[:forkable])
437
+ forkable: !!options[:forkable],
438
+ aaq: !!options[:aaq],
439
+ prework: !!options[:prework],
440
+ contains_html: options[:contains_html])
350
441
  end
@@ -1,4 +1,4 @@
1
- require 'byebug'
1
+ require 'csv'
2
2
  require_relative './github-to-canvas/create_canvas_lesson'
3
3
  require_relative './github-to-canvas/update_canvas_lesson'
4
4
  require_relative './github-to-canvas/canvas_dotfile'
@@ -21,14 +21,16 @@ class GithubToCanvas
21
21
  when 'query'
22
22
  CanvasInterface.get_course_info(options[:course_id], options[:id])
23
23
  when 'map'
24
- CanvasInterface.map_course_info(options[:file_to_convert])
24
+ CanvasInterface.map_course_info(options)
25
25
  when 'csv'
26
26
  CanvasInterface.csv(options[:file_to_convert])
27
27
  when 'canvas_read'
28
28
  puts CanvasInterface.read_lesson(options[:filepath])
29
+ when 'canvas_copy'
30
+ CanvasInterface.copy_lesson(options)
29
31
  when 'github_read'
30
- markdown = GithubInterface.read_remote(options[:filepath])
31
- puts RepositoryConverter.convert_to_html(markdown)
32
+ html = RepositoryConverter.remote_file_conversion(options)
33
+ puts RepositoryConverter.adjust_converted_html(options, html)
32
34
  when 'create' # used with a local repo
33
35
  html = RepositoryConverter.local_file_conversion(options)
34
36
  name = RepositoryInterface.get_name(options[:filepath], html)
@@ -38,21 +40,29 @@ class GithubToCanvas
38
40
  puts "Canvas lesson created. Lesson available at #{response['html_url']}"
39
41
  when 'align' # used with a local repo
40
42
  html = RepositoryConverter.local_file_conversion(options)
41
- name = RepositoryInterface.get_name(options[:filepath], html)
43
+ name = options[:name] ? options[:name] : RepositoryInterface.get_name(options[:filepath], html)
42
44
  html = RepositoryConverter.adjust_converted_html(options, html)
43
45
  CanvasInterface.update_all_related_lessons(options, name, html)
44
46
 
45
47
  when 'github_create'
48
+ if (!options[:branch])
49
+ options[:branch] = 'master'
50
+ end
46
51
  html = RepositoryConverter.remote_file_conversion(options)
47
- name = RepositoryInterface.get_name(options[:filepath], html)
48
- html = RepositoryConverter.adjust_converted_html(options, html)
49
52
 
53
+ html = RepositoryConverter.adjust_converted_html(options, html)
54
+ name = options[:name] ? options[:name] : RepositoryInterface.get_name(options[:filepath], html)
55
+ puts name
50
56
  response = CanvasInterface.create_lesson(options, name, html)
51
57
 
52
58
  puts "Canvas lesson created. Lesson available at #{response['html_url']}"
53
59
  when 'github_align'
60
+ if (!options[:branch])
61
+ options[:branch] = 'master'
62
+ end
54
63
  html = RepositoryConverter.remote_file_conversion(options)
55
64
  name = options[:name] ? options[:name] : RepositoryInterface.get_name(options[:filepath], html)
65
+
56
66
  html = RepositoryConverter.adjust_converted_html(options, html)
57
67
  response = CanvasInterface.update_existing_lesson(options, name, html)
58
68
  puts "Canvas lesson updated. Lesson available at #{response['html_url']}"
@@ -152,6 +162,60 @@ class GithubToCanvas
152
162
  end
153
163
  }
154
164
  }
165
+ when 'csv_build'
166
+ if !options[:course_id]
167
+ course_info = {
168
+ name: "CSV Build Test",
169
+ course_code: "CSV-TEST"
170
+ }
171
+ created_course_info = CanvasInterface.create_course(course_info)
172
+ puts "Course created - #{created_course_info["id"]}"
173
+ puts "Make sure to add yourself as a teacher to this course before continuing, then press Enter/Return"
174
+ input = gets
175
+ options[:course_id] = created_course_info["id"]
176
+ else
177
+ puts "Adding to course #{options[:course_id]}"
178
+ end
179
+
180
+ csv_data = CSV.read(options[:file_to_convert])
181
+ created_module_info = {
182
+ "id" => "",
183
+ "name" => ""
184
+ }
185
+
186
+ csv_data.each { |lesson|
187
+ # lesson[0] == repo
188
+ # lesson[1] == name
189
+ # lesson[2] == module
190
+ # lesson[3] == type
191
+ # lesson[4] == yes/no contains HTML
192
+ module_info = {
193
+ name: lesson[2]
194
+ }
195
+ if created_module_info["name"] != module_info[:name]
196
+ created_module_info = CanvasInterface.create_module(options[:course_id], module_info)
197
+ puts "New module created - #{created_module_info["id"]} - #{created_module_info["name"]}"
198
+ end
199
+
200
+ options[:filepath] = lesson[0]
201
+ options[:name] = lesson[1]
202
+ options[:type] = lesson[3]
203
+ options[:branch] = "master" if !options[:branch]
204
+ if !options[:contains_html]
205
+ options[:contains_html] = (lesson[4] == "yes" || lesson[4] == "Yes") ? true : false
206
+ end
207
+
208
+
209
+ html = RepositoryConverter.remote_file_conversion(options)
210
+ html = RepositoryConverter.adjust_converted_html(options, html)
211
+ created_lesson_info = CanvasInterface.create_lesson(options, lesson[1], html)
212
+ created_lesson_info["page_url"] = created_lesson_info["url"] if !created_lesson_info["page_url"]
213
+ created_lesson_info["id"] = created_lesson_info["page_url"] if !created_lesson_info["id"]
214
+ created_lesson_info["type"] = options[:type]
215
+ puts "Creating lesson - #{options[:name]}"
216
+ response = CanvasInterface.add_to_module(options[:course_id], created_module_info, created_lesson_info)
217
+
218
+ }
155
219
  else
156
220
  puts VERSION
157
221
  end
@@ -1,4 +1,3 @@
1
- require 'byebug'
2
1
  require 'json'
3
2
  require 'rest-client'
4
3
  require 'yaml'
@@ -47,44 +46,37 @@ class CanvasInterface
47
46
  JSON.parse(response.body)
48
47
  end
49
48
 
50
- def self.create_quiz(options, quiz_data)
51
-
52
- end
53
-
54
49
  def self.add_to_module(course_id, module_info, lesson_info)
55
50
  # POST /api/v1/courses/:course_id/modules/:module_id/items
56
51
  url = "#{ENV['CANVAS_API_PATH']}/courses/#{course_id}/modules/#{module_info["id"]}/items"
57
52
 
58
- if lesson_info["type"] == "Page"
53
+ if lesson_info["type"] == "Page" || lesson_info["type"] == "page"
59
54
  payload = {
60
- 'module_item[title]' => lesson_info["title"],
61
- 'module_item[type]' => lesson_info["type"],
62
- 'module_item[indent]' => 0,
63
- 'module_item[page_url]' => lesson_info["id"],
64
- 'module_item[completion_requirement][type]' => 'must_view'
65
- }
55
+ 'module_item[title]' => lesson_info["title"],
56
+ 'module_item[type]' => lesson_info["type"].capitalize,
57
+ 'module_item[indent]' => 0,
58
+ 'module_item[page_url]' => lesson_info["id"],
59
+ 'module_item[completion_requirement][type]' => 'must_view'
60
+ }
66
61
  elsif lesson_info["type"] == "Quiz"
67
62
  puts "Quiz needs to be added manually - #{lesson_info['title']} - lesson_info["
68
63
  else
69
64
 
70
65
  payload = {
71
66
  'module_item[title]' => lesson_info["title"],
72
- 'module_item[type]' => lesson_info["type"],
67
+ 'module_item[type]' => lesson_info["type"].capitalize,
73
68
  'module_item[indent]' => 1,
74
69
  'module_item[content_id]' => lesson_info["id"],
75
70
  'module_item[completion_requirement][type]' => 'must_submit'
76
71
  }
77
72
  end
78
73
  begin
79
- byebug
80
74
  response = RestClient.post(url, payload, self.headers)
81
75
  rescue
82
76
  puts "Something went wrong while adding lesson #{lesson_info["id"]} to module #{module_info["id"]} in course #{course_id}" if lesson_info["type"] == "Assignment"
83
77
  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"
84
78
  abort
85
79
  end
86
-
87
-
88
80
  response
89
81
 
90
82
  end
@@ -200,6 +192,7 @@ class CanvasInterface
200
192
  while !!index
201
193
  url = "#{ENV['CANVAS_API_PATH']}/courses/#{course}/modules?page=#{index}&per_page=20"
202
194
  index += 1
195
+
203
196
  response = RestClient.get(url, self.headers)
204
197
  modules = JSON.parse(response.body)
205
198
 
@@ -207,7 +200,7 @@ class CanvasInterface
207
200
  course_info[:modules] = course_info[:modules] + modules
208
201
  else
209
202
  index = nil
210
- end
203
+ end
211
204
  end
212
205
 
213
206
  course_info[:modules] = course_info[:modules].map do |mod|
@@ -220,11 +213,12 @@ class CanvasInterface
220
213
  while !!index
221
214
  url = "#{ENV['CANVAS_API_PATH']}/courses/#{course}/modules/#{mod['id']}/items?page=#{index}&per_page=20"
222
215
  index += 1
223
- response = RestClient.get(url, headers={
224
- "Authorization" => "Bearer #{ENV['CANVAS_API_KEY']}"
225
- })
216
+ response = RestClient.get(url, self.headers)
226
217
  lessons = JSON.parse(response.body)
227
218
  lessons = lessons.map do |lesson|
219
+ if lesson["type"] == "ExternalUrl"
220
+ next
221
+ end
228
222
  lesson = lesson.slice("id","title","name","indent","type","html_url","page_url","url","completion_requirement", "published")
229
223
  lesson["repository"] = ""
230
224
  lesson['id'] = lesson['url'].gsub(/^(.*[\\\/])/,'')
@@ -239,7 +233,7 @@ class CanvasInterface
239
233
  end
240
234
  new_mod
241
235
  end
242
-
236
+
243
237
  puts course_info.to_yaml
244
238
 
245
239
  rescue
@@ -248,8 +242,8 @@ class CanvasInterface
248
242
  end
249
243
  end
250
244
 
251
- def self.map_course_info(file_to_convert)
252
- course_info = YAML.load(File.read("#{Dir.pwd}/#{file_to_convert}"))
245
+ def self.map_course_info(options)
246
+ course_info = YAML.load(File.read("#{Dir.pwd}/#{options[:file_to_convert]}"))
253
247
  course_info[:modules] = course_info[:modules].map do |mod|
254
248
  mod[:lessons] = mod[:lessons].map do |lesson|
255
249
 
@@ -285,6 +279,7 @@ class CanvasInterface
285
279
  lesson["repository"] = repo
286
280
  else
287
281
  lesson["repository"] = "https://github.com/learn-co-curriculum/" + repo
282
+ puts lesson["repository"] if options[:urls_only]
288
283
  end
289
284
  end
290
285
  sleep(1)
@@ -292,7 +287,7 @@ class CanvasInterface
292
287
  end
293
288
  mod
294
289
  end
295
- puts course_info.to_yaml
290
+ puts course_info.to_yaml if !options[:urls_only]
296
291
  end
297
292
 
298
293
  def self.csv(file_to_convert)
@@ -339,12 +334,40 @@ class CanvasInterface
339
334
  end
340
335
  mod
341
336
  end
342
- byebug
343
337
  puts course_info.to_yaml
344
338
  end
345
339
 
346
-
340
+ def self.copy_lesson(options)
341
+ types = ["page", "assignment", "quiz", "discussion"]
342
+ url = options[:filepath]
343
+ type = types.find {|type| url.match(type)}
344
+ options[:type] = type
345
+ if !url.include?(ENV['CANVAS_API_PATH'])
346
+ url = url.sub(/^.*\/\/.*?\//,"#{ENV['CANVAS_API_PATH']}/")
347
+ end
347
348
 
349
+ response = RestClient.get(url, headers={
350
+ "Authorization" => "Bearer #{ENV['CANVAS_API_KEY']}"
351
+ })
352
+
353
+ lesson_info = JSON.parse(response)
354
+ lesson_info = lesson_info.slice("title",
355
+ "name",
356
+ "description",
357
+ "body",
358
+ "message",
359
+ "shuffle_answers",
360
+ "allowed_attempts",
361
+ "question_count"
362
+ )
363
+ if options[:type] == "page"
364
+ self.update_existing_lesson(options, lesson_info["title"], lesson_info["body"])
365
+ else
366
+ self.update_existing_lesson(options, lesson_info["name"], lesson_info["description"])
367
+ end
368
+
369
+
370
+ end
348
371
 
349
372
  def self.build_payload(options, name, html)
350
373
  if options[:only_update_content]
@@ -61,11 +61,11 @@ class GithubInterface
61
61
  rescue
62
62
  begin
63
63
  response = RestClient.get(url_fallback)
64
+ return response.body
64
65
  rescue
65
66
  puts 'Error reading ' + url
66
67
  end
67
68
  end
68
-
69
69
  response.body
70
70
  end
71
71
 
@@ -17,7 +17,7 @@ class RepositoryConverter
17
17
  GithubInterface.get_updated_repo(options[:filepath], options[:branch])
18
18
  markdown = RepositoryInterface.read_local_file(options[:filepath], options[:file_to_convert])
19
19
  raw_remote_url = self.set_raw_image_remote_url(options[:filepath])
20
-
20
+ markdown = self.escape_existing_html(markdown) if options[:contains_html]
21
21
  markdown = self.fix_local_images(options, markdown, raw_remote_url)
22
22
  html = self.convert_to_html(markdown)
23
23
  # self.fix_local_html_links(options, html, options[:filepath])
@@ -26,15 +26,27 @@ class RepositoryConverter
26
26
  def self.remote_file_conversion(options)
27
27
  markdown = GithubInterface.read_remote(options[:filepath])
28
28
  raw_remote_url = self.set_raw_image_remote_url(options[:filepath])
29
+ if options[:contains_html]
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'
39
+ end
29
40
  markdown = self.fix_local_images(options, markdown, raw_remote_url)
30
41
  html = self.convert_to_html(markdown)
31
42
  # self.fix_local_html_links(options, html, options[:filepath])
32
43
  end
33
44
 
34
45
  def self.convert_to_html(markdown)
35
- 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})
36
48
  html = redcarpet.render(markdown)
37
- self.remove_line_breaks(html)
49
+ # self.remove_line_breaks(html)
38
50
  end
39
51
 
40
52
  def self.adjust_converted_html(options, html)
@@ -43,12 +55,52 @@ class RepositoryConverter
43
55
  html = self.remove_header_and_footer(html)
44
56
  end
45
57
 
46
- if options[:fis_links]
58
+ if options[:fis_links] || options[:git_links]
47
59
  html = self.add_fis_links(options, html)
48
60
  end
61
+
62
+ if options[:contains_html]
63
+ html = self.fix_escaped_inline_html_code(html)
64
+ end
65
+
66
+ html
67
+ end
68
+
69
+ def self.fix_escaped_inline_html_code(html)
70
+
71
+ # stops HTML/JSX code blocks from rendering as HTML in Canvas
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
+
49
94
  html
50
95
  end
51
96
 
97
+
98
+ def self.escape_existing_html(markdown)
99
+ markdown = markdown.gsub(/<\/(?!iframe)/, "&lt;/")
100
+ markdown = markdown.gsub(/<(?!iframe)/, "&lt;")
101
+ markdown = markdown.gsub(/(?<!iframe)>/, "&gt;")
102
+ end
103
+
52
104
  def self.remove_header_and_footer(html)
53
105
  new_html = self.remove_html_header(html)
54
106
  new_html = self.remove_footer(new_html)
@@ -56,12 +108,15 @@ class RepositoryConverter
56
108
  end
57
109
 
58
110
  def self.remove_header(readme)
59
- readme.gsub!(/^# .+?\n\n/,"")
111
+ readme = readme.gsub(/^# .+?\n\n/,"")
60
112
  readme.gsub(/^# .+?\n/,"")
61
113
  end
62
114
 
63
115
  def self.remove_footer(readme)
64
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>/,"")
65
120
  end
66
121
 
67
122
  def self.remove_html_header(html)
@@ -114,7 +169,7 @@ class RepositoryConverter
114
169
  end
115
170
 
116
171
  def self.adjust_local_markdown_images(readme, raw_remote_url, branch)
117
- readme.gsub!(/\!\[.+\]\(.+\)/) {|image_markdown|
172
+ readme.gsub(/\!\[.+\]\(.+\)/) {|image_markdown|
118
173
  if !image_markdown.match?('amazonaws.com') && !image_markdown.match?('https://') && !image_markdown.match?('http://') && !image_markdown.match?('youtube')
119
174
  image_markdown.gsub!(/\(.+\)/) { |path|
120
175
  path.delete_prefix!("(")
@@ -127,12 +182,18 @@ class RepositoryConverter
127
182
  end
128
183
 
129
184
  def self.adjust_local_html_images(readme, raw_remote_url, branch)
130
- readme.gsub!(/src=(\'|\")[\s\S]*?(\'|\")/) { |image_source|
131
- if !image_source.match?('amazonaws.com') && !image_source.match?('https://') && !image_source.match?('http://') && !image_source.match?('youtube')
132
- image_source.gsub!(/(\'|\")/, "")
133
- image_source.gsub!(/src=/, '')
134
- image_source.strip!
135
- 'src="' + raw_remote_url + '/' + branch + '/' + image_source + '"'
185
+ readme.gsub(/src=(\'|\")[\s\S]*?(\'|\")/) { |image_source|
186
+
187
+ if !image_source.match?('amazonaws.com') && !image_source.match?('https://') && !image_source.match?('http://') && !image_source.match?('youtube') && !image_source.match(/src=(\'|\")(?=<%)/)
188
+ image_source = image_source.gsub(/(\'|\")/, "")
189
+ image_source = image_source.gsub(/src=/, '')
190
+ image_source = image_source.strip
191
+
192
+ begin
193
+ 'src="' + raw_remote_url + '/' + branch + '/' + image_source + '"'
194
+ rescue
195
+ puts "Error adjust HTML images - check images in Canvas"
196
+ end
136
197
  else
137
198
  image_source
138
199
  end
@@ -162,12 +223,12 @@ class RepositoryConverter
162
223
  def self.add_fis_links(options, html)
163
224
  repo_info = self.get_repo_info(options[:filepath])
164
225
  html = html.sub(/<div id="git-data-element.*<header class="fis-header.*<\/header>/,'') # remove existing fis header
165
- header = self.create_github_link_header(repo_info[:repo_path], options[:forkable])
166
- data_element = self.create_data_element(repo_info[:repo_org], repo_info[:repo_name])
226
+ header = self.create_github_link_header(repo_info[:repo_path], options)
227
+ data_element = self.create_data_element(repo_info[:repo_org], repo_info[:repo_name], options[:aaq], options[:prework])
167
228
  data_element + header + html
168
229
  end
169
230
 
170
- def self.create_github_link_header(repo_path, forkable)
231
+ def self.create_github_link_header(repo_path, options)
171
232
  # add link to associated repository
172
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>"
173
234
 
@@ -175,16 +236,19 @@ class RepositoryConverter
175
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>"
176
237
 
177
238
  # add link to fork (forking handled by separate Flatiron server, generation of link handled via custom Canvas JS theme file)
178
- if (forkable)
179
- 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>"
180
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>"
181
245
  else
182
246
  "<header class='fis-header' style='visibility: hidden;'>#{github_repo_link}#{github_issue_link}</header>"
183
247
  end
184
248
  end
185
249
 
186
- def self.create_data_element(repo_org, repo_name)
187
- "<div id='git-data-element' data-org='#{repo_org}' data-repo='#{repo_name}'></div>"
250
+ def self.create_data_element(repo_org, repo_name, aaq, prework)
251
+ "<div id='git-data-element' #{prework ? "data-prework='true'" : ""} #{aaq ? "data-aaq='enabled'" : ""} data-org='#{repo_org}' data-repo='#{repo_name}'></div>"
188
252
  end
189
253
 
190
254
 
@@ -1,3 +1,3 @@
1
1
  class GithubToCanvas
2
- VERSION = "0.1.2"
2
+ VERSION = "0.1.8"
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.2
4
+ version: 0.1.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - maxwellbenton
@@ -108,7 +108,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
108
108
  - !ruby/object:Gem::Version
109
109
  version: '0'
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