canvas_link_migrator 0.2.0 → 1.0.1
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/lib/canvas_link_migrator/link_parser.rb +12 -2
- data/lib/canvas_link_migrator/link_resolver.rb +7 -5
- data/spec/canvas_link_migrator/imported_html_converter_spec.rb +22 -9
- data/spec/canvas_link_migrator/link_resolver_spec.rb +1 -1
- data/spec/fixtures/canvas_resource_map.json +24 -4
- metadata +18 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7d147093c7e6b397c3eb184aba4af1595f782e14735a50e9d4986be628af75f3
|
4
|
+
data.tar.gz: cb48c35f35dd333b02ff7dcba5e3bd79d1a1a7b736b7bb14c56de11b6c91565e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4074cbb1bfa20b00f4843327d62ee0e1cf739f7450b46698ee1a6a240054f27acd34046605e2ae4f54bbdf02b529272ba165769352e10abff1f5950c08af6ad8
|
7
|
+
data.tar.gz: e1deecf7b1d6586c432234092e338c9d3059f26b744072eab1cb6e644c25dbcec9ffacfb53239b6c9ffc0610c210bf80399f097f2d7efa2265686caf314a8fee
|
@@ -19,6 +19,7 @@
|
|
19
19
|
|
20
20
|
require "nokogiri"
|
21
21
|
require "digest"
|
22
|
+
require "addressable"
|
22
23
|
|
23
24
|
module CanvasLinkMigrator
|
24
25
|
class LinkParser
|
@@ -181,6 +182,14 @@ module CanvasLinkMigrator
|
|
181
182
|
|
182
183
|
# returns a hash with resolution status and data to hold onto if unresolved
|
183
184
|
def parse_url(url, node, attr)
|
185
|
+
parsed_url = Addressable::URI.parse(url)
|
186
|
+
query_values = parsed_url.query_values
|
187
|
+
media_attachment = query_values.try(:delete, "media_attachment") == "true"
|
188
|
+
if media_attachment
|
189
|
+
parsed_url.query_values = query_values.present? ? query_values : nil
|
190
|
+
url = Addressable::URI.unencode(parsed_url)
|
191
|
+
end
|
192
|
+
|
184
193
|
if url =~ /wiki_page_migration_id=(.*)/
|
185
194
|
unresolved(:wiki_page, migration_id: $1)
|
186
195
|
elsif url =~ /discussion_topic_migration_id=(.*)/
|
@@ -191,7 +200,8 @@ module CanvasLinkMigrator
|
|
191
200
|
unresolved(:file_ref,
|
192
201
|
migration_id: $1,
|
193
202
|
rest: $2,
|
194
|
-
in_media_iframe: attr == "src" && ["iframe", "source"].include?(node.name) && node["data-media-id"]
|
203
|
+
in_media_iframe: attr == "src" && ["iframe", "source"].include?(node.name) && node["data-media-id"],
|
204
|
+
media_attachment: media_attachment)
|
195
205
|
elsif url =~ %r{(?:\$CANVAS_OBJECT_REFERENCE\$|\$WIKI_REFERENCE\$)/([^/]*)/([^?]*)(\?.*)?}
|
196
206
|
if KNOWN_REFERENCE_TYPES.include?($1)
|
197
207
|
unresolved(:object, type: $1, migration_id: $2, query: $3)
|
@@ -207,7 +217,7 @@ module CanvasLinkMigrator
|
|
207
217
|
rel_path = URI::DEFAULT_PARSER.unescape($1)
|
208
218
|
if (attr == "href" && node["class"]&.include?("instructure_inline_media_comment")) ||
|
209
219
|
(attr == "src" && ["iframe", "source"].include?(node.name) && node["data-media-id"])
|
210
|
-
unresolved(:media_object, rel_path: rel_path)
|
220
|
+
unresolved(:media_object, rel_path: rel_path, media_attachment: media_attachment)
|
211
221
|
else
|
212
222
|
unresolved(:file, rel_path: rel_path)
|
213
223
|
end
|
@@ -68,7 +68,8 @@ module CanvasLinkMigrator
|
|
68
68
|
type = "pages" if type == "wiki"
|
69
69
|
if type == "pages"
|
70
70
|
query = resolve_module_item_query(nil, link[:query])
|
71
|
-
|
71
|
+
linked_wiki_url = @migration_id_converter.convert_wiki_page_migration_id_to_slug(migration_id) || migration_id
|
72
|
+
link[:new_value] = "#{context_path}/pages/#{linked_wiki_url}#{query}"
|
72
73
|
elsif type == "attachments"
|
73
74
|
att_id = @migration_id_converter.convert_attachment_migration_id(migration_id)
|
74
75
|
if att_id
|
@@ -91,7 +92,7 @@ module CanvasLinkMigrator
|
|
91
92
|
# see LinkParser for details
|
92
93
|
rel_path = link[:rel_path]
|
93
94
|
node = Nokogiri::HTML5.fragment(link[:old_value]).children.first
|
94
|
-
new_url = resolve_media_comment_data(node, rel_path)
|
95
|
+
new_url = resolve_media_comment_data(node, rel_path, link[:media_attachment])
|
95
96
|
new_url ||= resolve_relative_file_url(rel_path)
|
96
97
|
|
97
98
|
unless new_url
|
@@ -123,6 +124,8 @@ module CanvasLinkMigrator
|
|
123
124
|
# during a file fetch
|
124
125
|
if rest.include?("icon_maker_icon=1")
|
125
126
|
link[:new_value] = "/files/#{file_id}#{rest}"
|
127
|
+
elsif link[:in_media_iframe] && link[:media_attachment]
|
128
|
+
link[:new_value] = "/media_attachments_iframe/#{file_id}#{rest}"
|
126
129
|
else
|
127
130
|
link[:new_value] = "#{context_path}/files/#{file_id}#{rest}"
|
128
131
|
link[:new_value] = "/media_objects_iframe?mediahref=#{link[:new_value]}" if link[:in_media_iframe]
|
@@ -222,14 +225,13 @@ module CanvasLinkMigrator
|
|
222
225
|
url
|
223
226
|
end
|
224
227
|
|
225
|
-
def resolve_media_comment_data(node, rel_path)
|
228
|
+
def resolve_media_comment_data(node, rel_path, media_attachment)
|
226
229
|
if (file = find_file_in_context(rel_path[/^[^?]+/])) # strip query string for this search
|
227
230
|
media_id = file.try(:media_object)&.media_id || file["media_entry_id"]
|
228
231
|
if media_id && media_id != "maybe"
|
229
232
|
if ["iframe", "source"].include?(node.name)
|
230
233
|
node["data-media-id"] = media_id
|
231
|
-
if
|
232
|
-
node.delete("data-is-media-attachment")
|
234
|
+
if media_attachment
|
233
235
|
return media_attachment_iframe_url(file["id"], node["data-media-type"])
|
234
236
|
else
|
235
237
|
return media_iframe_url(media_id, node["data-media-type"])
|
@@ -37,6 +37,13 @@ describe CanvasLinkMigrator::ImportedHtmlConverter do
|
|
37
37
|
expect(bad_links).to be_nil
|
38
38
|
end
|
39
39
|
|
40
|
+
it "converts a wiki reference with migration id" do
|
41
|
+
test_string = %(<a href="%24WIKI_REFERENCE%24/pages/A?query=blah">Test Wiki Page</a>)
|
42
|
+
html, bad_links = @converter.convert_exported_html(test_string)
|
43
|
+
expect(html).to eq %(<a href="#{@path}pages/slug-a?query=blah">Test Wiki Page</a>)
|
44
|
+
expect(bad_links).to be_nil
|
45
|
+
end
|
46
|
+
|
40
47
|
context "when course attachments exist" do
|
41
48
|
subject { @converter.convert_exported_html(test_string) }
|
42
49
|
|
@@ -214,22 +221,28 @@ describe CanvasLinkMigrator::ImportedHtmlConverter do
|
|
214
221
|
end
|
215
222
|
|
216
223
|
it "converts source tags to RCE media attachment iframes" do
|
217
|
-
test_string = %(<video style="width: 400px; height: 225px; display: inline-block;" title="this is a media comment" data-media-type="video" allowfullscreen="allowfullscreen" allow="fullscreen" data-media-id="m-stuff"><source src="$
|
218
|
-
converted_string = %(<iframe style="width: 400px; height: 225px; display: inline-block;" title="this is a media comment" data-media-type="video" allowfullscreen="allowfullscreen" allow="fullscreen" data-media-id="m-
|
224
|
+
test_string = %(<video style="width: 400px; height: 225px; display: inline-block;" title="this is a media comment" data-media-type="video" allowfullscreen="allowfullscreen" allow="fullscreen" data-media-id="m-stuff"><source src="$IMS-CC-FILEBASE$/subfolder/with a space/yodawg.mov?canvas_=1&canvas_qs_type=video&canvas_qs_amp=&canvas_qs_embedded=true&media_attachment=true" data-media-id="m-stuff" data-media-type="video"></video>)
|
225
|
+
converted_string = %(<iframe style="width: 400px; height: 225px; display: inline-block;" title="this is a media comment" data-media-type="video" allowfullscreen="allowfullscreen" allow="fullscreen" data-media-id="m-yodawg" src="/media_attachments_iframe/9?type=video"></iframe>)
|
219
226
|
expect(@converter.convert_exported_html(test_string)).to eq([converted_string, nil])
|
220
227
|
|
221
|
-
test_string = %(<audio
|
222
|
-
converted_string = %(<iframe style="width: 400px; height: 225px; display: inline-block;" title="this is a media comment" data-media-type="audio" data-media-id="m-
|
228
|
+
test_string = %(<audio style="width: 400px; height: 225px; display: inline-block;" title="this is a media comment" data-media-type="audio" data-media-id="m-stuff"><source src="$IMS-CC-FILEBASE$/lolcat.mp3?canvas_=1&canvas_qs_type=audio&canvas_qs_amp=&canvas_qs_embedded=true&media_attachment=true" data-media-id="m-stuff" data-media-type="audio"></video>)
|
229
|
+
converted_string = %(<iframe style="width: 400px; height: 225px; display: inline-block;" title="this is a media comment" data-media-type="audio" data-media-id="m-lolcat" src="/media_attachments_iframe/8?type=audio"></iframe>)
|
223
230
|
expect(@converter.convert_exported_html(test_string)).to eq([converted_string, nil])
|
224
231
|
end
|
225
232
|
|
226
|
-
it "converts
|
227
|
-
test_string = %(<video style="width: 400px; height: 225px; display: inline-block;" title="this is a media comment" data-media-type="video" allowfullscreen="allowfullscreen" allow="fullscreen" data-media-id="m-
|
228
|
-
converted_string = %(<iframe style="width: 400px; height: 225px; display: inline-block;" title="this is a media comment" data-media-type="video" allowfullscreen="allowfullscreen" allow="fullscreen" data-media-id="m-
|
233
|
+
it "converts course copy style media attachmet iframe links" do
|
234
|
+
test_string = %(<video style="width: 400px; height: 225px; display: inline-block;" title="this is a media comment" data-media-type="video" allowfullscreen="allowfullscreen" allow="fullscreen" data-media-id="m-yodawg"><source src="$CANVAS_COURSE_REFERENCE$/file_ref/I?media_attachment=true&type=video" data-media-id="m-yodawg" data-media-type="video"></video>)
|
235
|
+
converted_string = %(<iframe style="width: 400px; height: 225px; display: inline-block;" title="this is a media comment" data-media-type="video" allowfullscreen="allowfullscreen" allow="fullscreen" data-media-id="m-yodawg" src="/media_attachments_iframe/9?type=video"></iframe>)
|
229
236
|
expect(@converter.convert_exported_html(test_string)).to eq([converted_string, nil])
|
230
237
|
|
231
|
-
test_string = %(<audio
|
232
|
-
converted_string = %(<iframe style="width: 400px; height: 225px; display: inline-block;" title="this is a media comment" data-media-type="audio" data-media-id="m-
|
238
|
+
test_string = %(<audio style="width: 400px; height: 225px; display: inline-block;" title="this is a media comment" data-media-type="audio" data-media-id="m-lolcat"><source src="$CANVAS_COURSE_REFERENCE$/file_ref/H?media_attachment=true&type=audio" data-media-id="m-lolcat" data-media-type="audio"></audio>)
|
239
|
+
converted_string = %(<iframe style="width: 400px; height: 225px; display: inline-block;" title="this is a media comment" data-media-type="audio" data-media-id="m-lolcat" src="/media_attachments_iframe/8?type=audio"></iframe>)
|
240
|
+
expect(@converter.convert_exported_html(test_string)).to eq([converted_string, nil])
|
241
|
+
end
|
242
|
+
|
243
|
+
it "converts mediahref iframes" do
|
244
|
+
test_string = %(<iframe data-media-type="video" src="/media_objects_iframe?mediahref=$CANVAS_COURSE_REFERENCE$/file_ref/I/download" data-media-id="m-yodawg"></iframe>)
|
245
|
+
converted_string = %(<iframe data-media-type="video" src="/media_objects_iframe?mediahref=/courses/2/files/9/download" data-media-id="m-yodawg"></iframe>)
|
233
246
|
expect(@converter.convert_exported_html(test_string)).to eq([converted_string, nil])
|
234
247
|
end
|
235
248
|
|
@@ -75,7 +75,7 @@ describe CanvasLinkMigrator::LinkResolver do
|
|
75
75
|
expect(link[:new_value]).to eq("/courses/2/modules/36?foo=bar")
|
76
76
|
end
|
77
77
|
|
78
|
-
it "
|
78
|
+
it "converts other links" do
|
79
79
|
link = { link_type: :object, type: "assignments", migration_id: "I", query: "#fie" }
|
80
80
|
resolver.resolve_link!(link)
|
81
81
|
expect(link[:new_value]).to eq("/courses/2/assignments/12#fie")
|
@@ -2,7 +2,9 @@
|
|
2
2
|
"attachment_path_id_lookup": {
|
3
3
|
"subfolder/test.png": "G",
|
4
4
|
"subfolder/with a space/test.png": "F",
|
5
|
+
"subfolder/with a space/yodawg.mov": "I",
|
5
6
|
"subfolder/withCapital/test.png": "migration_id!",
|
7
|
+
"lolcat.mp3": "H",
|
6
8
|
"test.png": "E"
|
7
9
|
},
|
8
10
|
"contains_migration_ids": true,
|
@@ -66,12 +68,30 @@
|
|
66
68
|
},
|
67
69
|
"G": {
|
68
70
|
"destination": {
|
69
|
-
"id": "7"
|
70
|
-
"media_entry_id": "m-stuff"
|
71
|
+
"id": "7"
|
71
72
|
},
|
72
73
|
"source": {
|
73
|
-
"id": "2"
|
74
|
-
|
74
|
+
"id": "2"
|
75
|
+
}
|
76
|
+
},
|
77
|
+
"H": {
|
78
|
+
"destination": {
|
79
|
+
"id": "8",
|
80
|
+
"media_entry_id": "m-lolcat"
|
81
|
+
},
|
82
|
+
"source": {
|
83
|
+
"id": "3",
|
84
|
+
"media_entry_id": "m-lolcat"
|
85
|
+
}
|
86
|
+
},
|
87
|
+
"I": {
|
88
|
+
"destination": {
|
89
|
+
"id": "9",
|
90
|
+
"media_entry_id": "m-yodawg"
|
91
|
+
},
|
92
|
+
"source": {
|
93
|
+
"id": "4",
|
94
|
+
"media_entry_id": "m-yodawg"
|
75
95
|
}
|
76
96
|
}
|
77
97
|
},
|
metadata
CHANGED
@@ -1,15 +1,16 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: canvas_link_migrator
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mysti Lilla
|
8
8
|
- James Logan
|
9
|
+
- Sarah Gerard
|
9
10
|
autorequire:
|
10
11
|
bindir: bin
|
11
12
|
cert_chain: []
|
12
|
-
date: 2023-
|
13
|
+
date: 2023-11-04 00:00:00.000000000 Z
|
13
14
|
dependencies:
|
14
15
|
- !ruby/object:Gem::Dependency
|
15
16
|
name: activesupport
|
@@ -53,6 +54,20 @@ dependencies:
|
|
53
54
|
- - ">="
|
54
55
|
- !ruby/object:Gem::Version
|
55
56
|
version: '0'
|
57
|
+
- !ruby/object:Gem::Dependency
|
58
|
+
name: addressable
|
59
|
+
requirement: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - ">="
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: '0'
|
64
|
+
type: :runtime
|
65
|
+
prerelease: false
|
66
|
+
version_requirements: !ruby/object:Gem::Requirement
|
67
|
+
requirements:
|
68
|
+
- - ">="
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: '0'
|
56
71
|
- !ruby/object:Gem::Dependency
|
57
72
|
name: bundler
|
58
73
|
requirement: !ruby/object:Gem::Requirement
|
@@ -113,6 +128,7 @@ description:
|
|
113
128
|
email:
|
114
129
|
- mysti@instructure.com
|
115
130
|
- james.logan@instructure.com
|
131
|
+
- sarah.gerard@instructure.com
|
116
132
|
executables: []
|
117
133
|
extensions: []
|
118
134
|
extra_rdoc_files: []
|