@instructure/canvas-rce 5.14.0 → 5.14.2

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.
Files changed (484) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/DEVELOPMENT.md +1 -1
  3. package/README.md +0 -8
  4. package/__tests__/common/indicate.test.js +84 -0
  5. package/__tests__/common/mimeClass.test.js +85 -0
  6. package/__tests__/module/contentInsertionUtils.test.js +52 -0
  7. package/__tests__/module/indicatorRegion.test.js +75 -0
  8. package/__tests__/module/normalizeLocale.test.js +46 -0
  9. package/__tests__/module/normalizeProps.test.js +51 -0
  10. package/__tests__/module/sanitizePlugins.test.js +48 -0
  11. package/__tests__/module/wrapInitCb.test.js +56 -0
  12. package/__tests__/rcs/api.test.js +819 -0
  13. package/{mocha-reporter-config.js → __tests__/sidebar/actions/all_files.test.js} +10 -9
  14. package/__tests__/sidebar/actions/data.test.js +196 -0
  15. package/__tests__/sidebar/actions/utils.js +44 -0
  16. package/__tests__/sidebar/reducers/all_files.test.js +28 -0
  17. package/babel.config.js +3 -1
  18. package/build.sh +7 -7
  19. package/es/bridge/Bridge.js +8 -56
  20. package/es/bridge/index.js +1 -0
  21. package/es/canvasFileBrowser/FileBrowser.js +12 -59
  22. package/es/canvasFileBrowser/en-US.js +3 -6
  23. package/es/common/FlashAlert.js +7 -28
  24. package/es/common/browser.js +4 -2
  25. package/es/common/fileUrl.js +104 -59
  26. package/es/common/incremental-loading/LoadMoreButton.js +1 -0
  27. package/es/common/incremental-loading/LoadingIndicator.js +1 -2
  28. package/es/common/incremental-loading/LoadingStatus.js +1 -2
  29. package/es/common/incremental-loading/index.js +1 -0
  30. package/es/common/incremental-loading/useIncrementalLoading.js +1 -3
  31. package/es/common/indicate.js +15 -8
  32. package/es/common/mimeClass.js +3 -4
  33. package/es/common/natcompare.js +1 -4
  34. package/es/defaultTinymceConfig.js +5 -3
  35. package/es/elementDenylist.js +1 -0
  36. package/es/enhance-user-content/doc_previews.js +17 -28
  37. package/es/enhance-user-content/enhance_user_content.js +28 -60
  38. package/es/enhance-user-content/external_links.js +5 -8
  39. package/es/enhance-user-content/index.js +1 -0
  40. package/es/enhance-user-content/instructure_helper.js +25 -38
  41. package/es/enhance-user-content/jqueryish_funcs.js +8 -11
  42. package/es/enhance-user-content/mathml.js +35 -82
  43. package/es/enhance-user-content/media_comment_thumbnail.js +5 -17
  44. package/es/format-message.js +3 -4
  45. package/es/getThemeVars.js +8 -6
  46. package/es/getTranslations.js +1 -78
  47. package/es/index.js +3 -1
  48. package/es/rce/AlertMessageArea.js +1 -1
  49. package/es/rce/DraggingBlocker.js +4 -2
  50. package/es/rce/KeyboardShortcutModal.js +1 -0
  51. package/es/rce/RCE.js +12 -11
  52. package/es/rce/RCEGlobals.js +12 -10
  53. package/es/rce/RCEVariants.js +27 -10
  54. package/es/rce/RCEWrapper.js +167 -386
  55. package/es/rce/RCEWrapperProps.js +8 -3
  56. package/es/rce/RceHtmlEditor.js +5 -8
  57. package/es/rce/ResizeHandle.js +3 -8
  58. package/es/rce/RestoreAutoSaveModal.js +1 -2
  59. package/es/rce/ShowOnFocusButton/index.js +0 -6
  60. package/es/rce/StatusBar.js +8 -37
  61. package/es/rce/alertHandler.js +1 -4
  62. package/es/rce/contentInsertion.js +35 -57
  63. package/es/rce/contentInsertionUtils.js +6 -8
  64. package/es/rce/contentRendering.js +7 -12
  65. package/es/rce/customEvents.js +1 -0
  66. package/es/rce/editorLanguage.js +22 -10
  67. package/es/rce/indicatorRegion.js +6 -5
  68. package/es/rce/normalizeLocale.js +5 -3
  69. package/es/rce/normalizeProps.js +3 -1
  70. package/es/rce/plugins/instructure-ui-icons/plugin.js +21 -3
  71. package/es/rce/plugins/instructure_color/clickCallback.js +84 -0
  72. package/es/rce/plugins/instructure_color/components/ColorPicker.js +299 -0
  73. package/es/rce/plugins/instructure_color/components/ColorPopup.js +68 -0
  74. package/es/rce/plugins/instructure_color/components/colorUtils.js +60 -0
  75. package/es/rce/plugins/instructure_color/plugin.js +40 -0
  76. package/es/rce/plugins/instructure_condensed_buttons/core/ListUtils.js +10 -3
  77. package/es/rce/plugins/instructure_condensed_buttons/plugin.js +1 -0
  78. package/es/rce/plugins/instructure_condensed_buttons/ui/alignment-button.js +1 -2
  79. package/es/rce/plugins/instructure_condensed_buttons/ui/directionality-button.js +3 -2
  80. package/es/rce/plugins/instructure_condensed_buttons/ui/indent-outdent-button.js +1 -0
  81. package/es/rce/plugins/instructure_condensed_buttons/ui/list-button.js +22 -15
  82. package/es/rce/plugins/instructure_condensed_buttons/ui/subscript-superscript-button.js +1 -2
  83. package/es/rce/plugins/instructure_documents/clickCallback.js +1 -0
  84. package/es/rce/plugins/instructure_documents/components/DocumentsPanel.js +1 -9
  85. package/es/rce/plugins/instructure_documents/components/Link.js +3 -18
  86. package/es/rce/plugins/instructure_documents/plugin.js +7 -14
  87. package/es/rce/plugins/instructure_equation/EquationEditorModal/advancedOnlySyntax.js +4 -2
  88. package/es/rce/plugins/instructure_equation/EquationEditorModal/advancedPreference.js +1 -2
  89. package/es/rce/plugins/instructure_equation/EquationEditorModal/index.js +12 -29
  90. package/es/rce/plugins/instructure_equation/EquationEditorModal/latexTextareaUtil.js +11 -12
  91. package/es/rce/plugins/instructure_equation/EquationEditorModal/parseLatex.js +4 -3
  92. package/es/rce/plugins/instructure_equation/EquationEditorModal/styles.js +4 -2
  93. package/es/rce/plugins/instructure_equation/EquationEditorToolbar/buttons.js +13 -7
  94. package/es/rce/plugins/instructure_equation/EquationEditorToolbar/index.js +4 -7
  95. package/es/rce/plugins/instructure_equation/MathIcon/index.js +1 -1
  96. package/es/rce/plugins/instructure_equation/MathIcon/svgs.js +1 -1
  97. package/es/rce/plugins/instructure_equation/clickCallback.js +2 -5
  98. package/es/rce/plugins/instructure_equation/mathlive/index.js +1 -1
  99. package/es/rce/plugins/instructure_equation/plugin.js +7 -10
  100. package/es/rce/plugins/instructure_fullscreen/plugin.js +3 -6
  101. package/es/rce/plugins/instructure_html_view/clickCallback.js +1 -0
  102. package/es/rce/plugins/instructure_html_view/plugin.js +5 -4
  103. package/es/rce/plugins/instructure_icon_maker/clickCallback.js +2 -4
  104. package/es/rce/plugins/instructure_icon_maker/components/CreateIconMakerForm/ColorSection.js +1 -2
  105. package/es/rce/plugins/instructure_icon_maker/components/CreateIconMakerForm/CreateIconMakerForm.js +1 -0
  106. package/es/rce/plugins/instructure_icon_maker/components/CreateIconMakerForm/Footer.js +1 -0
  107. package/es/rce/plugins/instructure_icon_maker/components/CreateIconMakerForm/Group.js +1 -0
  108. package/es/rce/plugins/instructure_icon_maker/components/CreateIconMakerForm/Header.js +1 -2
  109. package/es/rce/plugins/instructure_icon_maker/components/CreateIconMakerForm/ImageSection/Course.js +25 -22
  110. package/es/rce/plugins/instructure_icon_maker/components/CreateIconMakerForm/ImageSection/ImageOptions.js +7 -11
  111. package/es/rce/plugins/instructure_icon_maker/components/CreateIconMakerForm/ImageSection/ImageSection.js +27 -23
  112. package/es/rce/plugins/instructure_icon_maker/components/CreateIconMakerForm/ImageSection/ModeSelect.js +5 -4
  113. package/es/rce/plugins/instructure_icon_maker/components/CreateIconMakerForm/ImageSection/MultiColor/index.js +11 -9
  114. package/es/rce/plugins/instructure_icon_maker/components/CreateIconMakerForm/ImageSection/MultiColor/svg.js +1 -0
  115. package/es/rce/plugins/instructure_icon_maker/components/CreateIconMakerForm/ImageSection/SVGList.js +5 -4
  116. package/es/rce/plugins/instructure_icon_maker/components/CreateIconMakerForm/ImageSection/SVGThumbnail.js +1 -3
  117. package/es/rce/plugins/instructure_icon_maker/components/CreateIconMakerForm/ImageSection/SingleColor/index.js +7 -7
  118. package/es/rce/plugins/instructure_icon_maker/components/CreateIconMakerForm/ImageSection/SingleColor/svg.js +1 -0
  119. package/es/rce/plugins/instructure_icon_maker/components/CreateIconMakerForm/ImageSection/Upload.js +27 -20
  120. package/es/rce/plugins/instructure_icon_maker/components/CreateIconMakerForm/ImageSection/index.js +1 -0
  121. package/es/rce/plugins/instructure_icon_maker/components/CreateIconMakerForm/ImageSection/propTypes.js +1 -0
  122. package/es/rce/plugins/instructure_icon_maker/components/CreateIconMakerForm/ImageSection/utils.js +1 -0
  123. package/es/rce/plugins/instructure_icon_maker/components/CreateIconMakerForm/Preview.js +4 -4
  124. package/es/rce/plugins/instructure_icon_maker/components/CreateIconMakerForm/ShapeSection.js +1 -2
  125. package/es/rce/plugins/instructure_icon_maker/components/CreateIconMakerForm/TextSection.js +1 -5
  126. package/es/rce/plugins/instructure_icon_maker/components/CreateIconMakerForm/index.js +1 -0
  127. package/es/rce/plugins/instructure_icon_maker/components/IconMakerTray.js +18 -33
  128. package/es/rce/plugins/instructure_icon_maker/components/SavedIconMakerList.js +4 -4
  129. package/es/rce/plugins/instructure_icon_maker/plugin.js +10 -14
  130. package/es/rce/plugins/instructure_icon_maker/reducers/imageSection.js +37 -38
  131. package/es/rce/plugins/instructure_icon_maker/reducers/svgSettings.js +24 -24
  132. package/es/rce/plugins/instructure_icon_maker/registerEditToolbar.js +1 -3
  133. package/es/rce/plugins/instructure_icon_maker/svg/constants.js +4 -3
  134. package/es/rce/plugins/instructure_icon_maker/svg/font.js +3 -1
  135. package/es/rce/plugins/instructure_icon_maker/svg/image.js +69 -83
  136. package/es/rce/plugins/instructure_icon_maker/svg/index.js +11 -15
  137. package/es/rce/plugins/instructure_icon_maker/svg/metadata.js +1 -0
  138. package/es/rce/plugins/instructure_icon_maker/svg/settings.js +32 -39
  139. package/es/rce/plugins/instructure_icon_maker/svg/shape.js +1 -49
  140. package/es/rce/plugins/instructure_icon_maker/svg/text.js +7 -92
  141. package/es/rce/plugins/instructure_icon_maker/svg/utils.js +1 -7
  142. package/es/rce/plugins/instructure_icon_maker/utils/IconMakerClose.js +2 -6
  143. package/es/rce/plugins/instructure_icon_maker/utils/IconMakerFormHasChanges.js +1 -15
  144. package/es/rce/plugins/instructure_icon_maker/utils/addIconMakerAttributes.js +3 -4
  145. package/es/rce/plugins/instructure_icon_maker/utils/iconValidation.js +1 -1
  146. package/es/rce/plugins/instructure_icon_maker/utils/iconsLabels.js +1 -0
  147. package/es/rce/plugins/instructure_icon_maker/utils/useDebouncedValue.js +12 -13
  148. package/es/rce/plugins/instructure_image/ImageEmbedOptions.js +6 -24
  149. package/es/rce/plugins/instructure_image/ImageList/Image.js +1 -6
  150. package/es/rce/plugins/instructure_image/ImageList/index.js +1 -2
  151. package/es/rce/plugins/instructure_image/ImageOptionsTray/TrayController.js +7 -27
  152. package/es/rce/plugins/instructure_image/ImageOptionsTray/index.js +3 -16
  153. package/es/rce/plugins/instructure_image/Images/index.js +1 -3
  154. package/es/rce/plugins/instructure_image/clickCallback.js +1 -0
  155. package/es/rce/plugins/instructure_image/plugin.js +13 -18
  156. package/es/rce/plugins/instructure_links/clickCallback.js +1 -0
  157. package/es/rce/plugins/instructure_links/components/AccordionSection.js +1 -0
  158. package/es/rce/plugins/instructure_links/components/CollectionPanel.js +1 -3
  159. package/es/rce/plugins/instructure_links/components/Link.js +7 -19
  160. package/es/rce/plugins/instructure_links/components/LinkOptionsDialog/LinkOptionsDialogController.js +1 -21
  161. package/es/rce/plugins/instructure_links/components/LinkOptionsDialog/index.js +1 -4
  162. package/es/rce/plugins/instructure_links/components/LinkOptionsTray/LinkOptionsTrayController.js +3 -20
  163. package/es/rce/plugins/instructure_links/components/LinkOptionsTray/index.js +1 -12
  164. package/es/rce/plugins/instructure_links/components/LinkSet.js +4 -20
  165. package/es/rce/plugins/instructure_links/components/LinksPanel.js +1 -2
  166. package/es/rce/plugins/instructure_links/components/NavigationPanel.js +7 -9
  167. package/es/rce/plugins/instructure_links/components/NoResults.js +1 -7
  168. package/es/rce/plugins/instructure_links/plugin.js +17 -40
  169. package/es/rce/plugins/instructure_links/validateURL.js +81 -36
  170. package/es/rce/plugins/instructure_media_embed/clickCallback.js +2 -5
  171. package/es/rce/plugins/instructure_media_embed/components/Embed.js +1 -0
  172. package/es/rce/plugins/instructure_media_embed/plugin.js +7 -3
  173. package/es/rce/plugins/instructure_paste/pasteMenuCommand.js +1 -5
  174. package/es/rce/plugins/instructure_paste/plugin.js +27 -29
  175. package/es/rce/plugins/instructure_rce_external_tools/ExternalToolsEnv.js +14 -53
  176. package/es/rce/plugins/instructure_rce_external_tools/RceToolWrapper.js +21 -49
  177. package/es/rce/plugins/instructure_rce_external_tools/components/ExternalToolDialog/ExternalToolDialog.js +11 -42
  178. package/es/rce/plugins/instructure_rce_external_tools/components/ExternalToolDialog/ExternalToolDialogModal.js +1 -2
  179. package/es/rce/plugins/instructure_rce_external_tools/components/ExternalToolDialog/ExternalToolDialogTray.js +1 -1
  180. package/es/rce/plugins/instructure_rce_external_tools/components/ExternalToolSelectionDialog/ExternalToolSelectionDialog.js +2 -10
  181. package/es/rce/plugins/instructure_rce_external_tools/components/ExternalToolSelectionDialog/ExternalToolSelectionItem.js +1 -2
  182. package/es/rce/plugins/instructure_rce_external_tools/components/util/ExpandoText.js +1 -0
  183. package/es/rce/plugins/instructure_rce_external_tools/components/util/ToolLaunchIframe.js +2 -1
  184. package/es/rce/plugins/instructure_rce_external_tools/constants.js +28 -0
  185. package/es/rce/plugins/instructure_rce_external_tools/dialog-helper.js +19 -4
  186. package/es/rce/plugins/instructure_rce_external_tools/helpers/tags.js +0 -2
  187. package/es/rce/plugins/instructure_rce_external_tools/jquery/jquery.dropdownList.js +130 -136
  188. package/es/rce/plugins/instructure_rce_external_tools/lti11-content-items/RceLti11ContentItem.js +100 -95
  189. package/es/rce/plugins/instructure_rce_external_tools/lti13-content-items/Lti13ContentItemJson.js +1 -0
  190. package/es/rce/plugins/instructure_rce_external_tools/lti13-content-items/RceLti13ContentItem.js +2 -19
  191. package/es/rce/plugins/instructure_rce_external_tools/lti13-content-items/models/BaseLinkContentItem.js +1 -14
  192. package/es/rce/plugins/instructure_rce_external_tools/lti13-content-items/models/HtmlFragmentContentItem.js +1 -6
  193. package/es/rce/plugins/instructure_rce_external_tools/lti13-content-items/models/ImageContentItem.js +1 -9
  194. package/es/rce/plugins/instructure_rce_external_tools/lti13-content-items/models/LinkContentItem.js +1 -1
  195. package/es/rce/plugins/instructure_rce_external_tools/lti13-content-items/models/ResourceLinkContentItem.js +3 -5
  196. package/es/rce/plugins/instructure_rce_external_tools/lti13-content-items/processEditorContentItems.js +18 -10
  197. package/es/rce/plugins/instructure_rce_external_tools/lti13-content-items/rceLti13ContentItemFromJson.js +4 -4
  198. package/es/rce/plugins/instructure_rce_external_tools/plugin.js +7 -16
  199. package/es/rce/plugins/instructure_rce_external_tools/util/addParentFrameContextToUrl.js +1 -1
  200. package/es/rce/plugins/instructure_record/AudioOptionsTray/TrayController.js +1 -25
  201. package/es/rce/plugins/instructure_record/AudioOptionsTray/index.js +1 -4
  202. package/es/rce/plugins/instructure_record/MediaPanel/index.js +1 -9
  203. package/es/rce/plugins/instructure_record/VideoOptionsTray/TrayController.js +8 -51
  204. package/es/rce/plugins/instructure_record/VideoOptionsTray/index.js +4 -17
  205. package/es/rce/plugins/instructure_record/clickCallback.js +7 -15
  206. package/es/rce/plugins/instructure_record/mediaTranslations.js +1 -0
  207. package/es/rce/plugins/instructure_record/plugin.js +11 -18
  208. package/es/rce/plugins/instructure_search_and_replace/clickCallback.js +2 -5
  209. package/es/rce/plugins/instructure_search_and_replace/components/FindReplaceTray.js +20 -35
  210. package/es/rce/plugins/instructure_search_and_replace/components/FindReplaceTrayController.js +3 -18
  211. package/es/rce/plugins/instructure_search_and_replace/getSelectionContext.js +2 -9
  212. package/es/rce/plugins/instructure_search_and_replace/plugin.js +1 -3
  213. package/es/rce/plugins/instructure_studio_media_options/plugin.js +1 -1
  214. package/es/rce/plugins/instructure_wordcount/clickCallback.js +2 -5
  215. package/es/rce/plugins/instructure_wordcount/components/WordCountModal.js +1 -4
  216. package/es/rce/plugins/instructure_wordcount/plugin.js +1 -0
  217. package/es/rce/plugins/instructure_wordcount/utils/countContent.js +1 -8
  218. package/es/rce/plugins/instructure_wordcount/utils/tableContent.js +1 -0
  219. package/es/rce/plugins/shared/CanvasContentTray.js +43 -63
  220. package/es/rce/plugins/shared/CheckerboardStyling.js +1 -1
  221. package/es/rce/plugins/shared/ColorInput.js +5 -14
  222. package/es/rce/plugins/shared/ConditionalTooltip.js +1 -0
  223. package/es/rce/plugins/shared/ContentSelection.js +17 -58
  224. package/es/rce/plugins/shared/DimensionUtils.js +1 -8
  225. package/es/rce/plugins/shared/DimensionsInput/DimensionInput.js +6 -6
  226. package/es/rce/plugins/shared/DimensionsInput/index.js +37 -15
  227. package/es/rce/plugins/shared/DimensionsInput/useDimensionsState.js +5 -29
  228. package/es/rce/plugins/shared/ErrorBoundary.js +2 -5
  229. package/es/rce/plugins/shared/EventUtils.js +1 -3
  230. package/es/rce/plugins/shared/Filter.js +8 -38
  231. package/es/rce/plugins/shared/FixedContentTray.js +3 -3
  232. package/es/rce/plugins/shared/ImageCropper/DirectionRegion.js +1 -8
  233. package/es/rce/plugins/shared/ImageCropper/Modal.js +4 -7
  234. package/es/rce/plugins/shared/ImageCropper/Preview.js +7 -11
  235. package/es/rce/plugins/shared/ImageCropper/constants.js +1 -0
  236. package/es/rce/plugins/shared/ImageCropper/controls/CustomNumberInput.js +2 -5
  237. package/es/rce/plugins/shared/ImageCropper/controls/ResetControls.js +1 -0
  238. package/es/rce/plugins/shared/ImageCropper/controls/RotationControls.js +1 -10
  239. package/es/rce/plugins/shared/ImageCropper/controls/ShapeControls.js +1 -0
  240. package/es/rce/plugins/shared/ImageCropper/controls/ZoomControls.js +1 -11
  241. package/es/rce/plugins/shared/ImageCropper/controls/index.js +1 -0
  242. package/es/rce/plugins/shared/ImageCropper/controls/useDebouncedNumericValue.js +3 -16
  243. package/es/rce/plugins/shared/ImageCropper/controls/utils.js +1 -2
  244. package/es/rce/plugins/shared/ImageCropper/imageCropUtils.js +1 -10
  245. package/es/rce/plugins/shared/ImageCropper/index.js +1 -0
  246. package/es/rce/plugins/shared/ImageCropper/propTypes.js +1 -0
  247. package/es/rce/plugins/shared/ImageCropper/reducers/imageCropper.js +15 -14
  248. package/es/rce/plugins/shared/ImageCropper/shape.js +1 -0
  249. package/es/rce/plugins/shared/ImageCropper/svg/index.js +1 -2
  250. package/es/rce/plugins/shared/ImageCropper/svg/shape.js +1 -17
  251. package/es/rce/plugins/shared/ImageCropper/svg/utils.js +1 -0
  252. package/es/rce/plugins/shared/ImageCropper/useKeyMouseEvents.js +19 -46
  253. package/es/rce/plugins/shared/ImageCropper/useMouseWheel.js +8 -10
  254. package/es/rce/plugins/shared/ImageOptionsForm.js +1 -2
  255. package/es/rce/plugins/shared/LinkDisplay.js +1 -2
  256. package/es/rce/plugins/shared/PreviewIcon.js +1 -6
  257. package/es/rce/plugins/shared/Previewable.js +1 -0
  258. package/es/rce/plugins/shared/RceFileBrowser.js +5 -7
  259. package/es/rce/plugins/shared/StoreContext.js +1 -2
  260. package/es/rce/plugins/shared/StudioLtiSupportUtils.js +10 -6
  261. package/es/rce/plugins/shared/UnknownFileTypePanel.js +1 -0
  262. package/es/rce/plugins/shared/Upload/CanvasContentPanel.js +13 -18
  263. package/es/rce/plugins/shared/Upload/CategoryProcessor.js +1 -1
  264. package/es/rce/plugins/shared/Upload/ComputerPanel.js +8 -26
  265. package/es/rce/plugins/shared/Upload/PanelFilter.js +3 -12
  266. package/es/rce/plugins/shared/Upload/SvgCategoryProcessor.js +4 -3
  267. package/es/rce/plugins/shared/Upload/UploadFile.js +15 -18
  268. package/es/rce/plugins/shared/Upload/UploadFileModal.js +9 -25
  269. package/es/rce/plugins/shared/Upload/UrlPanel.js +1 -0
  270. package/es/rce/plugins/shared/Upload/UsageRightsSelectBox.js +7 -12
  271. package/es/rce/plugins/shared/Upload/doFileUpload.js +4 -6
  272. package/es/rce/plugins/shared/Upload/index.js +1 -0
  273. package/es/rce/plugins/shared/ai_tools/AIResponseModal.js +1 -3
  274. package/es/rce/plugins/shared/ai_tools/AIToolsTray.js +6 -24
  275. package/es/rce/plugins/shared/ai_tools/aiicons.js +1 -0
  276. package/es/rce/plugins/shared/ai_tools/index.js +1 -0
  277. package/es/rce/plugins/shared/buildDownloadUrl.js +0 -2
  278. package/es/rce/plugins/shared/canvasContentUtils.js +6 -9
  279. package/es/rce/plugins/shared/compressionUtils.js +1 -8
  280. package/es/rce/plugins/shared/dateUtils.js +1 -1
  281. package/es/rce/plugins/shared/do-fetch-api-effect/defaultFetchOptions.js +4 -2
  282. package/es/rce/plugins/shared/do-fetch-api-effect/doFetchApi.js +7 -10
  283. package/es/rce/plugins/shared/do-fetch-api-effect/index.js +1 -0
  284. package/es/rce/plugins/shared/do-fetch-api-effect/parse-link-header.js +6 -20
  285. package/es/rce/plugins/shared/do-fetch-api-effect/query-string-encoding.js +5 -3
  286. package/es/rce/plugins/shared/fileShape.js +4 -9
  287. package/es/rce/plugins/shared/fileTypeUtils.js +32 -42
  288. package/es/rce/plugins/shared/fileUtils.js +1 -2
  289. package/es/rce/plugins/shared/linkUtils.js +1 -16
  290. package/es/rce/plugins/shared/round.js +1 -0
  291. package/es/rce/plugins/shared/trayUtils.js +4 -3
  292. package/es/rce/plugins/shared/useDataUrl.js +9 -9
  293. package/es/rce/plugins/shared/useFilterSettings.js +3 -3
  294. package/es/rce/plugins/tinymce-a11y-checker/components/ColorField.js +2 -6
  295. package/es/rce/plugins/tinymce-a11y-checker/components/checker.js +5 -63
  296. package/es/rce/plugins/tinymce-a11y-checker/components/color-picker.js +1 -2
  297. package/es/rce/plugins/tinymce-a11y-checker/components/placeholder-svg.js +1 -0
  298. package/es/rce/plugins/tinymce-a11y-checker/components/pointer.js +1 -0
  299. package/es/rce/plugins/tinymce-a11y-checker/node-checker.js +1 -6
  300. package/es/rce/plugins/tinymce-a11y-checker/plugin.js +4 -7
  301. package/es/rce/plugins/tinymce-a11y-checker/rules/adjacent-links.js +3 -26
  302. package/es/rce/plugins/tinymce-a11y-checker/rules/headings-sequence.js +9 -38
  303. package/es/rce/plugins/tinymce-a11y-checker/rules/headings-start-at-h2.js +1 -5
  304. package/es/rce/plugins/tinymce-a11y-checker/rules/img-alt-filename.js +1 -2
  305. package/es/rce/plugins/tinymce-a11y-checker/rules/img-alt-length.js +1 -1
  306. package/es/rce/plugins/tinymce-a11y-checker/rules/img-alt.js +1 -2
  307. package/es/rce/plugins/tinymce-a11y-checker/rules/index.js +1 -0
  308. package/es/rce/plugins/tinymce-a11y-checker/rules/large-text-contrast.js +1 -4
  309. package/es/rce/plugins/tinymce-a11y-checker/rules/list-structure.js +5 -24
  310. package/es/rce/plugins/tinymce-a11y-checker/rules/paragraphs-for-headings.js +1 -3
  311. package/es/rce/plugins/tinymce-a11y-checker/rules/small-text-contrast.js +1 -6
  312. package/es/rce/plugins/tinymce-a11y-checker/rules/table-caption.js +1 -3
  313. package/es/rce/plugins/tinymce-a11y-checker/rules/table-header-scope.js +1 -2
  314. package/es/rce/plugins/tinymce-a11y-checker/rules/table-header.js +1 -9
  315. package/es/rce/plugins/tinymce-a11y-checker/utils/colors.js +1 -0
  316. package/es/rce/plugins/tinymce-a11y-checker/utils/describe.js +1 -7
  317. package/es/rce/plugins/tinymce-a11y-checker/utils/dom.js +1 -26
  318. package/es/rce/plugins/tinymce-a11y-checker/utils/indicate.js +16 -15
  319. package/es/rce/plugins/tinymce-a11y-checker/utils/rgb-hex.js +7 -10
  320. package/es/rce/plugins/tinymce-a11y-checker/utils/strings.js +1 -4
  321. package/es/rce/root.js +9 -8
  322. package/es/rce/sanitizePlugins.js +1 -3
  323. package/es/rce/style.js +1 -4
  324. package/es/rce/tinyRCE.js +13 -9
  325. package/es/rce/tinymce.oxide.content.min.css.js +1 -0
  326. package/es/rce/tinymce.oxide.skin.min.css.js +1 -0
  327. package/es/rce/transformContent.js +8 -10
  328. package/es/rce/types.js +1 -0
  329. package/es/rce/userOS.js +1 -1
  330. package/es/rce/wrapInitCb.js +50 -43
  331. package/es/rcs/api.js +61 -116
  332. package/es/rcs/buildError.js +5 -17
  333. package/es/rcs/fake.js +4 -13
  334. package/es/sidebar/actions/all_files.js +2 -0
  335. package/es/sidebar/actions/data.js +4 -7
  336. package/es/sidebar/actions/documents.js +9 -6
  337. package/es/sidebar/actions/files.js +3 -6
  338. package/es/sidebar/actions/filter.js +1 -0
  339. package/es/sidebar/actions/flickr.js +1 -1
  340. package/es/sidebar/actions/images.js +12 -11
  341. package/es/sidebar/actions/links.js +1 -0
  342. package/es/sidebar/actions/media.js +12 -10
  343. package/es/sidebar/actions/session.js +1 -3
  344. package/es/sidebar/actions/ui.js +1 -0
  345. package/es/sidebar/actions/upload.js +14 -39
  346. package/es/sidebar/containers/Sidebar.js +1 -2
  347. package/es/sidebar/containers/sidebarHandlers.js +3 -1
  348. package/es/sidebar/dragHtml.js +5 -3
  349. package/es/sidebar/reducers/all_files.js +4 -3
  350. package/es/sidebar/reducers/collection.js +12 -13
  351. package/es/sidebar/reducers/collections.js +5 -5
  352. package/es/sidebar/reducers/documents.js +6 -13
  353. package/es/sidebar/reducers/files.js +3 -3
  354. package/es/sidebar/reducers/filter.js +1 -8
  355. package/es/sidebar/reducers/flickr.js +9 -9
  356. package/es/sidebar/reducers/folder.js +15 -15
  357. package/es/sidebar/reducers/folders.js +3 -3
  358. package/es/sidebar/reducers/images.js +3 -13
  359. package/es/sidebar/reducers/index.js +3 -1
  360. package/es/sidebar/reducers/media.js +6 -13
  361. package/es/sidebar/reducers/newPageLinkExpanded.js +1 -2
  362. package/es/sidebar/reducers/noop.js +1 -0
  363. package/es/sidebar/reducers/rootFolderId.js +1 -2
  364. package/es/sidebar/reducers/session.js +3 -3
  365. package/es/sidebar/reducers/ui.js +3 -16
  366. package/es/sidebar/reducers/upload.js +8 -40
  367. package/es/sidebar/store/configureStore.js +1 -0
  368. package/es/sidebar/store/initialState.js +13 -24
  369. package/es/translations/locales/ab.js +1 -0
  370. package/es/translations/locales/ar.js +67 -9
  371. package/es/translations/locales/ca.js +67 -9
  372. package/es/translations/locales/cs.js +1 -0
  373. package/es/translations/locales/cs_CZ.js +1 -0
  374. package/es/translations/locales/cy.js +67 -9
  375. package/es/translations/locales/da-x-k12.js +67 -9
  376. package/es/translations/locales/da.js +67 -9
  377. package/es/translations/locales/da_DK.js +1 -0
  378. package/es/translations/locales/de.js +67 -9
  379. package/es/translations/locales/el.js +4 -0
  380. package/es/translations/locales/en-AU-x-unimelb.js +67 -9
  381. package/es/translations/locales/en-GB-x-ukhe.js +67 -9
  382. package/es/translations/locales/en.js +72 -8
  383. package/es/translations/locales/en_AU.js +67 -9
  384. package/es/translations/locales/en_CA.js +67 -9
  385. package/es/translations/locales/en_CY.js +67 -9
  386. package/es/translations/locales/en_GB.js +67 -9
  387. package/es/translations/locales/en_NZ.js +1 -0
  388. package/es/translations/locales/en_SE.js +1 -0
  389. package/es/translations/locales/en_US.js +1 -0
  390. package/es/translations/locales/es.js +67 -9
  391. package/es/translations/locales/es_ES.js +67 -9
  392. package/es/translations/locales/es_GT.js +1 -0
  393. package/es/translations/locales/fa_IR.js +7 -0
  394. package/es/translations/locales/fi.js +67 -9
  395. package/es/translations/locales/fr.js +67 -9
  396. package/es/translations/locales/fr_CA.js +68 -10
  397. package/es/translations/locales/ga.js +5 -13
  398. package/es/translations/locales/he.js +7 -0
  399. package/es/translations/locales/hi.js +67 -9
  400. package/es/translations/locales/ht.js +67 -9
  401. package/es/translations/locales/hu.js +7 -6
  402. package/es/translations/locales/hu_HU.js +1 -0
  403. package/es/translations/locales/hy.js +1 -0
  404. package/es/translations/locales/id.js +67 -9
  405. package/es/translations/locales/id_ID.js +1 -0
  406. package/es/translations/locales/is.js +67 -9
  407. package/es/translations/locales/it.js +67 -9
  408. package/es/translations/locales/ja.js +67 -9
  409. package/es/translations/locales/ko.js +1 -0
  410. package/es/translations/locales/ko_KR.js +1 -0
  411. package/es/translations/locales/lt.js +1 -0
  412. package/es/translations/locales/lt_LT.js +1 -0
  413. package/es/translations/locales/mi.js +67 -9
  414. package/es/translations/locales/mn_MN.js +1 -0
  415. package/es/translations/locales/ms.js +67 -9
  416. package/es/translations/locales/nb-x-k12.js +67 -9
  417. package/es/translations/locales/nb.js +67 -9
  418. package/es/translations/locales/nl.js +67 -9
  419. package/es/translations/locales/nl_NL.js +1 -0
  420. package/es/translations/locales/nn.js +7 -6
  421. package/es/translations/locales/pl.js +67 -9
  422. package/es/translations/locales/pt.js +67 -9
  423. package/es/translations/locales/pt_BR.js +67 -9
  424. package/es/translations/locales/ro.js +1 -0
  425. package/es/translations/locales/ru.js +67 -9
  426. package/es/translations/locales/se.js +1 -0
  427. package/es/translations/locales/sl.js +67 -9
  428. package/es/translations/locales/sv-x-k12.js +67 -9
  429. package/es/translations/locales/sv.js +67 -9
  430. package/es/translations/locales/sv_SE.js +1 -0
  431. package/es/translations/locales/tg.js +1 -0
  432. package/es/translations/locales/th.js +67 -9
  433. package/es/translations/locales/th_TH.js +1 -0
  434. package/es/translations/locales/tl_PH.js +1 -0
  435. package/es/translations/locales/tr.js +7 -0
  436. package/es/translations/locales/uk_UA.js +7 -0
  437. package/es/translations/locales/vi.js +67 -9
  438. package/es/translations/locales/vi_VN.js +1 -0
  439. package/es/translations/locales/zh-Hans.js +67 -9
  440. package/es/translations/locales/zh-Hant.js +67 -9
  441. package/es/translations/locales/zh.js +67 -9
  442. package/es/translations/locales/zh_HK.js +67 -9
  443. package/es/translations/locales/zh_TW.Big5.js +1 -0
  444. package/es/translations/locales/zh_TW.js +1 -0
  445. package/es/translations/tinymce/ar_SA.js +1 -0
  446. package/es/translations/tinymce/fi.js +1 -0
  447. package/es/translations/tinymce/ga.js +1 -0
  448. package/es/translations/tinymce/id.js +1 -0
  449. package/es/translations/tinymce/ru.js +1 -0
  450. package/es/translations/tinymce/ru_RU.js +1 -0
  451. package/es/translations/tinymce/sl.js +1 -0
  452. package/es/translations/tinymce/sr.js +1 -0
  453. package/es/translations/tinymce/th.js +1 -0
  454. package/es/translations/tinymce/uk_UA.js +1 -0
  455. package/es/translations/tinymce/vi_VN.js +1 -0
  456. package/es/util/TypedDict.js +4 -2
  457. package/es/util/encrypted-storage.js +3 -13
  458. package/es/util/file-url-util.js +1 -6
  459. package/es/util/fullscreenHelpers.js +4 -1
  460. package/es/util/instui-icon-helper.js +4 -3
  461. package/es/util/loadingPlaceholder.js +38 -39
  462. package/es/util/simpleCache.js +0 -3
  463. package/es/util/string-util.js +1 -1
  464. package/es/util/textarea-editing-util.js +3 -7
  465. package/es/util/tinymce-plugin-util.js +0 -5
  466. package/es/util/url-util.js +16 -25
  467. package/eslint.config.js +239 -0
  468. package/jest.config.js +1 -1
  469. package/package.json +77 -82
  470. package/scripts/build-canvas +2 -1
  471. package/scripts/build.js +4 -4
  472. package/scripts/publish_to_npm.sh +1 -1
  473. package/testcafe/RCEWrapper.test.js +0 -1
  474. package/testcafe/StatusBar.test.js +0 -1
  475. package/testcafe/axe.test.js +3 -4
  476. package/testcafe/enhanceUserContent.test.js +0 -1
  477. package/tsconfig.json +20 -15
  478. package/.eslintrc +0 -45
  479. package/.prettierignore +0 -6
  480. package/es/common/components/FileTree/File.js +0 -64
  481. package/es/common/components/FileTree/Folder.js +0 -110
  482. package/es/common/components/FileTree/index.js +0 -84
  483. package/es/common/components/FileTree/styles.js +0 -72
  484. package/es/common/components/Loading.js +0 -83
@@ -15,6 +15,7 @@
15
15
  * You should have received a copy of the GNU Affero General Public License along
16
16
  * with this program. If not, see <http://www.gnu.org/licenses/>.
17
17
  */
18
+
18
19
  import React, { Component, useRef } from 'react';
19
20
  import { bool, func, string } from 'prop-types';
20
21
  import { linkShape, linksShape, linkType } from './propTypes';
@@ -27,10 +28,10 @@ import { LoadMoreButton, LoadingIndicator, LoadingStatus, useIncrementalLoading
27
28
  import Link from './Link';
28
29
  import RCEGlobals from '../../../RCEGlobals';
29
30
  import { NoResults } from './NoResults';
31
+
30
32
  /*
31
33
  * This is needed only as long as `LinkSet` is a class component.
32
34
  */
33
-
34
35
  function IncrementalLoader(props) {
35
36
  const {
36
37
  children,
@@ -57,17 +58,14 @@ function IncrementalLoader(props) {
57
58
  },
58
59
  // not actually used in the query, but a required param
59
60
  searchString,
60
-
61
61
  onLoadInitial() {
62
62
  if (fetchInitialPage) {
63
63
  fetchInitialPage();
64
64
  }
65
65
  },
66
-
67
66
  onLoadMore() {
68
67
  fetchNextPage();
69
68
  },
70
-
71
69
  records: links
72
70
  });
73
71
  return children({
@@ -75,41 +73,35 @@ function IncrementalLoader(props) {
75
73
  lastItemRef
76
74
  });
77
75
  }
78
-
79
76
  class LinkSet extends Component {
80
77
  constructor(props) {
81
78
  super(props);
82
79
  this.describedByID = `rce-LinkSet-describedBy-${uid()}`;
83
80
  this.loadMoreButtonRef = null;
84
81
  }
85
-
86
82
  hasLinks(props) {
87
83
  return props.collection.links.length > 0;
88
84
  }
89
-
90
85
  isEmpty(props) {
91
86
  return !this.hasLinks(props) && !props.collection.hasMore && !props.collection.isLoading;
92
87
  }
93
-
94
88
  compareURLs() {
95
89
  let url1 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
96
90
  let url2 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
97
91
  if (url1 === '' || url2 === '') return false;
98
92
  return url1.split('?')[0] === url2.split('?')[0];
99
93
  }
100
-
101
94
  renderLinks(lastItemRef) {
102
95
  function refFor(index, array) {
103
96
  if (!lastItemRef || index !== array.length - 1) {
104
97
  return null;
105
- } // Return a compatible callback ref for InstUI
106
-
98
+ }
107
99
 
100
+ // Return a compatible callback ref for InstUI
108
101
  return ref => {
109
102
  lastItemRef.current = ref;
110
103
  };
111
104
  }
112
-
113
105
  return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(ScreenReaderContent, {
114
106
  id: this.describedByID
115
107
  }, formatMessage('Click to insert a link into the editor.')), /*#__PURE__*/React.createElement(List, {
@@ -118,7 +110,6 @@ class LinkSet extends Component {
118
110
  margin: "0"
119
111
  }, this.props.collection.links.map((link, index, array) => {
120
112
  var _this$props$selectedL;
121
-
122
113
  return /*#__PURE__*/React.createElement(List.Item, {
123
114
  key: link.href,
124
115
  spacing: "none",
@@ -135,10 +126,8 @@ class LinkSet extends Component {
135
126
  }));
136
127
  })));
137
128
  }
138
-
139
129
  renderEmptyIndicator() {
140
130
  var _this$props$searchStr;
141
-
142
131
  return /*#__PURE__*/React.createElement(NoResults, {
143
132
  contextType: this.props.contextType,
144
133
  contextId: this.props.contextId,
@@ -146,7 +135,6 @@ class LinkSet extends Component {
146
135
  isSearchResult: ((_this$props$searchStr = this.props.searchString) === null || _this$props$searchStr === void 0 ? void 0 : _this$props$searchStr.length) >= 3
147
136
  });
148
137
  }
149
-
150
138
  renderLoadingError() {
151
139
  if (this.props.collection.lastError) {
152
140
  return /*#__PURE__*/React.createElement("span", {
@@ -154,10 +142,8 @@ class LinkSet extends Component {
154
142
  role: "alert"
155
143
  }, formatMessage('Loading failed...'));
156
144
  }
157
-
158
145
  return null;
159
146
  }
160
-
161
147
  render() {
162
148
  return /*#__PURE__*/React.createElement(IncrementalLoader, this.props, _ref => {
163
149
  let {
@@ -175,9 +161,7 @@ class LinkSet extends Component {
175
161
  }));
176
162
  });
177
163
  }
178
-
179
164
  }
180
-
181
165
  LinkSet.propTypes = {
182
166
  type: linkType.isRequired,
183
167
  collection: linksShape.isRequired,
@@ -15,6 +15,7 @@
15
15
  * You should have received a copy of the GNU Affero General Public License along
16
16
  * with this program. If not, see <http://www.gnu.org/licenses/>.
17
17
  */
18
+
18
19
  import React from 'react';
19
20
  import { bool, func, string } from 'prop-types';
20
21
  import formatMessage from '../../../../format-message';
@@ -23,7 +24,6 @@ import NavigationPanel from './NavigationPanel';
23
24
  import CollectionPanel from './CollectionPanel';
24
25
  import { View } from '@instructure/ui-view';
25
26
  import { pickProps } from '@instructure/ui-react-utils';
26
-
27
27
  function LinksPanel(props) {
28
28
  const isCourse = props.contextType === 'course';
29
29
  const isGroup = props.contextType === 'group';
@@ -77,7 +77,6 @@ function LinksPanel(props) {
77
77
  onEditClick: props.onEditClick
78
78
  }));
79
79
  }
80
-
81
80
  LinksPanel.propTypes = {
82
81
  selectedAccordionIndex: string,
83
82
  onChangeAccordion: func,
@@ -15,12 +15,12 @@
15
15
  * You should have received a copy of the GNU Affero General Public License along
16
16
  * with this program. If not, see <http://www.gnu.org/licenses/>.
17
17
  */
18
+
18
19
  import { bool, func, string } from 'prop-types';
19
20
  import React from 'react';
20
21
  import LinkSet from './LinkSet';
21
22
  import formatMessage from '../../../../format-message';
22
23
  import AccordionSection from './AccordionSection';
23
-
24
24
  function typeCollection(contextId, contextType) {
25
25
  switch (contextType) {
26
26
  case 'course':
@@ -52,21 +52,23 @@ function typeCollection(contextId, contextType) {
52
52
  }, {
53
53
  href: `/courses/${contextId}/assignments/syllabus`,
54
54
  title: formatMessage('Syllabus')
55
- }, // outcomes
55
+ },
56
+ // outcomes
56
57
  {
57
58
  href: `/courses/${contextId}/quizzes`,
58
59
  title: formatMessage('Quizzes')
59
60
  }, {
60
61
  href: `/courses/${contextId}/modules`,
61
62
  title: formatMessage('Modules')
62
- }, // conferences
63
+ },
64
+ // conferences
63
65
  {
64
66
  href: `/courses/${contextId}/collaborations`,
65
67
  title: formatMessage('Collaborations')
66
- } // settings
68
+ }
69
+ // settings
67
70
  ]
68
71
  };
69
-
70
72
  case 'group':
71
73
  return {
72
74
  links: [{
@@ -89,7 +91,6 @@ function typeCollection(contextId, contextType) {
89
91
  title: formatMessage('People')
90
92
  }]
91
93
  };
92
-
93
94
  default:
94
95
  // user, TODO
95
96
  return {
@@ -100,11 +101,9 @@ function typeCollection(contextId, contextType) {
100
101
  };
101
102
  }
102
103
  }
103
-
104
104
  export default function NavigationPanel(props) {
105
105
  const collection = typeCollection(props.contextId, props.contextType);
106
106
  let navigationSummary = '';
107
-
108
107
  if (props.contextType === 'course') {
109
108
  navigationSummary = formatMessage('Course Navigation');
110
109
  } else if (props.contextType === 'group') {
@@ -112,7 +111,6 @@ export default function NavigationPanel(props) {
112
111
  } else {
113
112
  return null;
114
113
  }
115
-
116
114
  return /*#__PURE__*/React.createElement("div", {
117
115
  "data-testid": "instructure_links-NavigationPanel"
118
116
  }, /*#__PURE__*/React.createElement(AccordionSection, {
@@ -1,5 +1,4 @@
1
1
  import _pt from "prop-types";
2
-
3
2
  /*
4
3
  * Copyright (C) 2023 - present Instructure, Inc.
5
4
  *
@@ -17,6 +16,7 @@ import _pt from "prop-types";
17
16
  * You should have received a copy of the GNU Affero General Public License along
18
17
  * with this program. If not, see <http://www.gnu.org/licenses/>.
19
18
  */
19
+
20
20
  import React from 'react';
21
21
  import { View } from '@instructure/ui-view';
22
22
  import { Flex } from '@instructure/ui-flex';
@@ -26,7 +26,6 @@ import formatMessage from '../../../../format-message';
26
26
  import { getIcon } from '../../shared/linkUtils';
27
27
  export function buildUrl(contextType, contextId, collectionType) {
28
28
  var _typeMap$collectionTy;
29
-
30
29
  const typeMap = {
31
30
  wikiPages: 'pages',
32
31
  discussions: 'discussion_topics'
@@ -37,19 +36,14 @@ export function getMessage(collectionType, isSearchResult) {
37
36
  switch (collectionType) {
38
37
  case 'wikiPages':
39
38
  return isSearchResult ? formatMessage('No pages found.') : formatMessage('No pages created yet.');
40
-
41
39
  case 'assignments':
42
40
  return isSearchResult ? formatMessage('No assignments found.') : formatMessage('No assignments created yet.');
43
-
44
41
  case 'quizzes':
45
42
  return isSearchResult ? formatMessage('No quizzes found.') : formatMessage('No quizzes created yet.');
46
-
47
43
  case 'announcements':
48
44
  return isSearchResult ? formatMessage('No announcements found.') : formatMessage('No announcements created yet.');
49
-
50
45
  case 'discussions':
51
46
  return isSearchResult ? formatMessage('No discussions found.') : formatMessage('No discussions created yet.');
52
-
53
47
  case 'modules':
54
48
  return isSearchResult ? formatMessage('No modules found.') : formatMessage('No modules created yet.');
55
49
  }
@@ -1,5 +1,3 @@
1
- // @ts-nocheck
2
-
3
1
  /*
4
2
  * Copyright (C) 2019 - present Instructure, Inc.
5
3
  *
@@ -62,6 +60,7 @@
62
60
  * href with the new URL. if the link text is updated, replace the link's
63
61
  * content with the new plain text (deleting the image)
64
62
  */
63
+
65
64
  import formatMessage from '../../../format-message';
66
65
  import clickCallback from './clickCallback';
67
66
  import bridge from '../../../bridge';
@@ -72,23 +71,18 @@ import tinymce from 'tinymce';
72
71
  const trayController = new LinkOptionsTrayController();
73
72
  const COURSE_PLUGIN_KEY = 'course_links';
74
73
  const GROUP_PLUGIN_KEY = 'group_links';
75
-
76
74
  function getCommandName(selectedNode) {
77
75
  const isCourseLink = selectedNode.getAttribute('data-course-type');
78
76
  return isCourseLink ? 'instructureTrayForCourseLinks' : 'instructureTrayToEditLink';
79
77
  }
80
-
81
78
  function selectedAnchorCount(ed) {
82
79
  return ed.selection.getRng().cloneContents().querySelectorAll('a').length;
83
80
  }
84
-
85
81
  function getMenuItems(ed) {
86
82
  var _ed$settings$canvas_r;
87
-
88
83
  const contextType = (_ed$settings$canvas_r = ed.settings.canvas_rce_containing_context) === null || _ed$settings$canvas_r === void 0 ? void 0 : _ed$settings$canvas_r.type;
89
84
  const sel_anchors = ed.selection.isCollapsed() ? 0 : selectedAnchorCount(ed);
90
85
  let items;
91
-
92
86
  if (getAnchorElement(ed, ed.selection.getNode())) {
93
87
  // cursor is on an anchor, edit or remove it
94
88
  items = [{
@@ -103,7 +97,6 @@ function getMenuItems(ed) {
103
97
  text: formatMessage('External Link'),
104
98
  value: 'instructureLinkCreate'
105
99
  }];
106
-
107
100
  if (contextType === 'course') {
108
101
  items.push({
109
102
  text: formatMessage('Course Link'),
@@ -115,7 +108,6 @@ function getMenuItems(ed) {
115
108
  value: 'instructure_group_links'
116
109
  });
117
110
  }
118
-
119
111
  if (sel_anchors > 0) {
120
112
  // selection contains anchor(s), so the user can remove them
121
113
  items.push({
@@ -127,10 +119,8 @@ function getMenuItems(ed) {
127
119
  });
128
120
  }
129
121
  }
130
-
131
122
  return items;
132
123
  }
133
-
134
124
  function removeAnchorFromSelectedElement(ed) {
135
125
  const selectedElem = ed.selection.getNode();
136
126
  const anchorElem = getAnchorElement(ed, selectedElem);
@@ -138,7 +128,6 @@ function removeAnchorFromSelectedElement(ed) {
138
128
  ed.undoManager.add();
139
129
  ed.execCommand('Unlink');
140
130
  }
141
-
142
131
  function doMenuItem(ed, actionName) {
143
132
  switch (actionName) {
144
133
  case 'instructureTrayToEditLink':
@@ -146,30 +135,23 @@ function doMenuItem(ed, actionName) {
146
135
  case 'instructureLinkCreate':
147
136
  ed.execCommand(actionName);
148
137
  break;
149
-
150
138
  case 'instructureUnlink':
151
139
  removeAnchorFromSelectedElement(ed);
152
140
  break;
153
-
154
141
  case 'instructureUnlinkAll':
155
142
  ed.undoManager.add();
156
143
  ed.execCommand('unlink');
157
144
  break;
158
-
159
145
  case 'instructure_course_links':
160
146
  ed.focus(true); // activate the editor without changing focus
161
-
162
147
  ed.execCommand('instructureTrayForLinks', false, COURSE_PLUGIN_KEY);
163
148
  break;
164
-
165
149
  case 'instructure_group_links':
166
150
  ed.focus(true); // activate the editor without changing focus
167
-
168
151
  ed.execCommand('instructureTrayForLinks', false, GROUP_PLUGIN_KEY);
169
152
  break;
170
153
  }
171
154
  }
172
-
173
155
  tinymce.PluginManager.add('instructure_links', function (ed) {
174
156
  // Register commands
175
157
  ed.addCommand('instructureLinkCreate', () => clickCallback(ed, CREATE_LINK));
@@ -183,10 +165,12 @@ tinymce.PluginManager.add('instructure_links', function (ed) {
183
165
  ed.addCommand('instructureTrayForCourseLinks', () => {
184
166
  ed.selection.select(ed.selection.getNode());
185
167
  return bridge.showTrayForPlugin('course_link_edit', ed.id);
186
- }); // Register shortcuts
168
+ });
187
169
 
188
- ed.addShortcut('Meta+K', '', 'instructureLinkCreate'); // Register menu item
170
+ // Register shortcuts
171
+ ed.addShortcut('Meta+K', '', 'instructureLinkCreate');
189
172
 
173
+ // Register menu item
190
174
  ed.ui.registry.addNestedMenuItem('instructure_links', {
191
175
  text: formatMessage('Link'),
192
176
  icon: 'link',
@@ -201,8 +185,9 @@ tinymce.PluginManager.add('instructure_links', function (ed) {
201
185
  }
202
186
  };
203
187
  })
204
- }); // Register toolbar button
188
+ });
205
189
 
190
+ // Register toolbar button
206
191
  ed.ui.registry.addMenuButton('instructure_links', {
207
192
  tooltip: formatMessage('Links'),
208
193
  icon: 'link',
@@ -212,52 +197,45 @@ tinymce.PluginManager.add('instructure_links', function (ed) {
212
197
  value: item.value,
213
198
  onAction: () => doMenuItem(ed, item.value)
214
199
  }))),
215
-
216
200
  onSetup(api) {
201
+ // @ts-expect-error
217
202
  function handleNodeChange(e) {
218
203
  if (e !== null && e !== void 0 && e.element) {
219
204
  api.setActive(!!getAnchorElement(ed, e.element));
220
205
  }
206
+ if (ed.selection) {
207
+ api.setDisabled(!isOKToLink(ed.selection.getContent()));
208
+ }
209
+ }
221
210
 
222
- api.setDisabled(!isOKToLink(ed.selection.getContent()));
223
- } // if the user selects all the content w/in a link and deletes it via the keyboard
211
+ // if the user selects all the content w/in a link and deletes it via the keyboard
224
212
  // make sure the surrounding <a> gets deleted too.
225
-
226
-
227
213
  function deleteEmptyLink() {
228
214
  let node = null;
229
-
230
215
  if (ed.selection.getNode().tagName === 'A') {
231
216
  node = ed.selection.getNode();
232
217
  } else {
233
218
  var _rng$endContainer$nex, _rng$nextSibling;
234
-
235
219
  // Type checking is disabled here because the code below isn't type safe. The code below
236
220
  // should be updated, specifically rng.endContainer.nextSibling?.tagName
237
221
  const rng = ed.selection.getRng();
238
-
239
222
  if (rng.commonAncestorContainer === rng.endContainer && ((_rng$endContainer$nex = rng.endContainer.nextSibling) === null || _rng$endContainer$nex === void 0 ? void 0 : _rng$endContainer$nex.tagName) === 'A') {
240
223
  node = rng.endContainer.nextSibling;
241
224
  } else if (((_rng$nextSibling = rng.nextSibling) === null || _rng$nextSibling === void 0 ? void 0 : _rng$nextSibling.tagName) === 'A') {
242
225
  node = rng.nextSibling;
243
226
  }
244
227
  }
245
-
246
228
  if (node) {
247
229
  var _node$textContent;
248
-
249
230
  if (node.firstElementChild) {
250
231
  return;
251
232
  }
252
-
253
233
  const txt = (_node$textContent = node.textContent) === null || _node$textContent === void 0 ? void 0 : _node$textContent.trim();
254
-
255
234
  if ((txt === null || txt === void 0 ? void 0 : txt.length) === 0) {
256
235
  ed.execCommand('Unlink');
257
236
  }
258
237
  }
259
238
  }
260
-
261
239
  setTimeout(handleNodeChange, 0, null);
262
240
  ed.on('NodeChange', handleNodeChange);
263
241
  ed.on('Change', deleteEmptyLink);
@@ -266,14 +244,14 @@ tinymce.PluginManager.add('instructure_links', function (ed) {
266
244
  ed.off('Change', deleteEmptyLink);
267
245
  };
268
246
  }
247
+ });
269
248
 
270
- }); // the context toolbar buttons
271
-
249
+ // the context toolbar buttons
272
250
  ed.ui.registry.addButton('instructure-link-options', {
273
- onAction() {
251
+ onAction(/* buttonApi */
252
+ ) {
274
253
  ed.execCommand(getCommandName(ed.selection.getNode()), false, ed);
275
254
  },
276
-
277
255
  text: formatMessage('Link Options'),
278
256
  tooltip: formatMessage('Show link options')
279
257
  });
@@ -282,7 +260,6 @@ tinymce.PluginManager.add('instructure_links', function (ed) {
282
260
  onAction() {
283
261
  removeAnchorFromSelectedElement(ed);
284
262
  },
285
-
286
263
  text: remButtonLabel
287
264
  });
288
265
  ed.ui.registry.addContextToolbar('instructure-link-toolbar', {
@@ -15,56 +15,101 @@
15
15
  * You should have received a copy of the GNU Affero General Public License along
16
16
  * with this program. If not, see <http://www.gnu.org/licenses/>.
17
17
  */
18
- import { parse } from 'url';
19
- import formatMessage from '../../../format-message'; // keep in sync with the protocols permitted for <a href>
20
- // as listed in gems/canvas_sanitize/lib/canvas_sanitize/canvas_sanitize.rb
21
18
 
22
- const allowed_protocols = ['ftp:', 'http:', 'https:', 'mailto:', 'tel:', 'skype:']; // weakly validate a url
23
- // return true if valid
24
- // return false if not valid yet, but incomplete
25
- // throw an Error if invalid
19
+ import formatMessage from '../../../format-message';
26
20
 
21
+ // Keep in sync with the protocols permitted for <a href>
22
+ // as listed in gems/canvas_sanitize/lib/canvas_sanitize/canvas_sanitize.rb
23
+ const allowed_protocols = ['ftp:', 'http:', 'https:', 'mailto:', 'tel:', 'skype:'];
24
+
25
+ /**
26
+ * Weakly validate a URL
27
+ * @param {string} url URL to validate
28
+ * @returns {boolean} true if valid, false if not valid yet, but incomplete, throws if invalid
29
+ */
27
30
  export default function validateURL(url) {
28
31
  const href = url.trim();
29
- const parsed = parse(href, false, true);
30
- const protocol = parsed.protocol;
31
32
 
32
- if (!protocol) {
33
- if (parsed.href[0] === ':') {
34
- // ":anything" is invalid
35
- // need this check as an artifact of parse(href)
33
+ // Handle special cases for partial URLs
34
+ if (href === '' || href === 'mailto:' || href === 'tel:' || href === 'skype:') {
35
+ return false;
36
+ }
37
+ if (/^\/\/$/.test(href)) {
38
+ return false;
39
+ }
40
+ try {
41
+ // Handle URLs starting with :// (invalid protocol)
42
+ if (href.startsWith('://')) {
36
43
  throw new Error(formatMessage('Protocol must be ftp, http, https, mailto, skype, tel or may be omitted'));
37
44
  }
38
45
 
39
- if (/^\/\/$/.test(href)) {
40
- // "//" by itself is not a URL yet
41
- return false;
42
- }
43
- } else if (protocol) {
44
- if (!allowed_protocols.includes(protocol)) {
45
- throw new Error(formatMessage('{p} is not a valid protocol which must be ftp, http, https, mailto, skype, tel or may be omitted', {
46
- p: protocol.replace(/:$/, '')
47
- }));
48
- } // ftp, http, https require ://anything
49
-
46
+ // For URLs with protocols, we can use the URL constructor directly
47
+ if (/^[a-zA-Z][a-zA-Z\d+.-]*:/.test(href)) {
48
+ const protocol = href.substring(0, href.indexOf(':') + 1);
49
+ if (!allowed_protocols.includes(protocol)) {
50
+ throw new Error(formatMessage('{p} is not a valid protocol.', {
51
+ p: protocol.slice(0, -1)
52
+ }));
53
+ }
50
54
 
51
- if (/(?:ftp|http|https):\/\/.+/.test(href)) {
52
- return true;
53
- } // allow mailto:address, skype:participant, tel:911 or
54
- // mailto://address, skype://participant, tel://911,
55
+ // For absolute URLs with protocols that require //, validate the format
56
+ if (['http:', 'https:', 'ftp:'].includes(protocol) && !href.startsWith(protocol + '//')) {
57
+ throw new Error(formatMessage('Invalid URL'));
58
+ }
55
59
 
60
+ // Special handling for mailto:, tel:, and skype: URLs
61
+ if (['mailto:', 'tel:', 'skype:'].includes(protocol)) {
62
+ // Consider protocol:// as incomplete for these protocols
63
+ if (href === protocol + '//' || href === protocol + '///') {
64
+ return false;
65
+ }
66
+ return href.length > protocol.length;
67
+ }
56
68
 
57
- if (/(?:mailto|skype|tel):(\/\/)?[^/].*/.test(href)) {
58
- return true;
59
- } // http:/xyzzy is invalid
69
+ // Handle partial URLs
70
+ if (href === protocol || href === protocol + '/' || href === protocol + '//') {
71
+ return false;
72
+ }
60
73
 
74
+ // Try constructing the URL to validate the format
75
+ try {
76
+ if (href.includes('//')) {
77
+ new URL(href);
78
+ }
79
+ return true;
80
+ } catch {
81
+ // If URL construction fails but we have more than just protocol://, consider it valid
82
+ // This allows for test URLs like ftp://host:port/path
83
+ return href.length > protocol.length + 2;
84
+ }
85
+ }
61
86
 
62
- if (/^(?:ftp|http|https):\/{0,1}[^/]/.test(href)) {
63
- throw new Error(formatMessage('Invalid URL'));
87
+ // Handle protocol-relative URLs
88
+ if (href.startsWith('//')) {
89
+ if (href === '//' || href === '///') {
90
+ return false;
91
+ }
92
+ try {
93
+ new URL('http:' + href);
94
+ return true;
95
+ } catch {
96
+ // If URL construction fails but we have more than just //, consider it valid
97
+ return href.length > 2;
98
+ }
64
99
  }
65
100
 
66
- return false;
101
+ // Handle relative paths
102
+ return true;
103
+ } catch (e) {
104
+ if (e instanceof Error) {
105
+ if (e.message.includes('Invalid URL')) {
106
+ if (href.match(/^(https?|ftp):\/?\/?$/)) {
107
+ return false;
108
+ }
109
+ throw new Error(formatMessage('Invalid URL'));
110
+ }
111
+ throw e;
112
+ }
113
+ throw e;
67
114
  }
68
-
69
- return true;
70
115
  }
@@ -15,6 +15,7 @@
15
15
  * You should have received a copy of the GNU Affero General Public License along
16
16
  * with this program. If not, see <http://www.gnu.org/licenses/>.
17
17
  */
18
+
18
19
  import React from 'react';
19
20
  import ReactDOM from 'react-dom';
20
21
  import Bridge from '../../../bridge';
@@ -24,23 +25,19 @@ export default function (ed, document) {
24
25
  Embed
25
26
  } = _ref;
26
27
  let container = document.querySelector('.canvas-rce-embed-container');
27
-
28
28
  if (!container) {
29
29
  container = document.createElement('div');
30
30
  container.className = 'canvas-rce-embed-container';
31
31
  document.body.appendChild(container);
32
32
  }
33
-
34
33
  const handleDismiss = () => {
35
34
  ReactDOM.unmountComponentAtNode(container);
36
35
  ed.focus(false);
37
36
  };
38
-
39
37
  const handleEmbedCode = embedCode => {
40
38
  Bridge.insertEmbedCode(embedCode);
41
39
  };
42
-
43
- ReactDOM.render( /*#__PURE__*/React.createElement(Embed, {
40
+ ReactDOM.render(/*#__PURE__*/React.createElement(Embed, {
44
41
  onSubmit: handleEmbedCode,
45
42
  onDismiss: handleDismiss
46
43
  }), container);
@@ -15,6 +15,7 @@
15
15
  * You should have received a copy of the GNU Affero General Public License along
16
16
  * with this program. If not, see <http://www.gnu.org/licenses/>.
17
17
  */
18
+
18
19
  import React, { useState } from 'react';
19
20
  import { Modal } from '@instructure/ui-modal';
20
21
  import formatMessage from '../../../../format-message';
@@ -15,19 +15,23 @@
15
15
  * You should have received a copy of the GNU Affero General Public License along
16
16
  * with this program. If not, see <http://www.gnu.org/licenses/>.
17
17
  */
18
+
18
19
  import clickCallback from './clickCallback';
19
20
  import formatMessage from '../../../format-message';
20
- import tinymce from 'tinymce'; // Register plugin
21
+ import tinymce from 'tinymce';
21
22
 
23
+ // Register plugin
22
24
  tinymce.PluginManager.add('instructure_media_embed', function (ed) {
23
- ed.addCommand('instructureMediaEmbed', () => clickCallback(ed, document)); // Register menu item
25
+ ed.addCommand('instructureMediaEmbed', () => clickCallback(ed, document));
24
26
 
27
+ // Register menu item
25
28
  ed.ui.registry.addMenuItem('instructure_media_embed', {
26
29
  text: formatMessage('Embed'),
27
30
  icon: 'embed',
28
31
  onAction: () => ed.execCommand('instructureMediaEmbed')
29
- }); // Register toolbar button
32
+ });
30
33
 
34
+ // Register toolbar button
31
35
  ed.ui.registry.addButton('instructure_media_embed', {
32
36
  tooltip: formatMessage('Embed'),
33
37
  icon: 'embed',