github-to-canvas 0.1.0 → 0.1.5
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 +4 -4
- data/README.md +347 -52
- data/bin/github-to-canvas +79 -19
- data/lib/github-to-canvas.rb +26 -8
- data/lib/github-to-canvas/canvas_interface.rb +64 -20
- data/lib/github-to-canvas/github_interface.rb +2 -2
- data/lib/github-to-canvas/repository_converter.rb +38 -12
- data/lib/github-to-canvas/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b18946099c8b4fd23e1c2230f71fac458f932079fd22ada5297732358fec4d0e
|
4
|
+
data.tar.gz: '092e1b7854f2b4c4026f0713599d423d8eac6431ae16e4f9372c1a00ebb9775c'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d11be9f366fc3a457a671669a57802d6a1a8cc8ff3b0a7e9fa3ee10b4b8b91334cbaa336d39c1e3057c41e787619716d76df3e8523d918393cbb1b6fa9737549
|
7
|
+
data.tar.gz: 85d91f81000c82d55cb45e02f31c9aa3b2e241c785cb58366f5fbef99b72c7ce76e7e9d70f101cedb7f54c5082b2061926e0453cd8a162227cdba78f96c54e71
|
data/README.md
CHANGED
@@ -4,19 +4,15 @@
|
|
4
4
|
|
5
5
|
The `github-to-canvas` gem is designed to aid in integrating GitHub and the
|
6
6
|
Canvas LMS. This gem takes a GitHub repository's `README.md` file, converts it
|
7
|
-
to HTML, and pushes it to Canvas using the Canvas API.
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
With the `.canvas` file in place, this gem can be used to continuously align
|
12
|
-
content between GitHub and Canvas using the GitHub repository as the single
|
13
|
-
source of truth.
|
7
|
+
to HTML, and pushes it to Canvas using the Canvas API. This gem can also update
|
8
|
+
existing Canvas lessons, allowing continuous alignment of content between GitHub
|
9
|
+
and Canvas.
|
14
10
|
|
15
11
|
This gem is built for use internally at [Flatiron School][], so some features may be
|
16
12
|
specific to Flatiron School branding and needs. Access to the
|
17
13
|
[Canvas LMS API][] and the ability to add pages and assignments to a Canvas
|
18
14
|
course are required. Write access to the GitHub repository being converted is
|
19
|
-
also required for
|
15
|
+
also required for some features.
|
20
16
|
|
21
17
|
## Installation
|
22
18
|
|
@@ -47,7 +43,7 @@ echo "$(export 'CANVAS_API_KEY=your-new-API-key-here' | cat - ~/.bash_profile)"
|
|
47
43
|
|
48
44
|
### Add Canvas API Base Path
|
49
45
|
|
50
|
-
The exact Canvas API path is specific to where
|
46
|
+
The exact Canvas API path is specific to where your Canvas LMS is located. For example,
|
51
47
|
Flatiron School's base path is `https://learning.flatironschool.com/api/v1`. Add this path
|
52
48
|
as an `ENV` variable like the API key. **Do not add a `/` at the end after `/api/v1`.**
|
53
49
|
|
@@ -65,67 +61,366 @@ After both the API key and path are added to `~/.zshrc`, run `source ~/.zshrc` (
|
|
65
61
|
to make them available in your current terminal. You can verify these variables
|
66
62
|
are present by running `ENV` and finding them in the output list.
|
67
63
|
|
68
|
-
##
|
64
|
+
## Common Uses
|
65
|
+
|
66
|
+
The GitHub to Canvas gem can be used for the following:
|
67
|
+
|
68
|
+
- [Create a Canvas Lesson from a Local Repository](#create)
|
69
|
+
- [Create a Canvas Lesson from a Remote Repository](#createremote)
|
70
|
+
- [Read a Remote Repository as HTML](#read)
|
71
|
+
- [Update a Canvas Lesson from a Local Repository](#update)
|
72
|
+
- [Update a Canvas Lesson from a Remote Repository](#updateremote)
|
73
|
+
- [Retrieve Canvas Course Information as YAML Markdown](#query)
|
74
|
+
- [Map GitHub Repositories to a Canvas Course YAML file](#map)
|
75
|
+
- [Create New Canvas Course from a YAML file](#buildcourse)
|
76
|
+
- [Update Lessons in an Existing Course from a YAML file](#updatecourse)
|
77
|
+
|
78
|
+
### Creating and Updating Canvas Lessons
|
79
|
+
|
80
|
+
#### Create a Canvas Lesson from a Local Repository <a name="create"></a>
|
81
|
+
|
82
|
+
Navigate into a repository folder cloned down to your local machine and run:
|
83
|
+
|
84
|
+
```sh
|
85
|
+
github-to-canvas -c <CANVAS_COURSE_ID> -lr --forkable
|
86
|
+
```
|
87
|
+
|
88
|
+
The command above will create a Canvas lesson in the course provided. It will
|
89
|
+
also remove the repositories top-level header and remove any old Flatiron
|
90
|
+
branded footers. It will also add an HTML header for Canvas that includes links
|
91
|
+
back to the repository.
|
92
|
+
|
93
|
+
If the lesson type is an assignment, a Fork button will also be added to the
|
94
|
+
HTML header. Because the command didn't specify, the type of lesson is determined
|
95
|
+
based on the local repo structure - if it has sub-folders, the lesson will become
|
96
|
+
an assignment; if there are no sub-folders, the lesson will become a page. If the
|
97
|
+
lesson type is a page, the `--forkable` option will be ignored.
|
98
|
+
|
99
|
+
Creating a lesson this way will also produce a `.canvas` file. This file
|
100
|
+
contains info about the Canvas lesson that was created.
|
101
|
+
|
102
|
+
#### Create a Canvas Lesson from a Remote Repository <a name="createremote"></a>
|
103
|
+
|
104
|
+
To create from a remote repo, run the following command:
|
105
|
+
|
106
|
+
```sh
|
107
|
+
github-to-canvas --create-from-github <URL> --course <CANVAS_COURSE_ID> --type <TYPE> -lr --forkable
|
108
|
+
```
|
109
|
+
|
110
|
+
This command will read a GitHub markdown based on the provided URL and create a
|
111
|
+
Canvas lesson based on it. We need to provide the Course ID and the type of
|
112
|
+
lesson (`page` or `assignment`) as type can't be determined automatically. We'll
|
113
|
+
also continue to use `-lr --forkable` like the previous command to set up the
|
114
|
+
lesson the same way as before.
|
115
|
+
|
116
|
+
The repository must be public in order to read the markdown file.
|
69
117
|
|
70
|
-
|
118
|
+
#### Read a Remote Repository as HTML <a name="read"></a>
|
71
119
|
|
72
|
-
To
|
73
|
-
need to know the Canvas course id you are going to add to. This id can be found
|
74
|
-
in the URL of the course.
|
120
|
+
To read the contents of a remote repo:
|
75
121
|
|
76
|
-
|
122
|
+
```sh
|
123
|
+
github-to-canvas --read-from-github <URL>
|
124
|
+
```
|
125
|
+
|
126
|
+
This will produce an HTML conversion of the repository's markdwon. This HTML can
|
127
|
+
be directly pasted into Canvas' HTML editor if a manual process is needed.
|
77
128
|
|
78
|
-
|
79
|
-
2. Change directory into the new local repository
|
80
|
-
3. Run `github-to-canvas --create <your-course-id>` from inside the local repo
|
129
|
+
#### Update a Canvas Lesson from a Local Repository <a name="update"></a>
|
81
130
|
|
82
|
-
If
|
83
|
-
|
84
|
-
|
85
|
-
|
131
|
+
If you previously created a Canvas lesson from a local repository, you should
|
132
|
+
have a `.canvas` file present in the repo. If that file is present, you can run
|
133
|
+
the following command to update the listed Canvas lesson automatically:
|
134
|
+
|
135
|
+
```sh
|
136
|
+
github-to-canvas -a -lr --forkable
|
137
|
+
```
|
86
138
|
|
87
|
-
|
139
|
+
If you don't have or want to use the `.canvas` file, you can also specify the
|
140
|
+
course ID and lesson ID:
|
88
141
|
|
89
|
-
|
90
|
-
|
91
|
-
|
142
|
+
```sh
|
143
|
+
github-to-canvas -a --course <CANVAS_COURSE_ID> --id <CANVAS_LESSON_ID> -lr --forkable
|
144
|
+
```
|
92
145
|
|
93
|
-
|
94
|
-
Canvas data will be stored in the `.canvas` file.
|
146
|
+
Canvas course and lesson IDs can be found in the URL.
|
95
147
|
|
96
|
-
|
148
|
+
#### Update a Canvas Lesson from a Remote Repository <a name="updateremote"></a>
|
97
149
|
|
98
|
-
|
99
|
-
must be present in the repo**, as it contains the lesson information for the
|
100
|
-
Canvas API.
|
150
|
+
You can update an existing Canvas course using a remote GitHub repository like so:
|
101
151
|
|
102
|
-
|
103
|
-
|
152
|
+
```sh
|
153
|
+
github-to-canvas --align-from-github <URL> --course <COURSE_ID> --id <LESSON_ID> --type <TYPE> -lr --forkable
|
154
|
+
```
|
104
155
|
|
105
|
-
|
106
|
-
|
107
|
-
Canvas lessons included in the `.canvas` file, each lesson will be updated (i.e.
|
108
|
-
you have the same lesson in two courses created from one repository).
|
156
|
+
This will read remote markdown using the provided URL and update a Canvas course
|
157
|
+
using the info provided. Type must match the existing lesson type.
|
109
158
|
|
110
|
-
###
|
159
|
+
### Course Creation
|
111
160
|
|
112
|
-
This gem
|
161
|
+
This gem can create Canvas courses from scratch. These features
|
162
|
+
are still in development and may not work for all course designs. Quiz and
|
163
|
+
Discussion Topic lesson creation is still under development and will not work.
|
113
164
|
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
165
|
+
By providing a YAML file of the desired course structure, this gem can create a
|
166
|
+
course, add in modules, and populate those modules with pages and assignments.
|
167
|
+
The required YAML file must follow a specific structure. Using the steps below,
|
168
|
+
this gem can create the necessary YAML markup from existing Canvas courses.
|
169
|
+
|
170
|
+
#### Retrieve Canvas Course Information as YAML Markdown <a name="query"></a>
|
171
|
+
|
172
|
+
To create YAML markup of an existing Canvas course, use the following:
|
173
|
+
|
174
|
+
```sh
|
175
|
+
github-to-canvas --query <CANVAS_COURSE_ID>
|
176
|
+
```
|
177
|
+
|
178
|
+
This command will use the Canvas API to read a course's information, including
|
179
|
+
its module and lesson structure and lesson URLs. YAML markup will be produced as a result. This
|
180
|
+
output can be directly saved to a file, which will make the next step a little
|
181
|
+
easier:
|
182
|
+
|
183
|
+
```sh
|
184
|
+
github-to-canvas --query <CANVAS_COURSE_ID> > query_results.yml
|
185
|
+
```
|
186
|
+
|
187
|
+
The output will look similar to this:
|
188
|
+
|
189
|
+
```yml
|
190
|
+
---
|
191
|
+
:name: The Course's Title
|
192
|
+
:id: 111
|
193
|
+
:modules:
|
194
|
+
- :id: 2020
|
195
|
+
:name: First Module's Name
|
196
|
+
:lessons:
|
197
|
+
- id: slugified-page-name
|
198
|
+
title: This is the Title Of The First Lesson, a Page
|
199
|
+
indent: 0
|
200
|
+
type: Page
|
201
|
+
html_url: https://learning.flatironschool.com/courses/111/modules/items/27001
|
202
|
+
page_url: slugified-page-name
|
203
|
+
url: https://learning.flatironschool.com/api/v1/courses/111/pages/slugified-page-name
|
204
|
+
published: false
|
205
|
+
repository: ''
|
206
|
+
- id: 333
|
207
|
+
title: This is the Title Of The Second Lesson, an Assignment
|
208
|
+
indent: 1
|
209
|
+
type: Assignment
|
210
|
+
html_url: https://learning.flatironschool.com/courses/111/modules/items/27002
|
211
|
+
page_url: ''
|
212
|
+
url: https://learning.flatironschool.com/api/v1/courses/111/assignments/333
|
213
|
+
published: false
|
214
|
+
repository: ''
|
215
|
+
- :id: 2021
|
216
|
+
:name: Second Module's Name
|
217
|
+
:lessons:
|
218
|
+
```
|
219
|
+
|
220
|
+
The output YAML will not include associated GitHub repository information.
|
221
|
+
|
222
|
+
#### Map GitHub Repositories to a Canvas Course YAML file <a name="map"></a>
|
223
|
+
|
224
|
+
To associate repositories to an existing course YAML, the following command can be used:
|
225
|
+
|
226
|
+
```sh
|
227
|
+
github-to-canvas --map <YAML_FILE>
|
228
|
+
```
|
229
|
+
|
230
|
+
For this feature to work, all Canvas lessons must have the GitHub HTML header
|
231
|
+
that is added using `-l`. This header contains the necessary repo information.
|
232
|
+
|
233
|
+
Save the output YAML to another file if you want to use it for later course
|
234
|
+
creation. For example:
|
235
|
+
|
236
|
+
```sh
|
237
|
+
github-to-canvas --map query_results.yml > course_structure.yml
|
238
|
+
```
|
239
|
+
|
240
|
+
The resulting YAML file will contain course information, the module and lesson
|
241
|
+
structure, and each lesson's associated GitHub repository.
|
242
|
+
|
243
|
+
#### Create New Canvas Course from a YAML file <a name="buildcourse"></a>
|
244
|
+
|
245
|
+
To create a Canvas course with this gem, you will need a correctly structured
|
246
|
+
YAML file with the course info, modules, lessons and associated lesson
|
247
|
+
repositories. In addition, all lessons must have a type (`Page` or
|
248
|
+
`Assignment`), a repository, and a title. Other lesson options are currently
|
249
|
+
ignored.
|
250
|
+
|
251
|
+
With the necessary data configured, use the `--build-course` option and pass in
|
252
|
+
the course's YAML file:
|
253
|
+
|
254
|
+
```sh
|
255
|
+
github-to-canvas --build-course course_structure.yml -lr --forkable
|
256
|
+
```
|
257
|
+
|
258
|
+
This command will cause the following to happen:
|
259
|
+
|
260
|
+
- Create a Canvas course using the top level `:name:` in the YAML data
|
261
|
+
- Create the first module
|
262
|
+
- Create the first lesson using the repository, title and type, as well as additional command options
|
263
|
+
- Add the newly created lesson to the current module
|
264
|
+
- Create the second lesson and add it to the module...
|
265
|
+
- Repeate process until all modules and lessons are created
|
266
|
+
|
267
|
+
#### Update Lessons in an Existing Course from a YAML file <a name="updatecourse"></a>
|
268
|
+
|
269
|
+
The GitHub to Canvas gem can be used to update all lessons in a course
|
270
|
+
with a single command. To do this, you will need an up-to-date course YAML file with repositories
|
271
|
+
mapped to each lesson.
|
272
|
+
|
273
|
+
```sh
|
274
|
+
github-to-canvas --query <COURSE_ID> > query_results.yml
|
275
|
+
github-to-canvas --map query_results.yml > your_new_course.yml
|
276
|
+
```
|
277
|
+
|
278
|
+
Use the resulting file (in this example, `your_new_course.yml`) to update all lessons in
|
279
|
+
a course based on their GitHub repo:
|
280
|
+
|
281
|
+
```sh
|
282
|
+
github-to-canvas --update-course YAML_FILE -lr --forkable
|
283
|
+
```
|
284
|
+
|
285
|
+
The gem will iterate over the data and update every lesson according to the
|
286
|
+
associated repository.
|
287
|
+
|
288
|
+
## Known Issues
|
289
|
+
|
290
|
+
### HTML Code Snippets Do Not Render
|
291
|
+
|
292
|
+
The Canvas API renders all HTML it receives. If your repository's markdown
|
293
|
+
includes HTML that is not meant to be rendered, the content will be rendered as
|
294
|
+
part of the page's HTML, resulting in unusual display errors in Canvas. Examples of
|
295
|
+
this would be lessons on HTML or JavaScript that include HTML code snippets.
|
296
|
+
|
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 (``).
|
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.
|
330
|
+
|
331
|
+
The Canvas editor will treat the pasted HTML content as code and will
|
332
|
+
automatically replace some characters, escaping the code from the
|
333
|
+
normal rendering process.
|
334
|
+
|
335
|
+
Note that realigning after fixing this content may overwrite fixes.
|
336
|
+
|
337
|
+
### Multi-Line Code Snippets Render as a Single Line
|
338
|
+
|
339
|
+
The Github to Canvas gem uses an existing gem, Redcarpet, to handle the Markdown to HTML
|
340
|
+
conversion. This gem does not currently support multi-line codeblocks. This
|
341
|
+
functionality has been added in the Github to Canvas gem through monkeypatching.
|
342
|
+
This error should be resolved, but if you encounter code snippet rendering
|
343
|
+
issues, please open a new issue with a markdown example to replicate the error.
|
344
|
+
|
345
|
+
### Markdown Formatting Issues Cause Errors in Canvas
|
346
|
+
|
347
|
+
An empty line should separate individual markdown headers, paragraphs and code snippets
|
348
|
+
in the markdown. Without these empty lines, the contents will be interpretted as one
|
349
|
+
continuous paragraph and ignore formatting.
|
350
|
+
|
351
|
+
### New Repos That Use a `main` Branch
|
352
|
+
|
353
|
+
If you are using a new GitHub repository that uses a `main` branch, you may not be able to
|
354
|
+
create or update from a remote repository. You can still create and update from a local
|
355
|
+
repository by using the `--branch` (`-b`) option and specifying `main` as the branch.
|
356
|
+
|
357
|
+
A fix is planned for this issue, but not implemented.
|
358
|
+
|
359
|
+
## Overview of GitHub to Canvas workflows
|
360
|
+
|
361
|
+
Using this gem, you can maintain Canvas courses in multiple ways - either by
|
362
|
+
creating and updating individual Canvas lessons or through the YAML file process.
|
363
|
+
|
364
|
+
At Flatiron School, we use the Canvas blueprint course feature. We use the
|
365
|
+
github-to-canvas gem to update the blueprint copy of lessons. These updates will appear
|
366
|
+
in future copies of the course or when synced down associated courses in Canvas.
|
367
|
+
|
368
|
+

|
369
|
+
|
370
|
+
This can either be done with individual lessons or using a YAML files to keep
|
371
|
+
entire courses updated.
|
372
|
+
|
373
|
+
If you are using github-to-canvas in this way, changes should always be made on
|
374
|
+
the repository, not on Canvas. Any changes made only on Canvas will get
|
375
|
+
overwritten if the lesson is updated using the gem.
|
376
|
+
|
377
|
+
## Common Options
|
378
|
+
|
379
|
+
- `--create-lesson`, `-c`: Requires a Canvas course ID. Creates a new Canvas
|
380
|
+
lesson, converting the local repository's README.md to HTML. Adds `.canvas`
|
381
|
+
file to remote repository
|
382
|
+
- `--align`, `-a`: Updates a canvas lesson based on the local repository's
|
383
|
+
README.md. If no other options are used, `--align` will look for a `.canvas`
|
384
|
+
file to know what to lesson to update
|
385
|
+
- `--course`: Provide a specific course ID. When used with `--id`, this can
|
386
|
+
override the default behavior for `--align`, allowing you to update any
|
387
|
+
existing lesson and ignore the `.canvas` file if present.
|
388
|
+
- `--id`: Provide a specific lesson ID. This can be found in the URL of the
|
389
|
+
specific lesson. For Pages, used the slugified lesson title.
|
390
|
+
- `--type`: Sets the type of Canvas lesson to be created (page, assignment or
|
391
|
+
discussion). If no type, type decided based on repository structure.
|
392
|
+
- `--name`: Can be used to override default naming behavior. By default, Canvas
|
393
|
+
lesson names are determined by the first top-level (`#`) header in the
|
394
|
+
repository's markdown file.
|
395
|
+
- `--fis-links`, `-l`: Adds additional Flatiron School HTML header after
|
396
|
+
markdown conversion, including links back to the GitHub repo and it's issue
|
397
|
+
form.
|
398
|
+
- `--forkable`: Adds a **Fork** button to the Flatiron School HTML header. For
|
399
|
+
use with custom Canvas JS to enable Canvas assignment forking workflow for
|
400
|
+
Flatiron School students.
|
401
|
+
- `--remove-header-and-footer`, `-r`: Removes top lesson header and any Flatiron
|
402
|
+
School specific footer links before converting to HTML. Removing top lesson
|
403
|
+
header prevents duplicate titles while viewing in Canvas.
|
404
|
+
- `--create-from-github`: Requires a GitHub repository URL. Also requires
|
405
|
+
`--course` and `--type`. Creates a Canvas lesson, reading from the remote repo
|
406
|
+
instead of a local repository. Repository must be public.
|
407
|
+
- `--align-from-github`: Requires a GitHub repo URL, `--course`, `--id`, and
|
408
|
+
`--type`. Updates a Canvas lesson from a remote repository.
|
409
|
+
- `--read-from-github`: Requires a GitHub repo URL. Reads a remote repository
|
410
|
+
and converts its contents to HTML, but does not push to Canvas.
|
411
|
+
- `--branch`, `-b`: Can be used when creating or aligning with a local repo to
|
412
|
+
specify which branch to use. Use this if you have a new repository that uses a
|
413
|
+
`main` branch instead of `master`.
|
414
|
+
- `--save-to-github`, `-s`: If you are are creating or aligning content locally,
|
415
|
+
the `.canvas` file is not automatically committed to the repo. This option will
|
416
|
+
attempt to commit and push the `.canvas` file to the remote repository.
|
417
|
+
|
418
|
+
Run `github-to-canvas --help` for additional options not listed in this Readme.
|
126
419
|
|
127
420
|
## Examples of Valid Images This Gem Can Convert
|
128
421
|
|
422
|
+
This gem can convert both standard inline markdown and HTML images.
|
423
|
+
|
129
424
|
Inline Markdown:
|
130
425
|
|
131
426
|

|
data/bin/github-to-canvas
CHANGED
@@ -1,4 +1,7 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'byebug'
|
4
|
+
|
2
5
|
require 'optparse'
|
3
6
|
require 'github-to-canvas'
|
4
7
|
|
@@ -75,12 +78,15 @@ OptionParser.new do |opts|
|
|
75
78
|
end
|
76
79
|
opts.on("-tTYPE", "--type TYPE",
|
77
80
|
"Sets the type Canvas lesson to be created (page or assignment). If no type, type decided based on repository structure") do |type|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
81
|
+
# byebug
|
82
|
+
options[:type] = type.downcase
|
83
|
+
abort if type == 'quiz' || type == 'discussion'
|
84
|
+
# if type == 'page' || type == 'assignment' || type == 'discussion' || type == 'quiz' || type == 'Page' || type == 'Assignment' || type == 'Discussion' || type == 'Quiz'
|
85
|
+
|
86
|
+
# else
|
87
|
+
# puts "Invalid type. Defaulting to page"
|
88
|
+
# options[:type] = "page"
|
89
|
+
# end
|
84
90
|
end
|
85
91
|
opts.on("-fFILE", "--file FILE",
|
86
92
|
"Looks for and uses a markdown file in the currentt folder as source for conversion. Default file is README.md. Skips writing .canvas to repository") do |file|
|
@@ -102,6 +108,10 @@ OptionParser.new do |opts|
|
|
102
108
|
"Adds additional Flatiron School HTML after markdown conversion") do |f|
|
103
109
|
options[:fis] = true
|
104
110
|
end
|
111
|
+
opts.on("--aaq",
|
112
|
+
"Adds AAQ flag to HTML header appended with --fis-links") do |aaq|
|
113
|
+
options[:aaq] = aaq
|
114
|
+
end
|
105
115
|
opts.on("--forkable",
|
106
116
|
"Used with --fis-links, adds fork button to HTML header injected into Canvas lesson") do |remote|
|
107
117
|
options[:forkable] = true
|
@@ -130,6 +140,14 @@ OptionParser.new do |opts|
|
|
130
140
|
"REQUIRES -f or --file Associates canvas lessons with repositories. Use query to create required YAML file") do |file|
|
131
141
|
options[:map] = file
|
132
142
|
end
|
143
|
+
opts.on("--urls-only",
|
144
|
+
"Use with --map. Outputs repo URLs instead of YAML") do |urls|
|
145
|
+
options[:urls_only] = urls
|
146
|
+
end
|
147
|
+
# opts.on("--csv COURSE",
|
148
|
+
# "Returns a course's lesson struction as CSV") do |course|
|
149
|
+
# options[:csv] = course
|
150
|
+
# end
|
133
151
|
opts.on("--read-from-canvas CANVAS_URL",
|
134
152
|
"Retrieves an existing Canvas lesson using the provided URL") do |url|
|
135
153
|
options[:read_from_canvas] = url
|
@@ -142,10 +160,10 @@ OptionParser.new do |opts|
|
|
142
160
|
"Creates a new Canvas lesson from a remote GitHub Readme. --course and --type options required") do |url|
|
143
161
|
options[:create_from_github] = url
|
144
162
|
end
|
145
|
-
opts.on("--create-quiz-from-github GITHUB_URL",
|
146
|
-
|
147
|
-
|
148
|
-
|
163
|
+
# opts.on("--create-quiz-from-github GITHUB_URL",
|
164
|
+
# "Creates a new Canvas quiz from a remote GitHub YAML file. --course option required") do |url|
|
165
|
+
# options[:quiz_from_github] = url
|
166
|
+
# end
|
149
167
|
opts.on("--align-from-github GITHUB_URL",
|
150
168
|
"Aligns an existing Canvas lesson using a remote GitHub Readme. --course, --id, and --type options required") do |url|
|
151
169
|
options[:align_from_github] = url
|
@@ -162,6 +180,14 @@ OptionParser.new do |opts|
|
|
162
180
|
"Updates all lessons in a course using remote repos in provided YAML file") do |file|
|
163
181
|
options[:update_course_lessons] = file
|
164
182
|
end
|
183
|
+
opts.on("--clone-from-yaml YAML_FILE",
|
184
|
+
"Iterates over provided course YAML file and clones repos locally") do |file|
|
185
|
+
options[:clone_from_yaml] = file
|
186
|
+
end
|
187
|
+
opts.on("--contains-html",
|
188
|
+
"Escapes all HTML included in source markdown by replacing '<' and '>' with HTML charset values") do |html|
|
189
|
+
options[:contains_html] = html
|
190
|
+
end
|
165
191
|
|
166
192
|
end.parse!
|
167
193
|
|
@@ -171,12 +197,19 @@ if options[:version]
|
|
171
197
|
end
|
172
198
|
|
173
199
|
if options[:read_from_canvas]
|
174
|
-
GithubToCanvas.new(mode: 'canvas_read',
|
200
|
+
GithubToCanvas.new(mode: 'canvas_read',
|
201
|
+
filepath: options[:read_from_canvas])
|
175
202
|
abort
|
176
203
|
end
|
177
204
|
|
178
205
|
if options[:read_from_github]
|
179
|
-
GithubToCanvas.new(mode: 'github_read',
|
206
|
+
GithubToCanvas.new(mode: 'github_read',
|
207
|
+
filepath: options[:read_from_github],
|
208
|
+
remove_header_and_footer: !!options[:remove_header_and_footer],
|
209
|
+
forkable: !!options[:forkable],
|
210
|
+
fis_links: !!options[:fis],
|
211
|
+
aaq: !!options[:aaq],
|
212
|
+
contains_html: options[:contains_html])
|
180
213
|
abort
|
181
214
|
end
|
182
215
|
|
@@ -186,9 +219,12 @@ if options[:create_from_github]
|
|
186
219
|
filepath: options[:create_from_github],
|
187
220
|
course_id: options[:course_id],
|
188
221
|
type: options[:type],
|
222
|
+
name: options[:name],
|
189
223
|
remove_header_and_footer: !!options[:remove_header_and_footer],
|
190
224
|
forkable: !!options[:forkable],
|
191
|
-
fis_links: !!options[:fis]
|
225
|
+
fis_links: !!options[:fis],
|
226
|
+
aaq: !!options[:aaq],
|
227
|
+
contains_html: options[:contains_html])
|
192
228
|
else
|
193
229
|
puts 'Canvas course ID and lesson type required. Example: github-to-canvas --create-from-github URL --course ID --type TYPE'
|
194
230
|
end
|
@@ -202,9 +238,12 @@ if options[:align_from_github]
|
|
202
238
|
course_id: options[:course_id],
|
203
239
|
type: options[:type],
|
204
240
|
id: options[:id],
|
241
|
+
name: options[:name],
|
205
242
|
remove_header_and_footer: !!options[:remove_header_and_footer],
|
206
243
|
forkable: !!options[:forkable],
|
207
|
-
fis_links: !!options[:fis]
|
244
|
+
fis_links: !!options[:fis],
|
245
|
+
aaq: !!options[:aaq],
|
246
|
+
contains_html: options[:contains_html])
|
208
247
|
else
|
209
248
|
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'
|
210
249
|
end
|
@@ -217,7 +256,14 @@ if options[:query]
|
|
217
256
|
end
|
218
257
|
|
219
258
|
if options[:map]
|
220
|
-
GithubToCanvas.new(mode: 'map',
|
259
|
+
GithubToCanvas.new(mode: 'map',
|
260
|
+
file_to_convert: options[:map],
|
261
|
+
urls_only: !!options[:urls_only])
|
262
|
+
abort
|
263
|
+
end
|
264
|
+
|
265
|
+
if options[:csv]
|
266
|
+
GithubToCanvas.new(mode: 'csv', file_to_convert: options[:csv])
|
221
267
|
abort
|
222
268
|
end
|
223
269
|
|
@@ -226,6 +272,7 @@ if options[:build_course]
|
|
226
272
|
file_to_convert: options[:build_course],
|
227
273
|
fis_links: !!options[:fis],
|
228
274
|
remove_header_and_footer: !!options[:remove_header_and_footer],
|
275
|
+
aaq: !!options[:aaq],
|
229
276
|
forkable: !!options[:forkable])
|
230
277
|
abort
|
231
278
|
end
|
@@ -237,7 +284,9 @@ if options[:add_to_course]
|
|
237
284
|
file_to_convert: options[:add_to_course],
|
238
285
|
fis_links: !!options[:fis],
|
239
286
|
remove_header_and_footer: !!options[:remove_header_and_footer],
|
240
|
-
forkable: !!options[:forkable]
|
287
|
+
forkable: !!options[:forkable],
|
288
|
+
aaq: !!options[:aaq],
|
289
|
+
contains_html: options[:contains_html])
|
241
290
|
else
|
242
291
|
puts '--course required'
|
243
292
|
end
|
@@ -249,10 +298,17 @@ if options[:update_course_lessons]
|
|
249
298
|
file_to_convert: options[:update_course_lessons],
|
250
299
|
fis_links: !!options[:fis],
|
251
300
|
remove_header_and_footer: !!options[:remove_header_and_footer],
|
252
|
-
forkable: !!options[:forkable]
|
301
|
+
forkable: !!options[:forkable],
|
302
|
+
aaq: !!options[:aaq],
|
303
|
+
contains_html: options[:contains_html])
|
253
304
|
abort
|
254
305
|
end
|
255
306
|
|
307
|
+
if options[:clone_from_yaml]
|
308
|
+
GithubToCanvas.new(mode: 'clone_course',
|
309
|
+
file_to_convert: options[:clone_from_yaml])
|
310
|
+
abort
|
311
|
+
end
|
256
312
|
|
257
313
|
if !options[:type]
|
258
314
|
if Dir.glob("**/*/").empty?
|
@@ -306,7 +362,9 @@ if options[:create_lesson]
|
|
306
362
|
fis_links: !!options[:fis],
|
307
363
|
remove_header_and_footer: !!options[:remove_header_and_footer],
|
308
364
|
only_update_content: !!options[:only_content],
|
309
|
-
forkable: !!options[:forkable]
|
365
|
+
forkable: !!options[:forkable],
|
366
|
+
aaq: !!options[:aaq],
|
367
|
+
contains_html: options[:contains_html])
|
310
368
|
end
|
311
369
|
|
312
370
|
if options[:align]
|
@@ -322,5 +380,7 @@ if options[:align]
|
|
322
380
|
fis_links: !!options[:fis],
|
323
381
|
remove_header_and_footer: !!options[:remove_header_and_footer],
|
324
382
|
only_update_content: !!options[:only_content],
|
325
|
-
forkable: !!options[:forkable]
|
383
|
+
forkable: !!options[:forkable],
|
384
|
+
aaq: !!options[:aaq],
|
385
|
+
contains_html: options[:contains_html])
|
326
386
|
end
|
data/lib/github-to-canvas.rb
CHANGED
@@ -21,12 +21,14 @@ 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
|
24
|
+
CanvasInterface.map_course_info(options)
|
25
|
+
when 'csv'
|
26
|
+
CanvasInterface.csv(options[:file_to_convert])
|
25
27
|
when 'canvas_read'
|
26
28
|
puts CanvasInterface.read_lesson(options[:filepath])
|
27
29
|
when 'github_read'
|
28
|
-
|
29
|
-
puts RepositoryConverter.
|
30
|
+
html = RepositoryConverter.remote_file_conversion(options)
|
31
|
+
puts RepositoryConverter.adjust_converted_html(options, html)
|
30
32
|
when 'create' # used with a local repo
|
31
33
|
html = RepositoryConverter.local_file_conversion(options)
|
32
34
|
name = RepositoryInterface.get_name(options[:filepath], html)
|
@@ -36,13 +38,13 @@ class GithubToCanvas
|
|
36
38
|
puts "Canvas lesson created. Lesson available at #{response['html_url']}"
|
37
39
|
when 'align' # used with a local repo
|
38
40
|
html = RepositoryConverter.local_file_conversion(options)
|
39
|
-
name = RepositoryInterface.get_name(options[:filepath], html)
|
41
|
+
name = options[:name] ? options[:name] : RepositoryInterface.get_name(options[:filepath], html)
|
40
42
|
html = RepositoryConverter.adjust_converted_html(options, html)
|
41
43
|
CanvasInterface.update_all_related_lessons(options, name, html)
|
42
44
|
|
43
45
|
when 'github_create'
|
44
46
|
html = RepositoryConverter.remote_file_conversion(options)
|
45
|
-
name = RepositoryInterface.get_name(options[:filepath], html)
|
47
|
+
name = options[:name] ? options[:name] : RepositoryInterface.get_name(options[:filepath], html)
|
46
48
|
html = RepositoryConverter.adjust_converted_html(options, html)
|
47
49
|
|
48
50
|
response = CanvasInterface.create_lesson(options, name, html)
|
@@ -50,7 +52,7 @@ class GithubToCanvas
|
|
50
52
|
puts "Canvas lesson created. Lesson available at #{response['html_url']}"
|
51
53
|
when 'github_align'
|
52
54
|
html = RepositoryConverter.remote_file_conversion(options)
|
53
|
-
name = RepositoryInterface.get_name(options[:filepath], html)
|
55
|
+
name = options[:name] ? options[:name] : RepositoryInterface.get_name(options[:filepath], html)
|
54
56
|
html = RepositoryConverter.adjust_converted_html(options, html)
|
55
57
|
response = CanvasInterface.update_existing_lesson(options, name, html)
|
56
58
|
puts "Canvas lesson updated. Lesson available at #{response['html_url']}"
|
@@ -70,10 +72,8 @@ class GithubToCanvas
|
|
70
72
|
options[:course_id] = created_course_info["id"]
|
71
73
|
options[:filepath] = lesson["repository"]
|
72
74
|
|
73
|
-
|
74
75
|
html = RepositoryConverter.remote_file_conversion(options)
|
75
76
|
# Add each lesson to it's module
|
76
|
-
|
77
77
|
html = RepositoryConverter.adjust_converted_html(options, html)
|
78
78
|
created_lesson_info = CanvasInterface.create_lesson(options, lesson["title"], html)
|
79
79
|
lesson = lesson.merge(created_lesson_info)
|
@@ -134,6 +134,24 @@ class GithubToCanvas
|
|
134
134
|
sleep(1)
|
135
135
|
}
|
136
136
|
}
|
137
|
+
when 'clone_course'
|
138
|
+
course_yaml = YAML.load(File.read(options[:file_to_convert]))
|
139
|
+
new_dir = "#{course_yaml[:name].downcase.gsub(' ','-')}"
|
140
|
+
cmd = "mkdir #{new_dir}"
|
141
|
+
`#{cmd}`
|
142
|
+
course_yaml[:modules].each { |module_info|
|
143
|
+
puts "Cloning #{module_info[:name]}"
|
144
|
+
module_info[:lessons].each { |lesson|
|
145
|
+
if lesson["repository"] == ""
|
146
|
+
puts "No repository found for #{lesson['title']}"
|
147
|
+
next
|
148
|
+
else
|
149
|
+
cmd = "git clone #{lesson['repository']}"
|
150
|
+
puts cmd
|
151
|
+
GithubInterface.cd_into_and(new_dir, cmd)
|
152
|
+
end
|
153
|
+
}
|
154
|
+
}
|
137
155
|
else
|
138
156
|
puts VERSION
|
139
157
|
end
|
@@ -47,10 +47,6 @@ class CanvasInterface
|
|
47
47
|
JSON.parse(response.body)
|
48
48
|
end
|
49
49
|
|
50
|
-
def self.create_quiz(options, quiz_data)
|
51
|
-
|
52
|
-
end
|
53
|
-
|
54
50
|
def self.add_to_module(course_id, module_info, lesson_info)
|
55
51
|
# POST /api/v1/courses/:course_id/modules/:module_id/items
|
56
52
|
url = "#{ENV['CANVAS_API_PATH']}/courses/#{course_id}/modules/#{module_info["id"]}/items"
|
@@ -60,6 +56,7 @@ class CanvasInterface
|
|
60
56
|
'module_item[title]' => lesson_info["title"],
|
61
57
|
'module_item[type]' => lesson_info["type"],
|
62
58
|
'module_item[indent]' => 0,
|
59
|
+
'module_item[page_url]' => lesson_info["id"],
|
63
60
|
'module_item[completion_requirement][type]' => 'must_view'
|
64
61
|
}
|
65
62
|
elsif lesson_info["type"] == "Quiz"
|
@@ -70,19 +67,17 @@ class CanvasInterface
|
|
70
67
|
'module_item[title]' => lesson_info["title"],
|
71
68
|
'module_item[type]' => lesson_info["type"],
|
72
69
|
'module_item[indent]' => 1,
|
70
|
+
'module_item[content_id]' => lesson_info["id"],
|
73
71
|
'module_item[completion_requirement][type]' => 'must_submit'
|
74
72
|
}
|
75
73
|
end
|
76
74
|
begin
|
77
|
-
byebug
|
78
75
|
response = RestClient.post(url, payload, self.headers)
|
79
76
|
rescue
|
80
|
-
puts "Something went wrong while
|
81
|
-
puts "Something went wrong while
|
77
|
+
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
|
+
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"
|
82
79
|
abort
|
83
80
|
end
|
84
|
-
|
85
|
-
|
86
81
|
response
|
87
82
|
|
88
83
|
end
|
@@ -97,7 +92,7 @@ class CanvasInterface
|
|
97
92
|
|
98
93
|
begin
|
99
94
|
headers = self.headers
|
100
|
-
if options[:type] == 'page'
|
95
|
+
if options[:type] == 'page' || options[:type] == 'Page'
|
101
96
|
response = RestClient.get(url, headers)
|
102
97
|
lesson_info = JSON.parse(response)
|
103
98
|
url = url.sub(/[^\/]+$/, lesson_info["page_id"].to_s)
|
@@ -172,6 +167,7 @@ class CanvasInterface
|
|
172
167
|
[info, type]
|
173
168
|
end
|
174
169
|
|
170
|
+
|
175
171
|
def self.get_course_info(course, id)
|
176
172
|
if id
|
177
173
|
lesson_data = self.get_lesson_info(course, id)
|
@@ -197,6 +193,7 @@ class CanvasInterface
|
|
197
193
|
while !!index
|
198
194
|
url = "#{ENV['CANVAS_API_PATH']}/courses/#{course}/modules?page=#{index}&per_page=20"
|
199
195
|
index += 1
|
196
|
+
|
200
197
|
response = RestClient.get(url, self.headers)
|
201
198
|
modules = JSON.parse(response.body)
|
202
199
|
|
@@ -204,7 +201,7 @@ class CanvasInterface
|
|
204
201
|
course_info[:modules] = course_info[:modules] + modules
|
205
202
|
else
|
206
203
|
index = nil
|
207
|
-
end
|
204
|
+
end
|
208
205
|
end
|
209
206
|
|
210
207
|
course_info[:modules] = course_info[:modules].map do |mod|
|
@@ -217,11 +214,12 @@ class CanvasInterface
|
|
217
214
|
while !!index
|
218
215
|
url = "#{ENV['CANVAS_API_PATH']}/courses/#{course}/modules/#{mod['id']}/items?page=#{index}&per_page=20"
|
219
216
|
index += 1
|
220
|
-
response = RestClient.get(url, headers
|
221
|
-
"Authorization" => "Bearer #{ENV['CANVAS_API_KEY']}"
|
222
|
-
})
|
217
|
+
response = RestClient.get(url, self.headers)
|
223
218
|
lessons = JSON.parse(response.body)
|
224
219
|
lessons = lessons.map do |lesson|
|
220
|
+
if lesson["type"] == "ExternalUrl"
|
221
|
+
next
|
222
|
+
end
|
225
223
|
lesson = lesson.slice("id","title","name","indent","type","html_url","page_url","url","completion_requirement", "published")
|
226
224
|
lesson["repository"] = ""
|
227
225
|
lesson['id'] = lesson['url'].gsub(/^(.*[\\\/])/,'')
|
@@ -236,17 +234,18 @@ class CanvasInterface
|
|
236
234
|
end
|
237
235
|
new_mod
|
238
236
|
end
|
239
|
-
|
237
|
+
|
240
238
|
puts course_info.to_yaml
|
241
239
|
|
242
240
|
rescue
|
241
|
+
byebug
|
243
242
|
puts "Something went wrong while getting info about course #{course}"
|
244
243
|
abort
|
245
244
|
end
|
246
245
|
end
|
247
246
|
|
248
|
-
def self.map_course_info(
|
249
|
-
course_info = YAML.load(File.read("#{Dir.pwd}/#{file_to_convert}"))
|
247
|
+
def self.map_course_info(options)
|
248
|
+
course_info = YAML.load(File.read("#{Dir.pwd}/#{options[:file_to_convert]}"))
|
250
249
|
course_info[:modules] = course_info[:modules].map do |mod|
|
251
250
|
mod[:lessons] = mod[:lessons].map do |lesson|
|
252
251
|
|
@@ -282,6 +281,7 @@ class CanvasInterface
|
|
282
281
|
lesson["repository"] = repo
|
283
282
|
else
|
284
283
|
lesson["repository"] = "https://github.com/learn-co-curriculum/" + repo
|
284
|
+
puts lesson["repository"] if options[:urls_only]
|
285
285
|
end
|
286
286
|
end
|
287
287
|
sleep(1)
|
@@ -289,11 +289,55 @@ class CanvasInterface
|
|
289
289
|
end
|
290
290
|
mod
|
291
291
|
end
|
292
|
-
puts course_info.to_yaml
|
292
|
+
puts course_info.to_yaml if !options[:urls_only]
|
293
293
|
end
|
294
294
|
|
295
|
-
def self.
|
296
|
-
|
295
|
+
def self.csv(file_to_convert)
|
296
|
+
course_info = YAML.load(File.read("#{Dir.pwd}/#{file_to_convert}"))
|
297
|
+
course_info[:modules] = course_info[:modules].map do |mod|
|
298
|
+
mod[:lessons] = mod[:lessons].map do |lesson|
|
299
|
+
|
300
|
+
url = lesson["url"]
|
301
|
+
response = RestClient.get(url, headers={
|
302
|
+
"Authorization" => "Bearer #{ENV['CANVAS_API_KEY']}"
|
303
|
+
})
|
304
|
+
begin
|
305
|
+
lesson_data = JSON.parse(response)
|
306
|
+
contents = lesson_data["body"] if lesson["type"] == "Page"
|
307
|
+
contents = lesson_data["message"] if lesson["type"] == "Discussion"
|
308
|
+
contents = lesson_data["description"] if lesson["type"] == "Assignment" || lesson["type"] == "Quiz"
|
309
|
+
if contents.nil?
|
310
|
+
repo = ""
|
311
|
+
else
|
312
|
+
if contents[/data-repo=\"(.*?)"/]
|
313
|
+
repo = contents[/data-repo=\"(.*?)"/]
|
314
|
+
repo = repo.slice(11..-2)
|
315
|
+
elsif contents[/class=\"fis-git-link\" href=\"(.*?)"/]
|
316
|
+
repo = contents[/class=\"fis-git-link\" href=\"(.*?)"/]
|
317
|
+
repo = repo.slice(27..-2)
|
318
|
+
else
|
319
|
+
repo = ""
|
320
|
+
end
|
321
|
+
end
|
322
|
+
rescue
|
323
|
+
puts 'Error while mapping course info.'
|
324
|
+
abort
|
325
|
+
end
|
326
|
+
|
327
|
+
if repo != nil && repo != ""
|
328
|
+
if repo.include?('https://github.com/learn-co-curriculum/')
|
329
|
+
lesson["repository"] = repo
|
330
|
+
else
|
331
|
+
lesson["repository"] = "https://github.com/learn-co-curriculum/" + repo
|
332
|
+
end
|
333
|
+
end
|
334
|
+
sleep(1)
|
335
|
+
lesson
|
336
|
+
end
|
337
|
+
mod
|
338
|
+
end
|
339
|
+
byebug
|
340
|
+
puts course_info.to_yaml
|
297
341
|
end
|
298
342
|
|
299
343
|
|
@@ -1,4 +1,3 @@
|
|
1
|
-
require 'byebug'
|
2
1
|
require 'json'
|
3
2
|
require 'rest-client'
|
4
3
|
class GithubInterface
|
@@ -62,12 +61,13 @@ class GithubInterface
|
|
62
61
|
rescue
|
63
62
|
begin
|
64
63
|
response = RestClient.get(url_fallback)
|
64
|
+
return response.body
|
65
65
|
rescue
|
66
66
|
puts 'Error reading ' + url
|
67
67
|
end
|
68
68
|
end
|
69
69
|
|
70
|
-
|
70
|
+
|
71
71
|
end
|
72
72
|
|
73
73
|
def self.save_to_github(filepath, branch)
|
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'redcarpet'
|
2
|
-
require 'byebug'
|
3
2
|
|
4
3
|
class CustomRender < Redcarpet::Render::HTML
|
5
4
|
def block_code(code, lang)
|
@@ -18,7 +17,7 @@ class RepositoryConverter
|
|
18
17
|
GithubInterface.get_updated_repo(options[:filepath], options[:branch])
|
19
18
|
markdown = RepositoryInterface.read_local_file(options[:filepath], options[:file_to_convert])
|
20
19
|
raw_remote_url = self.set_raw_image_remote_url(options[:filepath])
|
21
|
-
|
20
|
+
markdown = self.escape_existing_html(markdown) if options[:contains_html]
|
22
21
|
markdown = self.fix_local_images(options, markdown, raw_remote_url)
|
23
22
|
html = self.convert_to_html(markdown)
|
24
23
|
# self.fix_local_html_links(options, html, options[:filepath])
|
@@ -27,6 +26,11 @@ class RepositoryConverter
|
|
27
26
|
def self.remote_file_conversion(options)
|
28
27
|
markdown = GithubInterface.read_remote(options[:filepath])
|
29
28
|
raw_remote_url = self.set_raw_image_remote_url(options[:filepath])
|
29
|
+
if options[:contains_html]
|
30
|
+
puts "Contains HTML"
|
31
|
+
puts options[:contains_html]
|
32
|
+
markdown = self.escape_existing_html(markdown)
|
33
|
+
end
|
30
34
|
markdown = self.fix_local_images(options, markdown, raw_remote_url)
|
31
35
|
html = self.convert_to_html(markdown)
|
32
36
|
# self.fix_local_html_links(options, html, options[:filepath])
|
@@ -47,9 +51,26 @@ class RepositoryConverter
|
|
47
51
|
if options[:fis_links]
|
48
52
|
html = self.add_fis_links(options, html)
|
49
53
|
end
|
54
|
+
|
55
|
+
if options[:contains_html]
|
56
|
+
html = self.fix_escaped_inline_html_code(html)
|
57
|
+
end
|
58
|
+
|
50
59
|
html
|
51
60
|
end
|
52
61
|
|
62
|
+
def self.fix_escaped_inline_html_code(html)
|
63
|
+
html = html.gsub("<code>&lt;", "<code><")
|
64
|
+
html = html.gsub("&gt;</code>", "></code>")
|
65
|
+
end
|
66
|
+
|
67
|
+
|
68
|
+
def self.escape_existing_html(markdown)
|
69
|
+
markdown = markdown.gsub(/<\/(?!iframe)/, "</")
|
70
|
+
markdown = markdown.gsub(/<(?!iframe)/, "<")
|
71
|
+
markdown = markdown.gsub(/(?<!iframe)>/, ">")
|
72
|
+
end
|
73
|
+
|
53
74
|
def self.remove_header_and_footer(html)
|
54
75
|
new_html = self.remove_html_header(html)
|
55
76
|
new_html = self.remove_footer(new_html)
|
@@ -57,7 +78,7 @@ class RepositoryConverter
|
|
57
78
|
end
|
58
79
|
|
59
80
|
def self.remove_header(readme)
|
60
|
-
readme.gsub
|
81
|
+
readme = readme.gsub(/^# .+?\n\n/,"")
|
61
82
|
readme.gsub(/^# .+?\n/,"")
|
62
83
|
end
|
63
84
|
|
@@ -115,7 +136,7 @@ class RepositoryConverter
|
|
115
136
|
end
|
116
137
|
|
117
138
|
def self.adjust_local_markdown_images(readme, raw_remote_url, branch)
|
118
|
-
readme.gsub
|
139
|
+
readme.gsub(/\!\[.+\]\(.+\)/) {|image_markdown|
|
119
140
|
if !image_markdown.match?('amazonaws.com') && !image_markdown.match?('https://') && !image_markdown.match?('http://') && !image_markdown.match?('youtube')
|
120
141
|
image_markdown.gsub!(/\(.+\)/) { |path|
|
121
142
|
path.delete_prefix!("(")
|
@@ -128,11 +149,12 @@ class RepositoryConverter
|
|
128
149
|
end
|
129
150
|
|
130
151
|
def self.adjust_local_html_images(readme, raw_remote_url, branch)
|
131
|
-
readme.gsub
|
132
|
-
|
133
|
-
|
134
|
-
image_source.gsub
|
135
|
-
image_source.
|
152
|
+
readme.gsub(/src=(\'|\")[\s\S]*?(\'|\")/) { |image_source|
|
153
|
+
|
154
|
+
if !image_source.match?('amazonaws.com') && !image_source.match?('https://') && !image_source.match?('http://') && !image_source.match?('youtube') && !image_source.match(/src=(\'|\")(?=<%)/)
|
155
|
+
image_source = image_source.gsub(/(\'|\")/, "")
|
156
|
+
image_source = image_source.gsub(/src=/, '')
|
157
|
+
image_source = image_source.strip
|
136
158
|
'src="' + raw_remote_url + '/' + branch + '/' + image_source + '"'
|
137
159
|
else
|
138
160
|
image_source
|
@@ -164,7 +186,7 @@ class RepositoryConverter
|
|
164
186
|
repo_info = self.get_repo_info(options[:filepath])
|
165
187
|
html = html.sub(/<div id="git-data-element.*<header class="fis-header.*<\/header>/,'') # remove existing fis header
|
166
188
|
header = self.create_github_link_header(repo_info[:repo_path], options[:forkable])
|
167
|
-
data_element = self.create_data_element(repo_info[:repo_org], repo_info[:repo_name])
|
189
|
+
data_element = self.create_data_element(repo_info[:repo_org], repo_info[:repo_name], options[:aaq])
|
168
190
|
data_element + header + html
|
169
191
|
end
|
170
192
|
|
@@ -184,8 +206,12 @@ class RepositoryConverter
|
|
184
206
|
end
|
185
207
|
end
|
186
208
|
|
187
|
-
def self.create_data_element(repo_org, repo_name)
|
188
|
-
|
209
|
+
def self.create_data_element(repo_org, repo_name, aaq)
|
210
|
+
if (aaq)
|
211
|
+
"<div id='git-data-element' data-aaq='enabled' data-org='#{repo_org}' data-repo='#{repo_name}'></div>"
|
212
|
+
else
|
213
|
+
"<div id='git-data-element' data-org='#{repo_org}' data-repo='#{repo_name}'></div>"
|
214
|
+
end
|
189
215
|
end
|
190
216
|
|
191
217
|
|
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.
|
4
|
+
version: 0.1.5
|
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.
|
111
|
+
rubygems_version: 3.0.8
|
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
|