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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 989d0e7044ece5d052b909fa121de7f205906c733908a8dcf4a26d619cf67caf
4
- data.tar.gz: a065d7f5ad6ad400cbd7cf448f5d42c5b69d400d9123837d2517950059d4a70e
3
+ metadata.gz: 7d147093c7e6b397c3eb184aba4af1595f782e14735a50e9d4986be628af75f3
4
+ data.tar.gz: cb48c35f35dd333b02ff7dcba5e3bd79d1a1a7b736b7bb14c56de11b6c91565e
5
5
  SHA512:
6
- metadata.gz: 50b673e7a91c0f345455c0ef0027b9e05a84c973f35d75f5659d336dfb70a3385d04d3360bead41b16a5101e3f8ee5e054f881cab88ac3f7c3ec0d5387cb7c6c
7
- data.tar.gz: 8519365222facd8c05af020e7c6734db5c61e386cfd1fd0097f1a0815924c2c622929c217bfa4772d37fcd3acadd118019672cd9958ad76951512acd4bd8c4ba
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
- link[:new_value] = "#{context_path}/pages/#{migration_id}#{query}"
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 node["data-is-media-attachment"]
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="$CANVAS_OBJECT_REFERENCE$/media_attachments_iframe/E?type=video" data-media-id="m-stuff" data-media-type="video"></video>)
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-stuff" src="/media_attachments_iframe/5?type=video"></iframe>)
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 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="$CANVAS_OBJECT_REFERENCE$/media_attachments_iframe/E?type=audio" data-media-id="m-stuff" data-media-type="audio"></video>)
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-stuff" src="/media_attachments_iframe/5?type=audio"></iframe>)
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 source tags to RCE media attachment iframes when link is untranslated" do
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-stuff"><source src="/media_attachments_iframe/5?type=video" data-media-id="m-stuff" data-media-type="video"></video>)
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-stuff" src="/media_attachments_iframe/5?type=video"></iframe>)
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 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="/media_attachments_iframe/5?type=audio" data-media-id="m-stuff" data-media-type="audio"></video>)
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-stuff" src="/media_attachments_iframe/5?type=audio"></iframe>)
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 "converters other links" do
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
- "media_entry_id": "m-stuff"
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.2.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-08-01 00:00:00.000000000 Z
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: []