canvas_link_migrator 0.2.0 → 1.0.0

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: b03a701351cd4f8484cd257bdbbb3e4437ada4d39988d97230e48093e6a8c2a9
4
+ data.tar.gz: 2fadff9dc0f3a7c0d07ef2d7e79bd20f2e8c9ee14ccf71e4951c89417aa35659
5
5
  SHA512:
6
- metadata.gz: 50b673e7a91c0f345455c0ef0027b9e05a84c973f35d75f5659d336dfb70a3385d04d3360bead41b16a5101e3f8ee5e054f881cab88ac3f7c3ec0d5387cb7c6c
7
- data.tar.gz: 8519365222facd8c05af020e7c6734db5c61e386cfd1fd0097f1a0815924c2c622929c217bfa4772d37fcd3acadd118019672cd9958ad76951512acd4bd8c4ba
6
+ metadata.gz: 12d6e3e37c9d8115ce1e47712b0f6192a9d4d6617ec038d8d1b94eb3ec27996f4062d60c75b0b1f26b25675be1738a3dbe121fdc5707c182ca78751f7b47010d
7
+ data.tar.gz: e9fb1a26ea2aa9b9a24e799f407a05792b26c5743cd919e221e32309d20c49e603a51ec967bf28de51aba60954842793196024d74cae26f232ded871bb55725e
@@ -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,12 @@ 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
+ url = Addressable::URI.parse(url)
186
+ query_values = url.query_values || {}
187
+ media_attachment = query_values.delete("media_attachment") == "true"
188
+ url.query_values = query_values.present? ? query_values : nil
189
+ url = url.to_s
190
+
184
191
  if url =~ /wiki_page_migration_id=(.*)/
185
192
  unresolved(:wiki_page, migration_id: $1)
186
193
  elsif url =~ /discussion_topic_migration_id=(.*)/
@@ -191,7 +198,8 @@ module CanvasLinkMigrator
191
198
  unresolved(:file_ref,
192
199
  migration_id: $1,
193
200
  rest: $2,
194
- in_media_iframe: attr == "src" && ["iframe", "source"].include?(node.name) && node["data-media-id"])
201
+ in_media_iframe: attr == "src" && ["iframe", "source"].include?(node.name) && node["data-media-id"],
202
+ media_attachment: media_attachment)
195
203
  elsif url =~ %r{(?:\$CANVAS_OBJECT_REFERENCE\$|\$WIKI_REFERENCE\$)/([^/]*)/([^?]*)(\?.*)?}
196
204
  if KNOWN_REFERENCE_TYPES.include?($1)
197
205
  unresolved(:object, type: $1, migration_id: $2, query: $3)
@@ -207,7 +215,7 @@ module CanvasLinkMigrator
207
215
  rel_path = URI::DEFAULT_PARSER.unescape($1)
208
216
  if (attr == "href" && node["class"]&.include?("instructure_inline_media_comment")) ||
209
217
  (attr == "src" && ["iframe", "source"].include?(node.name) && node["data-media-id"])
210
- unresolved(:media_object, rel_path: rel_path)
218
+ unresolved(:media_object, rel_path: rel_path, media_attachment: media_attachment)
211
219
  else
212
220
  unresolved(:file, rel_path: rel_path)
213
221
  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
@@ -121,12 +122,15 @@ module CanvasLinkMigrator
121
122
  # context prepended to the URL. This prevents
122
123
  # redirects to non cross-origin friendly urls
123
124
  # during a file fetch
124
- if rest.include?("icon_maker_icon=1")
125
- link[:new_value] = "/files/#{file_id}#{rest}"
126
- else
127
- link[:new_value] = "#{context_path}/files/#{file_id}#{rest}"
128
- link[:new_value] = "/media_objects_iframe?mediahref=#{link[:new_value]}" if link[:in_media_iframe]
129
- end
125
+ link[:new_value] = if rest.include?("icon_maker_icon=1")
126
+ "/files/#{file_id}#{rest}"
127
+ elsif link[:in_media_iframe] && link[:media_attachment]
128
+ "/media_attachments_iframe/#{file_id}#{rest}"
129
+ elsif link[:in_media_iframe]
130
+ "/media_objects_iframe?mediahref=#{link[:new_value]}"
131
+ else
132
+ "#{context_path}/files/#{file_id}#{rest}"
133
+ end
130
134
  end
131
135
  else
132
136
  raise "unrecognized link_type (#{link[:link_type]}) in unresolved link"
@@ -222,14 +226,13 @@ module CanvasLinkMigrator
222
226
  url
223
227
  end
224
228
 
225
- def resolve_media_comment_data(node, rel_path)
229
+ def resolve_media_comment_data(node, rel_path, media_attachment)
226
230
  if (file = find_file_in_context(rel_path[/^[^?]+/])) # strip query string for this search
227
231
  media_id = file.try(:media_object)&.media_id || file["media_entry_id"]
228
232
  if media_id && media_id != "maybe"
229
233
  if ["iframe", "source"].include?(node.name)
230
234
  node["data-media-id"] = media_id
231
- if node["data-is-media-attachment"]
232
- node.delete("data-is-media-attachment")
235
+ if media_attachment
233
236
  return media_attachment_iframe_url(file["id"], node["data-media-type"])
234
237
  else
235
238
  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,22 @@ 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>)
233
240
  expect(@converter.convert_exported_html(test_string)).to eq([converted_string, nil])
234
241
  end
235
242
 
@@ -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.0
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-02 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: []