2018-03-07 10:12:53 +08:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2018 - present Instructure, Inc.
|
|
|
|
*
|
|
|
|
* This file is part of Canvas.
|
|
|
|
*
|
|
|
|
* Canvas is free software: you can redistribute it and/or modify it under
|
|
|
|
* the terms of the GNU Affero General Public License as published by the Free
|
|
|
|
* Software Foundation, version 3 of the License.
|
|
|
|
*
|
|
|
|
* Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
|
|
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
|
|
|
* A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
|
|
|
* details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Affero General Public License along
|
|
|
|
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
Insert language polyfills at page load time
Refs FOO-1891
flag=none
Canvas officially supports a fixed set of languages and locales.
Unfortunately, not all browsers support all of those (the worst
offender oddly enough is Google Chrome). Fortunately, polyfills
for almost all of the Canvas supported languages are available
via a polyfill package.
This commit introduces a function that asynchronously loads the
polyfill for a requested language. It does nothing if it sees
there is already native support in the browser for that
language. The function can be imported and run to dynamically
switch in and out the polyfills as necessary, but since Canvas
never changes ENV.LOCALE except at page load time, it should
suffice to call it at front end initialization time; this was
added to ui/index.js as a part of its "readiness" checks.
The missing one (that NO browser supports) is Haitian Creole;
we will have to probably build our own locale data file for
that one.
This takes care of polyfilling DateTimeFormat, NumberFormat,
and RelativeTimeFormat. We can always add other Intl systems
if the need arises.
Test plan:
* Be on Chrome (which does not support the Welsh language)
* In the browser console, verify no native support for Welsh:
Intl.DateTimeFormat.supportedLocalesOf(['cy'])
... should return an empty array
* Go into your user settings on Canvas and change your language
to Welsh (Cymraeg). Reload the page to make it take effect.
Now your settings page should appear in Welsh.
* In the browser console, verify that dates and times can be
formatted correctly in Welsh (thanks to the polyfill):
Intl.DateTimeFormat('cy', {
dateStyle: 'long',
timeStyle: 'long'
}).format(new Date())
* That should display a date and time in Welsh (most prominently
seen in the name of the month).
Change-Id: I40632344ba1d8679aba1a976fcb55af97636be4b
Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/267359
Reviewed-by: Ahmad Amireh <ahmad@instructure.com>
Product-Review: Charley Kline <ckline@instructure.com>
Product-Review: Ahmad Amireh <ahmad@instructure.com>
QA-Review: Ahmad Amireh <ahmad@instructure.com>
Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com>
2021-06-17 10:43:17 +08:00
|
|
|
import './boot/initializers/setWebpackCdnHost'
|
2021-04-06 07:44:00 +08:00
|
|
|
import '@canvas/jquery/jquery.instructure_jquery_patches' // this needs to be before anything else that requires jQuery
|
Insert language polyfills at page load time
Refs FOO-1891
flag=none
Canvas officially supports a fixed set of languages and locales.
Unfortunately, not all browsers support all of those (the worst
offender oddly enough is Google Chrome). Fortunately, polyfills
for almost all of the Canvas supported languages are available
via a polyfill package.
This commit introduces a function that asynchronously loads the
polyfill for a requested language. It does nothing if it sees
there is already native support in the browser for that
language. The function can be imported and run to dynamically
switch in and out the polyfills as necessary, but since Canvas
never changes ENV.LOCALE except at page load time, it should
suffice to call it at front end initialization time; this was
added to ui/index.js as a part of its "readiness" checks.
The missing one (that NO browser supports) is Haitian Creole;
we will have to probably build our own locale data file for
that one.
This takes care of polyfilling DateTimeFormat, NumberFormat,
and RelativeTimeFormat. We can always add other Intl systems
if the need arises.
Test plan:
* Be on Chrome (which does not support the Welsh language)
* In the browser console, verify no native support for Welsh:
Intl.DateTimeFormat.supportedLocalesOf(['cy'])
... should return an empty array
* Go into your user settings on Canvas and change your language
to Welsh (Cymraeg). Reload the page to make it take effect.
Now your settings page should appear in Welsh.
* In the browser console, verify that dates and times can be
formatted correctly in Welsh (thanks to the polyfill):
Intl.DateTimeFormat('cy', {
dateStyle: 'long',
timeStyle: 'long'
}).format(new Date())
* That should display a date and time in Welsh (most prominently
seen in the name of the month).
Change-Id: I40632344ba1d8679aba1a976fcb55af97636be4b
Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/267359
Reviewed-by: Ahmad Amireh <ahmad@instructure.com>
Product-Review: Charley Kline <ckline@instructure.com>
Product-Review: Ahmad Amireh <ahmad@instructure.com>
QA-Review: Ahmad Amireh <ahmad@instructure.com>
Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com>
2021-06-17 10:43:17 +08:00
|
|
|
import './boot'
|
2018-03-07 10:12:53 +08:00
|
|
|
|
2019-05-17 04:30:07 +08:00
|
|
|
// true modules that we use in this file
|
|
|
|
import $ from 'jquery'
|
2019-07-31 07:04:16 +08:00
|
|
|
import ready from '@instructure/ready'
|
2021-04-06 07:44:00 +08:00
|
|
|
import Backbone from '@canvas/backbone'
|
|
|
|
import splitAssetString from '@canvas/util/splitAssetString'
|
Load mathjax if we find any inline LaTex
If the LaTex the user enters in the equation editor has errors, MathJax
will typeset it, with the bad parts in red. Unfortunately the services
canvas uses to generate the equation image simply fails. The equation
editor now verifies the image can be created and if not will insert the
raw LaTex into the RCE delimited by \(...\). Once the content is saved
MathJax will typeset it (includeing the red, but hey, that's better than
what used to happen)
now also looks for $$ or \( starting delimiters mathjax uses to identify
equations
and looks for math on wiki pages, which was missing before (that is not
behind the flag)
had to skip some screenreader_gradebook specs that started failing with
this change. The gradebook team is as baffled as I am. Will create a ticket
for them to investigate.
if MathJax finds LaTex errors (which you'll see as red in the preview
area), the service that generates the equation image fails. This detects
that and puts the raw LaTex back into the RCE's content. On saving,
MathJax can process it, though it will still show the red. This is better
than losing the equation because the image was missing.
closes LS-1488
flag=inline_math_everywhere
test plan
- turn on SiteAdmin feature "Updated math equation handling"
(flag=new_math_equation_handling) and the RootAccount feature
"Support LaTex math equations almost everywhere"
(flag=inline_math_everywhere)
- in the RCE, enter \(your equation here\)
- enter $$your equation here$$
- save
> expect the first equation to be typeset and inline
> expect the second equation to be typeset and a block
- the equations can span over multiple lines too
- edit an eq with the eq editor
> expect it to be typeset too
- in the RCE, click on the equation toolbar button
- in the advanced pane of the equation editor, enter \var = 27
> expect the \var part to be red in the preview area (because it's undefined)
- click Insert Equation
> expect the raw LaTex to be in the RCE, surrounded by \(...\)
- save
> expect the equation to get typeset (and \var will still be red)
- have an assignment with a student submission
- grade the submission and include an equation in the comments
for example: \(y = x^2\)
- view the assignment as the student
> expect the equation to be renered in the comment
- put some math in an assignment's title
> expect to see it in the assignments page
- create a page with inline math in it
> expect the math to be typeset
- create a discussion with math
- reply to the discussion with inline math in it
- edit the inline math in the reply
> expect the math to be typeset each time
- have a student submit an assignemnt
- as the teacher go to speedgrader
> expect typeset math everywhere
- add a comment with math
> expect it to get typeset
- goto /assignments/:id/submissions/:user_id
> expect comments with math to be typeset
- add a comment with math
> epxect it go get typeset
- old quizzes mostly work. While editing a question, inline
math is not typeset, but will be when previewed or being
taken
- new module items can have math in their title, but if you edit
the title, it's not typeset (this has baffled me, but it's
got to be an extremely rare case)
- load the calendar and flipping between Week, Month, Agenda views
> expect entries with inline math in their title to be typeset
- loading the calendar in different initial Views
> expect events with math to be typeset
- create a new event with math (e.g. "\(x^2\)"in the title
> expect it to be typeset when saved
- open an event in the calendar that has math in its body
> expect it to be typeset
Change-Id: Id5e1e822fad29a52bf21573e62976a4482afcf43
Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/248246
Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com>
Reviewed-by: Charley Kline <ckline@instructure.com>
QA-Review: Robin Kuss <rkuss@instructure.com>
Product-Review: Peyton Craighill <pcraighill@instructure.com>
2020-09-23 06:13:35 +08:00
|
|
|
import mathml from 'mathml'
|
2021-04-06 07:44:00 +08:00
|
|
|
import preventDefault from 'prevent-default'
|
2018-03-07 10:12:53 +08:00
|
|
|
import loadBundle from 'bundles-generated'
|
|
|
|
|
2019-05-17 04:30:07 +08:00
|
|
|
// these are all things that either define global $.whatever or $.fn.blah
|
|
|
|
// methods or set something up that other code expects to exist at runtime.
|
|
|
|
// so they have to be ran before any other app code runs.
|
2021-04-06 07:44:00 +08:00
|
|
|
import '@canvas/jquery/jquery.ajaxJSON'
|
|
|
|
import '@canvas/forms/jquery/jquery.instructure_forms'
|
Insert language polyfills at page load time
Refs FOO-1891
flag=none
Canvas officially supports a fixed set of languages and locales.
Unfortunately, not all browsers support all of those (the worst
offender oddly enough is Google Chrome). Fortunately, polyfills
for almost all of the Canvas supported languages are available
via a polyfill package.
This commit introduces a function that asynchronously loads the
polyfill for a requested language. It does nothing if it sees
there is already native support in the browser for that
language. The function can be imported and run to dynamically
switch in and out the polyfills as necessary, but since Canvas
never changes ENV.LOCALE except at page load time, it should
suffice to call it at front end initialization time; this was
added to ui/index.js as a part of its "readiness" checks.
The missing one (that NO browser supports) is Haitian Creole;
we will have to probably build our own locale data file for
that one.
This takes care of polyfilling DateTimeFormat, NumberFormat,
and RelativeTimeFormat. We can always add other Intl systems
if the need arises.
Test plan:
* Be on Chrome (which does not support the Welsh language)
* In the browser console, verify no native support for Welsh:
Intl.DateTimeFormat.supportedLocalesOf(['cy'])
... should return an empty array
* Go into your user settings on Canvas and change your language
to Welsh (Cymraeg). Reload the page to make it take effect.
Now your settings page should appear in Welsh.
* In the browser console, verify that dates and times can be
formatted correctly in Welsh (thanks to the polyfill):
Intl.DateTimeFormat('cy', {
dateStyle: 'long',
timeStyle: 'long'
}).format(new Date())
* That should display a date and time in Welsh (most prominently
seen in the name of the month).
Change-Id: I40632344ba1d8679aba1a976fcb55af97636be4b
Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/267359
Reviewed-by: Ahmad Amireh <ahmad@instructure.com>
Product-Review: Charley Kline <ckline@instructure.com>
Product-Review: Ahmad Amireh <ahmad@instructure.com>
QA-Review: Ahmad Amireh <ahmad@instructure.com>
Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com>
2021-06-17 10:43:17 +08:00
|
|
|
import './boot/initializers/ajax_errors'
|
|
|
|
import './boot/initializers/activateKeyClicks'
|
|
|
|
import './boot/initializers/activateTooltips'
|
2021-12-07 05:47:30 +08:00
|
|
|
import './boot/initializers/injectAuthTokenIntoForms'
|
2019-05-17 04:30:07 +08:00
|
|
|
|
2021-04-27 04:08:40 +08:00
|
|
|
window.canvasReadyState = 'loading'
|
|
|
|
window.dispatchEvent(new CustomEvent('canvasReadyStateChange'))
|
|
|
|
|
Redo the locale polyfiller using new features from @formatjs
Fixes FOO-2330
flag=none
Canvas supports locales that not all browsers support, so we have
to check for those cases and pull in a polyfilled version of the
Intl functions that we use (DateTimeFormat, NumberFormat, and
RelativeTimeFormat) when a locale is called for that the browser
does not support.
The first time the locale polyfiller was implemented, a lot of
tests had to be done to see if there was an available polyfill for
the given locale; this somehow broke Chrome after Version 92 so it
was disabled for Chrome. However, latest versions of the @formatjs
polyfillers are much smarter and can perform those checks and
fallbacks themselves, which makes the Canvas polyfiller code way
simpler and more stable.
An additional issue was uncovered: when the locale is being polyfilled,
NONE of the native locales can be accessed any more, so code relying on
being able to get at, say, 'en-US' to do date arithmetic was failing.
So when a polyfill loads, we save the browser's version as Native*
(so Intl.DateTimeFormat --> Intl.NativeDateTimeFormat) so it can
be accessed if needed (shouldn't be anywhere except in the ui/shared
datetime support code).
Another issue uncovered is that when a polyfill is necessary, it
seems to take a long time... it can be SECONDS before it is fully
loaded and its Promises resolve, at least in dev. Unfortunately a
lot of front-end code can start up and begin to use Intl functions
during that time, possibly with unpredictable results. The only real
answer is to make the execution of immediate bundles, and the call
to ready() to finish front-end initialization, wait pending the
resolution of the Promise indicating that the locales have loaded.
This is a bit unfortunate as it delays the execution of front-end
code, but will only be noticeable in locales that need polyfilling
because if a native locale is detected, the bundle loading and
call to ready() will happen immediately as before.
This commit does the following:
- changes the Rails js_env to include LOCALES instead of LOCALE.
LOCALES is a full list of locale strings in fallback order, so
that if `sv-SE-x-k12` isn't found, it will try `sv-SE` and
`sv-x-k12` and `sv` before finally falling back to `en`.
The front-end startup code backfills ENV.LOCALE to ENV.LOCALES[0]
for backward compatibility.
- up-revs @formatjs to a more recent version that implements the
check if a polyfill is available and leverages the LOCALES list
to find an available polyfill.
- Rewrites intl-polyfills to be smarter about detecting when a
polyfill is necessary and whether it is possible.
- Makes it easier to add new Intl subsystems to the polyfill code
should they start getting used in the Canvas code somewhere.
- Fixes up the helpers that relied upon the 'en-US' locale
specifically. They now specifically check for the Native version
of an Intl subsystem first.
- Fixes up the changeTimezone helpers in ui/shared/datetime because
they relied on the `en-US` locale always being available, which
is not true when the locale has been polyfilled. That was kind of
sketchy anyway because it relied on new Date() parsing a fairly
free-form English date and time string; it now constructs an
ISO8601 string which is much more supported as an argument to
new Date().
Test plan:
* Try some different locale scenarios and observe the behavior of
Canvas in that language in general, and also specifically how it
formats dates and times (this may be faster to do in console).
* Pay particular attention to places where datepickers are used,
specifically, create a new assignment and fiddle with the due
dates down near the bottom.
* Locale scenarios to try:
a native locale like de or es
-should just work
a native locale with an extension like sv-x-k12
-should just work
a polyfillable locale like cy or nn
-should work with a console message saying it is polyfilled
the one non-polyfillable locale: Kreyòl Ayisyen
-should work via a fallback all the way to 'en' on console
Change-Id: I93a1f2c3f0b3002747f564aba24c93d77244383e
Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/284509
Reviewed-by: Ahmad Amireh <ahmad@instructure.com>
QA-Review: Charley Kline <ckline@instructure.com>
Product-Review: Charley Kline <ckline@instructure.com>
Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com>
2022-02-05 08:03:25 +08:00
|
|
|
// Backfill LOCALE from LOCALES
|
|
|
|
if (!ENV.LOCALE && ENV.LOCALES instanceof Array) ENV.LOCALE = ENV.LOCALES[0]
|
|
|
|
|
2021-04-27 04:08:40 +08:00
|
|
|
const readinessTargets = [
|
Insert language polyfills at page load time
Refs FOO-1891
flag=none
Canvas officially supports a fixed set of languages and locales.
Unfortunately, not all browsers support all of those (the worst
offender oddly enough is Google Chrome). Fortunately, polyfills
for almost all of the Canvas supported languages are available
via a polyfill package.
This commit introduces a function that asynchronously loads the
polyfill for a requested language. It does nothing if it sees
there is already native support in the browser for that
language. The function can be imported and run to dynamically
switch in and out the polyfills as necessary, but since Canvas
never changes ENV.LOCALE except at page load time, it should
suffice to call it at front end initialization time; this was
added to ui/index.js as a part of its "readiness" checks.
The missing one (that NO browser supports) is Haitian Creole;
we will have to probably build our own locale data file for
that one.
This takes care of polyfilling DateTimeFormat, NumberFormat,
and RelativeTimeFormat. We can always add other Intl systems
if the need arises.
Test plan:
* Be on Chrome (which does not support the Welsh language)
* In the browser console, verify no native support for Welsh:
Intl.DateTimeFormat.supportedLocalesOf(['cy'])
... should return an empty array
* Go into your user settings on Canvas and change your language
to Welsh (Cymraeg). Reload the page to make it take effect.
Now your settings page should appear in Welsh.
* In the browser console, verify that dates and times can be
formatted correctly in Welsh (thanks to the polyfill):
Intl.DateTimeFormat('cy', {
dateStyle: 'long',
timeStyle: 'long'
}).format(new Date())
* That should display a date and time in Welsh (most prominently
seen in the name of the month).
Change-Id: I40632344ba1d8679aba1a976fcb55af97636be4b
Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/267359
Reviewed-by: Ahmad Amireh <ahmad@instructure.com>
Product-Review: Charley Kline <ckline@instructure.com>
Product-Review: Ahmad Amireh <ahmad@instructure.com>
QA-Review: Ahmad Amireh <ahmad@instructure.com>
Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com>
2021-06-17 10:43:17 +08:00
|
|
|
['asyncInitializers', false],
|
|
|
|
['deferredBundles', false],
|
2022-02-17 00:12:16 +08:00
|
|
|
['localeFiles', false],
|
Insert language polyfills at page load time
Refs FOO-1891
flag=none
Canvas officially supports a fixed set of languages and locales.
Unfortunately, not all browsers support all of those (the worst
offender oddly enough is Google Chrome). Fortunately, polyfills
for almost all of the Canvas supported languages are available
via a polyfill package.
This commit introduces a function that asynchronously loads the
polyfill for a requested language. It does nothing if it sees
there is already native support in the browser for that
language. The function can be imported and run to dynamically
switch in and out the polyfills as necessary, but since Canvas
never changes ENV.LOCALE except at page load time, it should
suffice to call it at front end initialization time; this was
added to ui/index.js as a part of its "readiness" checks.
The missing one (that NO browser supports) is Haitian Creole;
we will have to probably build our own locale data file for
that one.
This takes care of polyfilling DateTimeFormat, NumberFormat,
and RelativeTimeFormat. We can always add other Intl systems
if the need arises.
Test plan:
* Be on Chrome (which does not support the Welsh language)
* In the browser console, verify no native support for Welsh:
Intl.DateTimeFormat.supportedLocalesOf(['cy'])
... should return an empty array
* Go into your user settings on Canvas and change your language
to Welsh (Cymraeg). Reload the page to make it take effect.
Now your settings page should appear in Welsh.
* In the browser console, verify that dates and times can be
formatted correctly in Welsh (thanks to the polyfill):
Intl.DateTimeFormat('cy', {
dateStyle: 'long',
timeStyle: 'long'
}).format(new Date())
* That should display a date and time in Welsh (most prominently
seen in the name of the month).
Change-Id: I40632344ba1d8679aba1a976fcb55af97636be4b
Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/267359
Reviewed-by: Ahmad Amireh <ahmad@instructure.com>
Product-Review: Charley Kline <ckline@instructure.com>
Product-Review: Ahmad Amireh <ahmad@instructure.com>
QA-Review: Ahmad Amireh <ahmad@instructure.com>
Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com>
2021-06-17 10:43:17 +08:00
|
|
|
['localePolyfills', false]
|
2021-04-27 04:08:40 +08:00
|
|
|
]
|
|
|
|
const advanceReadiness = target => {
|
|
|
|
const entry = readinessTargets.find(x => x[0] === target)
|
|
|
|
|
|
|
|
if (!entry) {
|
|
|
|
throw new Error(`Invalid readiness target -- "${target}"`)
|
Insert language polyfills at page load time
Refs FOO-1891
flag=none
Canvas officially supports a fixed set of languages and locales.
Unfortunately, not all browsers support all of those (the worst
offender oddly enough is Google Chrome). Fortunately, polyfills
for almost all of the Canvas supported languages are available
via a polyfill package.
This commit introduces a function that asynchronously loads the
polyfill for a requested language. It does nothing if it sees
there is already native support in the browser for that
language. The function can be imported and run to dynamically
switch in and out the polyfills as necessary, but since Canvas
never changes ENV.LOCALE except at page load time, it should
suffice to call it at front end initialization time; this was
added to ui/index.js as a part of its "readiness" checks.
The missing one (that NO browser supports) is Haitian Creole;
we will have to probably build our own locale data file for
that one.
This takes care of polyfilling DateTimeFormat, NumberFormat,
and RelativeTimeFormat. We can always add other Intl systems
if the need arises.
Test plan:
* Be on Chrome (which does not support the Welsh language)
* In the browser console, verify no native support for Welsh:
Intl.DateTimeFormat.supportedLocalesOf(['cy'])
... should return an empty array
* Go into your user settings on Canvas and change your language
to Welsh (Cymraeg). Reload the page to make it take effect.
Now your settings page should appear in Welsh.
* In the browser console, verify that dates and times can be
formatted correctly in Welsh (thanks to the polyfill):
Intl.DateTimeFormat('cy', {
dateStyle: 'long',
timeStyle: 'long'
}).format(new Date())
* That should display a date and time in Welsh (most prominently
seen in the name of the month).
Change-Id: I40632344ba1d8679aba1a976fcb55af97636be4b
Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/267359
Reviewed-by: Ahmad Amireh <ahmad@instructure.com>
Product-Review: Charley Kline <ckline@instructure.com>
Product-Review: Ahmad Amireh <ahmad@instructure.com>
QA-Review: Ahmad Amireh <ahmad@instructure.com>
Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com>
2021-06-17 10:43:17 +08:00
|
|
|
} else if (entry[1]) {
|
2021-04-27 04:08:40 +08:00
|
|
|
throw new Error(`Target already marked ready -- "${target}"`)
|
|
|
|
}
|
|
|
|
|
|
|
|
entry[1] = true
|
2022-02-17 00:12:16 +08:00
|
|
|
window.dispatchEvent(new CustomEvent('canvasReadyStateChange', { detail: target }))
|
2021-04-27 04:08:40 +08:00
|
|
|
|
|
|
|
if (readinessTargets.every(x => x[1])) {
|
|
|
|
window.canvasReadyState = 'complete'
|
|
|
|
window.dispatchEvent(new CustomEvent('canvasReadyStateChange'))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Redo the locale polyfiller using new features from @formatjs
Fixes FOO-2330
flag=none
Canvas supports locales that not all browsers support, so we have
to check for those cases and pull in a polyfilled version of the
Intl functions that we use (DateTimeFormat, NumberFormat, and
RelativeTimeFormat) when a locale is called for that the browser
does not support.
The first time the locale polyfiller was implemented, a lot of
tests had to be done to see if there was an available polyfill for
the given locale; this somehow broke Chrome after Version 92 so it
was disabled for Chrome. However, latest versions of the @formatjs
polyfillers are much smarter and can perform those checks and
fallbacks themselves, which makes the Canvas polyfiller code way
simpler and more stable.
An additional issue was uncovered: when the locale is being polyfilled,
NONE of the native locales can be accessed any more, so code relying on
being able to get at, say, 'en-US' to do date arithmetic was failing.
So when a polyfill loads, we save the browser's version as Native*
(so Intl.DateTimeFormat --> Intl.NativeDateTimeFormat) so it can
be accessed if needed (shouldn't be anywhere except in the ui/shared
datetime support code).
Another issue uncovered is that when a polyfill is necessary, it
seems to take a long time... it can be SECONDS before it is fully
loaded and its Promises resolve, at least in dev. Unfortunately a
lot of front-end code can start up and begin to use Intl functions
during that time, possibly with unpredictable results. The only real
answer is to make the execution of immediate bundles, and the call
to ready() to finish front-end initialization, wait pending the
resolution of the Promise indicating that the locales have loaded.
This is a bit unfortunate as it delays the execution of front-end
code, but will only be noticeable in locales that need polyfilling
because if a native locale is detected, the bundle loading and
call to ready() will happen immediately as before.
This commit does the following:
- changes the Rails js_env to include LOCALES instead of LOCALE.
LOCALES is a full list of locale strings in fallback order, so
that if `sv-SE-x-k12` isn't found, it will try `sv-SE` and
`sv-x-k12` and `sv` before finally falling back to `en`.
The front-end startup code backfills ENV.LOCALE to ENV.LOCALES[0]
for backward compatibility.
- up-revs @formatjs to a more recent version that implements the
check if a polyfill is available and leverages the LOCALES list
to find an available polyfill.
- Rewrites intl-polyfills to be smarter about detecting when a
polyfill is necessary and whether it is possible.
- Makes it easier to add new Intl subsystems to the polyfill code
should they start getting used in the Canvas code somewhere.
- Fixes up the helpers that relied upon the 'en-US' locale
specifically. They now specifically check for the Native version
of an Intl subsystem first.
- Fixes up the changeTimezone helpers in ui/shared/datetime because
they relied on the `en-US` locale always being available, which
is not true when the locale has been polyfilled. That was kind of
sketchy anyway because it relied on new Date() parsing a fairly
free-form English date and time string; it now constructs an
ISO8601 string which is much more supported as an argument to
new Date().
Test plan:
* Try some different locale scenarios and observe the behavior of
Canvas in that language in general, and also specifically how it
formats dates and times (this may be faster to do in console).
* Pay particular attention to places where datepickers are used,
specifically, create a new assignment and fiddle with the due
dates down near the bottom.
* Locale scenarios to try:
a native locale like de or es
-should just work
a native locale with an extension like sv-x-k12
-should just work
a polyfillable locale like cy or nn
-should work with a console message saying it is polyfilled
the one non-polyfillable locale: Kreyòl Ayisyen
-should work via a fallback all the way to 'en' on console
Change-Id: I93a1f2c3f0b3002747f564aba24c93d77244383e
Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/284509
Reviewed-by: Ahmad Amireh <ahmad@instructure.com>
QA-Review: Charley Kline <ckline@instructure.com>
Product-Review: Charley Kline <ckline@instructure.com>
Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com>
2022-02-05 08:03:25 +08:00
|
|
|
function afterDocumentReady() {
|
Insert language polyfills at page load time
Refs FOO-1891
flag=none
Canvas officially supports a fixed set of languages and locales.
Unfortunately, not all browsers support all of those (the worst
offender oddly enough is Google Chrome). Fortunately, polyfills
for almost all of the Canvas supported languages are available
via a polyfill package.
This commit introduces a function that asynchronously loads the
polyfill for a requested language. It does nothing if it sees
there is already native support in the browser for that
language. The function can be imported and run to dynamically
switch in and out the polyfills as necessary, but since Canvas
never changes ENV.LOCALE except at page load time, it should
suffice to call it at front end initialization time; this was
added to ui/index.js as a part of its "readiness" checks.
The missing one (that NO browser supports) is Haitian Creole;
we will have to probably build our own locale data file for
that one.
This takes care of polyfilling DateTimeFormat, NumberFormat,
and RelativeTimeFormat. We can always add other Intl systems
if the need arises.
Test plan:
* Be on Chrome (which does not support the Welsh language)
* In the browser console, verify no native support for Welsh:
Intl.DateTimeFormat.supportedLocalesOf(['cy'])
... should return an empty array
* Go into your user settings on Canvas and change your language
to Welsh (Cymraeg). Reload the page to make it take effect.
Now your settings page should appear in Welsh.
* In the browser console, verify that dates and times can be
formatted correctly in Welsh (thanks to the polyfill):
Intl.DateTimeFormat('cy', {
dateStyle: 'long',
timeStyle: 'long'
}).format(new Date())
* That should display a date and time in Welsh (most prominently
seen in the name of the month).
Change-Id: I40632344ba1d8679aba1a976fcb55af97636be4b
Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/267359
Reviewed-by: Ahmad Amireh <ahmad@instructure.com>
Product-Review: Charley Kline <ckline@instructure.com>
Product-Review: Ahmad Amireh <ahmad@instructure.com>
QA-Review: Ahmad Amireh <ahmad@instructure.com>
Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com>
2021-06-17 10:43:17 +08:00
|
|
|
// eslint-disable-next-line promise/catch-or-return
|
Redo the locale polyfiller using new features from @formatjs
Fixes FOO-2330
flag=none
Canvas supports locales that not all browsers support, so we have
to check for those cases and pull in a polyfilled version of the
Intl functions that we use (DateTimeFormat, NumberFormat, and
RelativeTimeFormat) when a locale is called for that the browser
does not support.
The first time the locale polyfiller was implemented, a lot of
tests had to be done to see if there was an available polyfill for
the given locale; this somehow broke Chrome after Version 92 so it
was disabled for Chrome. However, latest versions of the @formatjs
polyfillers are much smarter and can perform those checks and
fallbacks themselves, which makes the Canvas polyfiller code way
simpler and more stable.
An additional issue was uncovered: when the locale is being polyfilled,
NONE of the native locales can be accessed any more, so code relying on
being able to get at, say, 'en-US' to do date arithmetic was failing.
So when a polyfill loads, we save the browser's version as Native*
(so Intl.DateTimeFormat --> Intl.NativeDateTimeFormat) so it can
be accessed if needed (shouldn't be anywhere except in the ui/shared
datetime support code).
Another issue uncovered is that when a polyfill is necessary, it
seems to take a long time... it can be SECONDS before it is fully
loaded and its Promises resolve, at least in dev. Unfortunately a
lot of front-end code can start up and begin to use Intl functions
during that time, possibly with unpredictable results. The only real
answer is to make the execution of immediate bundles, and the call
to ready() to finish front-end initialization, wait pending the
resolution of the Promise indicating that the locales have loaded.
This is a bit unfortunate as it delays the execution of front-end
code, but will only be noticeable in locales that need polyfilling
because if a native locale is detected, the bundle loading and
call to ready() will happen immediately as before.
This commit does the following:
- changes the Rails js_env to include LOCALES instead of LOCALE.
LOCALES is a full list of locale strings in fallback order, so
that if `sv-SE-x-k12` isn't found, it will try `sv-SE` and
`sv-x-k12` and `sv` before finally falling back to `en`.
The front-end startup code backfills ENV.LOCALE to ENV.LOCALES[0]
for backward compatibility.
- up-revs @formatjs to a more recent version that implements the
check if a polyfill is available and leverages the LOCALES list
to find an available polyfill.
- Rewrites intl-polyfills to be smarter about detecting when a
polyfill is necessary and whether it is possible.
- Makes it easier to add new Intl subsystems to the polyfill code
should they start getting used in the Canvas code somewhere.
- Fixes up the helpers that relied upon the 'en-US' locale
specifically. They now specifically check for the Native version
of an Intl subsystem first.
- Fixes up the changeTimezone helpers in ui/shared/datetime because
they relied on the `en-US` locale always being available, which
is not true when the locale has been polyfilled. That was kind of
sketchy anyway because it relied on new Date() parsing a fairly
free-form English date and time string; it now constructs an
ISO8601 string which is much more supported as an argument to
new Date().
Test plan:
* Try some different locale scenarios and observe the behavior of
Canvas in that language in general, and also specifically how it
formats dates and times (this may be faster to do in console).
* Pay particular attention to places where datepickers are used,
specifically, create a new assignment and fiddle with the due
dates down near the bottom.
* Locale scenarios to try:
a native locale like de or es
-should just work
a native locale with an extension like sv-x-k12
-should just work
a polyfillable locale like cy or nn
-should work with a console message saying it is polyfilled
the one non-polyfillable locale: Kreyòl Ayisyen
-should work via a fallback all the way to 'en' on console
Change-Id: I93a1f2c3f0b3002747f564aba24c93d77244383e
Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/284509
Reviewed-by: Ahmad Amireh <ahmad@instructure.com>
QA-Review: Charley Kline <ckline@instructure.com>
Product-Review: Charley Kline <ckline@instructure.com>
Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com>
2022-02-05 08:03:25 +08:00
|
|
|
Promise.all((window.deferredBundles || []).map(loadBundle)).then(() => {
|
Insert language polyfills at page load time
Refs FOO-1891
flag=none
Canvas officially supports a fixed set of languages and locales.
Unfortunately, not all browsers support all of those (the worst
offender oddly enough is Google Chrome). Fortunately, polyfills
for almost all of the Canvas supported languages are available
via a polyfill package.
This commit introduces a function that asynchronously loads the
polyfill for a requested language. It does nothing if it sees
there is already native support in the browser for that
language. The function can be imported and run to dynamically
switch in and out the polyfills as necessary, but since Canvas
never changes ENV.LOCALE except at page load time, it should
suffice to call it at front end initialization time; this was
added to ui/index.js as a part of its "readiness" checks.
The missing one (that NO browser supports) is Haitian Creole;
we will have to probably build our own locale data file for
that one.
This takes care of polyfilling DateTimeFormat, NumberFormat,
and RelativeTimeFormat. We can always add other Intl systems
if the need arises.
Test plan:
* Be on Chrome (which does not support the Welsh language)
* In the browser console, verify no native support for Welsh:
Intl.DateTimeFormat.supportedLocalesOf(['cy'])
... should return an empty array
* Go into your user settings on Canvas and change your language
to Welsh (Cymraeg). Reload the page to make it take effect.
Now your settings page should appear in Welsh.
* In the browser console, verify that dates and times can be
formatted correctly in Welsh (thanks to the polyfill):
Intl.DateTimeFormat('cy', {
dateStyle: 'long',
timeStyle: 'long'
}).format(new Date())
* That should display a date and time in Welsh (most prominently
seen in the name of the month).
Change-Id: I40632344ba1d8679aba1a976fcb55af97636be4b
Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/267359
Reviewed-by: Ahmad Amireh <ahmad@instructure.com>
Product-Review: Charley Kline <ckline@instructure.com>
Product-Review: Ahmad Amireh <ahmad@instructure.com>
QA-Review: Ahmad Amireh <ahmad@instructure.com>
Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com>
2021-06-17 10:43:17 +08:00
|
|
|
advanceReadiness('deferredBundles')
|
Redo the locale polyfiller using new features from @formatjs
Fixes FOO-2330
flag=none
Canvas supports locales that not all browsers support, so we have
to check for those cases and pull in a polyfilled version of the
Intl functions that we use (DateTimeFormat, NumberFormat, and
RelativeTimeFormat) when a locale is called for that the browser
does not support.
The first time the locale polyfiller was implemented, a lot of
tests had to be done to see if there was an available polyfill for
the given locale; this somehow broke Chrome after Version 92 so it
was disabled for Chrome. However, latest versions of the @formatjs
polyfillers are much smarter and can perform those checks and
fallbacks themselves, which makes the Canvas polyfiller code way
simpler and more stable.
An additional issue was uncovered: when the locale is being polyfilled,
NONE of the native locales can be accessed any more, so code relying on
being able to get at, say, 'en-US' to do date arithmetic was failing.
So when a polyfill loads, we save the browser's version as Native*
(so Intl.DateTimeFormat --> Intl.NativeDateTimeFormat) so it can
be accessed if needed (shouldn't be anywhere except in the ui/shared
datetime support code).
Another issue uncovered is that when a polyfill is necessary, it
seems to take a long time... it can be SECONDS before it is fully
loaded and its Promises resolve, at least in dev. Unfortunately a
lot of front-end code can start up and begin to use Intl functions
during that time, possibly with unpredictable results. The only real
answer is to make the execution of immediate bundles, and the call
to ready() to finish front-end initialization, wait pending the
resolution of the Promise indicating that the locales have loaded.
This is a bit unfortunate as it delays the execution of front-end
code, but will only be noticeable in locales that need polyfilling
because if a native locale is detected, the bundle loading and
call to ready() will happen immediately as before.
This commit does the following:
- changes the Rails js_env to include LOCALES instead of LOCALE.
LOCALES is a full list of locale strings in fallback order, so
that if `sv-SE-x-k12` isn't found, it will try `sv-SE` and
`sv-x-k12` and `sv` before finally falling back to `en`.
The front-end startup code backfills ENV.LOCALE to ENV.LOCALES[0]
for backward compatibility.
- up-revs @formatjs to a more recent version that implements the
check if a polyfill is available and leverages the LOCALES list
to find an available polyfill.
- Rewrites intl-polyfills to be smarter about detecting when a
polyfill is necessary and whether it is possible.
- Makes it easier to add new Intl subsystems to the polyfill code
should they start getting used in the Canvas code somewhere.
- Fixes up the helpers that relied upon the 'en-US' locale
specifically. They now specifically check for the Native version
of an Intl subsystem first.
- Fixes up the changeTimezone helpers in ui/shared/datetime because
they relied on the `en-US` locale always being available, which
is not true when the locale has been polyfilled. That was kind of
sketchy anyway because it relied on new Date() parsing a fairly
free-form English date and time string; it now constructs an
ISO8601 string which is much more supported as an argument to
new Date().
Test plan:
* Try some different locale scenarios and observe the behavior of
Canvas in that language in general, and also specifically how it
formats dates and times (this may be faster to do in console).
* Pay particular attention to places where datepickers are used,
specifically, create a new assignment and fiddle with the due
dates down near the bottom.
* Locale scenarios to try:
a native locale like de or es
-should just work
a native locale with an extension like sv-x-k12
-should just work
a polyfillable locale like cy or nn
-should work with a console message saying it is polyfilled
the one non-polyfillable locale: Kreyòl Ayisyen
-should work via a fallback all the way to 'en' on console
Change-Id: I93a1f2c3f0b3002747f564aba24c93d77244383e
Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/284509
Reviewed-by: Ahmad Amireh <ahmad@instructure.com>
QA-Review: Charley Kline <ckline@instructure.com>
Product-Review: Charley Kline <ckline@instructure.com>
Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com>
2022-02-05 08:03:25 +08:00
|
|
|
})
|
2020-06-12 00:07:43 +08:00
|
|
|
|
2020-12-04 06:44:01 +08:00
|
|
|
// LS-1662: there are math equations on the page that
|
|
|
|
// we don't see, so remain invisible and aren't
|
|
|
|
// typeset my MathJax. Let's trick Canvas into knowing
|
|
|
|
// there's math on the page by putting some there.
|
|
|
|
if (!/quizzes\/\d*\/edit/.test(window.location.pathname)) {
|
|
|
|
if (document.querySelector('.math_equation_latex')) {
|
|
|
|
const elem = document.createElement('math')
|
|
|
|
elem.innerHTML = ' '
|
|
|
|
document.body.appendChild(elem)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-02 22:56:45 +08:00
|
|
|
if (!ENV?.FEATURES?.new_math_equation_handling) {
|
2020-11-21 05:39:31 +08:00
|
|
|
// This is in a setTimeout to have it run on the next time through the event loop
|
|
|
|
// so that the code that actually renders the user_content runs first,
|
|
|
|
// because it has to be rendered before we can check if isMathMLOnPage
|
|
|
|
setTimeout(() => {
|
2020-11-22 07:36:48 +08:00
|
|
|
if (mathml.isMathOnPage()) mathml.loadMathJax(undefined)
|
2020-11-21 05:39:31 +08:00
|
|
|
}, 5)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2019-05-17 04:30:07 +08:00
|
|
|
// This is in a setTimeout to have it run on the next time through the event loop
|
|
|
|
// so that the code that actually renders the user_content runs first,
|
Load mathjax if we find any inline LaTex
If the LaTex the user enters in the equation editor has errors, MathJax
will typeset it, with the bad parts in red. Unfortunately the services
canvas uses to generate the equation image simply fails. The equation
editor now verifies the image can be created and if not will insert the
raw LaTex into the RCE delimited by \(...\). Once the content is saved
MathJax will typeset it (includeing the red, but hey, that's better than
what used to happen)
now also looks for $$ or \( starting delimiters mathjax uses to identify
equations
and looks for math on wiki pages, which was missing before (that is not
behind the flag)
had to skip some screenreader_gradebook specs that started failing with
this change. The gradebook team is as baffled as I am. Will create a ticket
for them to investigate.
if MathJax finds LaTex errors (which you'll see as red in the preview
area), the service that generates the equation image fails. This detects
that and puts the raw LaTex back into the RCE's content. On saving,
MathJax can process it, though it will still show the red. This is better
than losing the equation because the image was missing.
closes LS-1488
flag=inline_math_everywhere
test plan
- turn on SiteAdmin feature "Updated math equation handling"
(flag=new_math_equation_handling) and the RootAccount feature
"Support LaTex math equations almost everywhere"
(flag=inline_math_everywhere)
- in the RCE, enter \(your equation here\)
- enter $$your equation here$$
- save
> expect the first equation to be typeset and inline
> expect the second equation to be typeset and a block
- the equations can span over multiple lines too
- edit an eq with the eq editor
> expect it to be typeset too
- in the RCE, click on the equation toolbar button
- in the advanced pane of the equation editor, enter \var = 27
> expect the \var part to be red in the preview area (because it's undefined)
- click Insert Equation
> expect the raw LaTex to be in the RCE, surrounded by \(...\)
- save
> expect the equation to get typeset (and \var will still be red)
- have an assignment with a student submission
- grade the submission and include an equation in the comments
for example: \(y = x^2\)
- view the assignment as the student
> expect the equation to be renered in the comment
- put some math in an assignment's title
> expect to see it in the assignments page
- create a page with inline math in it
> expect the math to be typeset
- create a discussion with math
- reply to the discussion with inline math in it
- edit the inline math in the reply
> expect the math to be typeset each time
- have a student submit an assignemnt
- as the teacher go to speedgrader
> expect typeset math everywhere
- add a comment with math
> expect it to get typeset
- goto /assignments/:id/submissions/:user_id
> expect comments with math to be typeset
- add a comment with math
> epxect it go get typeset
- old quizzes mostly work. While editing a question, inline
math is not typeset, but will be when previewed or being
taken
- new module items can have math in their title, but if you edit
the title, it's not typeset (this has baffled me, but it's
got to be an extremely rare case)
- load the calendar and flipping between Week, Month, Agenda views
> expect entries with inline math in their title to be typeset
- loading the calendar in different initial Views
> expect events with math to be typeset
- create a new event with math (e.g. "\(x^2\)"in the title
> expect it to be typeset when saved
- open an event in the calendar that has math in its body
> expect it to be typeset
Change-Id: Id5e1e822fad29a52bf21573e62976a4482afcf43
Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/248246
Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com>
Reviewed-by: Charley Kline <ckline@instructure.com>
QA-Review: Robin Kuss <rkuss@instructure.com>
Product-Review: Peyton Craighill <pcraighill@instructure.com>
2020-09-23 06:13:35 +08:00
|
|
|
// because it has to be rendered before we can check if isMathOnPage
|
Make typeset math and math image match
at least get them much closer.
1. typeset math using svg by default, which is how the image is generated
2. size the image so it matches the surrounding font-size
Also, still typeset math from images even if the image fails to load.
closes MAT-501
flag=new_math_equation_handling
SIZING MATH REQUIRES A COMPANION CHANGE TO MATHMAN (the other stuff doesn't)
- clone git clone ssh://<yourid>@gerrit.instructure.com:29418/mathman
and follow the instructions for building.
- checkout https://gerrit.instructure.com/c/mathman/+/277389
- build it (once built, you don't have to run in in docker)
- in a canvas rails console:
Setting.set(
'equation_image_url,
'http://localhost:8000/svg?tex='
)
http://localhost:8000 is where mathman is via `node app.js`
it's at http://mathman.docker if in docker (at least that's
what the README says, I don't really know)
- test mathman by requesting `http://<mathman-url>/svg?tex=17`
and expect an image of "17". now try with `request /svg?tex=17&scale=2`
and your "17" shoul be twice as large.
- restart your canvas server
test plan:
Updated typesetting:
- have a question_bank quetsion with math and answers with math
- include the question in a quiz
> verify that the question looks the same in the question bank
as it does when previewing/taking the quiz
- if your math includes a "g", it should look the same
- the size of the equation should be pretty close
Sizing to match:
- turn on scale_math_equations site admin feature
- put an equation w/in a paragraph with a large font, or
add an equation to the rce, select it, and change the font size
- click on the equation, edit equation, click insert equation
w/o changing anything
> expect the equation to match the larger font.
- extra credit: DO THIS WITH AND WITHOUT MATHMAN PLUGIN ENABLED
(yes, there are 2 paths canvas takes to mathman)
make sure to update dyanmic-settings.yml's math-man entry
math-man:
base_url: 'http://localhost:8000'
use_for_svg: 'true'
use_for_mml: 'false'
- at /plugins, enable mathman plugin and ensure use_for_svg istrue
Error handling:
- change the URL to mathman to a dead end
- load a page with math equation images
> expect the math to be typeset by mathjax
Change-Id: I354e98a0a0256740ce5b4937f5b4e3adc690fe51
Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/277245
Reviewed-by: Weston Dransfield <wdransfield@instructure.com>
Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com>
QA-Review: Weston Dransfield <wdransfield@instructure.com>
Product-Review: David Lyons <lyons@instructure.com>
2021-11-02 20:52:12 +08:00
|
|
|
let processedBodyMath = false
|
2019-05-17 04:30:07 +08:00
|
|
|
setTimeout(() => {
|
Make typeset math and math image match
at least get them much closer.
1. typeset math using svg by default, which is how the image is generated
2. size the image so it matches the surrounding font-size
Also, still typeset math from images even if the image fails to load.
closes MAT-501
flag=new_math_equation_handling
SIZING MATH REQUIRES A COMPANION CHANGE TO MATHMAN (the other stuff doesn't)
- clone git clone ssh://<yourid>@gerrit.instructure.com:29418/mathman
and follow the instructions for building.
- checkout https://gerrit.instructure.com/c/mathman/+/277389
- build it (once built, you don't have to run in in docker)
- in a canvas rails console:
Setting.set(
'equation_image_url,
'http://localhost:8000/svg?tex='
)
http://localhost:8000 is where mathman is via `node app.js`
it's at http://mathman.docker if in docker (at least that's
what the README says, I don't really know)
- test mathman by requesting `http://<mathman-url>/svg?tex=17`
and expect an image of "17". now try with `request /svg?tex=17&scale=2`
and your "17" shoul be twice as large.
- restart your canvas server
test plan:
Updated typesetting:
- have a question_bank quetsion with math and answers with math
- include the question in a quiz
> verify that the question looks the same in the question bank
as it does when previewing/taking the quiz
- if your math includes a "g", it should look the same
- the size of the equation should be pretty close
Sizing to match:
- turn on scale_math_equations site admin feature
- put an equation w/in a paragraph with a large font, or
add an equation to the rce, select it, and change the font size
- click on the equation, edit equation, click insert equation
w/o changing anything
> expect the equation to match the larger font.
- extra credit: DO THIS WITH AND WITHOUT MATHMAN PLUGIN ENABLED
(yes, there are 2 paths canvas takes to mathman)
make sure to update dyanmic-settings.yml's math-man entry
math-man:
base_url: 'http://localhost:8000'
use_for_svg: 'true'
use_for_mml: 'false'
- at /plugins, enable mathman plugin and ensure use_for_svg istrue
Error handling:
- change the URL to mathman to a dead end
- load a page with math equation images
> expect the math to be typeset by mathjax
Change-Id: I354e98a0a0256740ce5b4937f5b4e3adc690fe51
Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/277245
Reviewed-by: Weston Dransfield <wdransfield@instructure.com>
Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com>
QA-Review: Weston Dransfield <wdransfield@instructure.com>
Product-Review: David Lyons <lyons@instructure.com>
2021-11-02 20:52:12 +08:00
|
|
|
processedBodyMath = true
|
2020-11-22 07:36:48 +08:00
|
|
|
window.dispatchEvent(
|
|
|
|
new CustomEvent(mathml.processNewMathEventName, {
|
|
|
|
detail: {target: document.body}
|
|
|
|
})
|
|
|
|
)
|
Load mathjax if we find any inline LaTex
If the LaTex the user enters in the equation editor has errors, MathJax
will typeset it, with the bad parts in red. Unfortunately the services
canvas uses to generate the equation image simply fails. The equation
editor now verifies the image can be created and if not will insert the
raw LaTex into the RCE delimited by \(...\). Once the content is saved
MathJax will typeset it (includeing the red, but hey, that's better than
what used to happen)
now also looks for $$ or \( starting delimiters mathjax uses to identify
equations
and looks for math on wiki pages, which was missing before (that is not
behind the flag)
had to skip some screenreader_gradebook specs that started failing with
this change. The gradebook team is as baffled as I am. Will create a ticket
for them to investigate.
if MathJax finds LaTex errors (which you'll see as red in the preview
area), the service that generates the equation image fails. This detects
that and puts the raw LaTex back into the RCE's content. On saving,
MathJax can process it, though it will still show the red. This is better
than losing the equation because the image was missing.
closes LS-1488
flag=inline_math_everywhere
test plan
- turn on SiteAdmin feature "Updated math equation handling"
(flag=new_math_equation_handling) and the RootAccount feature
"Support LaTex math equations almost everywhere"
(flag=inline_math_everywhere)
- in the RCE, enter \(your equation here\)
- enter $$your equation here$$
- save
> expect the first equation to be typeset and inline
> expect the second equation to be typeset and a block
- the equations can span over multiple lines too
- edit an eq with the eq editor
> expect it to be typeset too
- in the RCE, click on the equation toolbar button
- in the advanced pane of the equation editor, enter \var = 27
> expect the \var part to be red in the preview area (because it's undefined)
- click Insert Equation
> expect the raw LaTex to be in the RCE, surrounded by \(...\)
- save
> expect the equation to get typeset (and \var will still be red)
- have an assignment with a student submission
- grade the submission and include an equation in the comments
for example: \(y = x^2\)
- view the assignment as the student
> expect the equation to be renered in the comment
- put some math in an assignment's title
> expect to see it in the assignments page
- create a page with inline math in it
> expect the math to be typeset
- create a discussion with math
- reply to the discussion with inline math in it
- edit the inline math in the reply
> expect the math to be typeset each time
- have a student submit an assignemnt
- as the teacher go to speedgrader
> expect typeset math everywhere
- add a comment with math
> expect it to get typeset
- goto /assignments/:id/submissions/:user_id
> expect comments with math to be typeset
- add a comment with math
> epxect it go get typeset
- old quizzes mostly work. While editing a question, inline
math is not typeset, but will be when previewed or being
taken
- new module items can have math in their title, but if you edit
the title, it's not typeset (this has baffled me, but it's
got to be an extremely rare case)
- load the calendar and flipping between Week, Month, Agenda views
> expect entries with inline math in their title to be typeset
- loading the calendar in different initial Views
> expect events with math to be typeset
- create a new event with math (e.g. "\(x^2\)"in the title
> expect it to be typeset when saved
- open an event in the calendar that has math in its body
> expect it to be typeset
Change-Id: Id5e1e822fad29a52bf21573e62976a4482afcf43
Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/248246
Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com>
Reviewed-by: Charley Kline <ckline@instructure.com>
QA-Review: Robin Kuss <rkuss@instructure.com>
Product-Review: Peyton Craighill <pcraighill@instructure.com>
2020-09-23 06:13:35 +08:00
|
|
|
}, 0)
|
|
|
|
|
|
|
|
const observer = new MutationObserver((mutationList, _observer) => {
|
Make typeset math and math image match
at least get them much closer.
1. typeset math using svg by default, which is how the image is generated
2. size the image so it matches the surrounding font-size
Also, still typeset math from images even if the image fails to load.
closes MAT-501
flag=new_math_equation_handling
SIZING MATH REQUIRES A COMPANION CHANGE TO MATHMAN (the other stuff doesn't)
- clone git clone ssh://<yourid>@gerrit.instructure.com:29418/mathman
and follow the instructions for building.
- checkout https://gerrit.instructure.com/c/mathman/+/277389
- build it (once built, you don't have to run in in docker)
- in a canvas rails console:
Setting.set(
'equation_image_url,
'http://localhost:8000/svg?tex='
)
http://localhost:8000 is where mathman is via `node app.js`
it's at http://mathman.docker if in docker (at least that's
what the README says, I don't really know)
- test mathman by requesting `http://<mathman-url>/svg?tex=17`
and expect an image of "17". now try with `request /svg?tex=17&scale=2`
and your "17" shoul be twice as large.
- restart your canvas server
test plan:
Updated typesetting:
- have a question_bank quetsion with math and answers with math
- include the question in a quiz
> verify that the question looks the same in the question bank
as it does when previewing/taking the quiz
- if your math includes a "g", it should look the same
- the size of the equation should be pretty close
Sizing to match:
- turn on scale_math_equations site admin feature
- put an equation w/in a paragraph with a large font, or
add an equation to the rce, select it, and change the font size
- click on the equation, edit equation, click insert equation
w/o changing anything
> expect the equation to match the larger font.
- extra credit: DO THIS WITH AND WITHOUT MATHMAN PLUGIN ENABLED
(yes, there are 2 paths canvas takes to mathman)
make sure to update dyanmic-settings.yml's math-man entry
math-man:
base_url: 'http://localhost:8000'
use_for_svg: 'true'
use_for_mml: 'false'
- at /plugins, enable mathman plugin and ensure use_for_svg istrue
Error handling:
- change the URL to mathman to a dead end
- load a page with math equation images
> expect the math to be typeset by mathjax
Change-Id: I354e98a0a0256740ce5b4937f5b4e3adc690fe51
Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/277245
Reviewed-by: Weston Dransfield <wdransfield@instructure.com>
Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com>
QA-Review: Weston Dransfield <wdransfield@instructure.com>
Product-Review: David Lyons <lyons@instructure.com>
2021-11-02 20:52:12 +08:00
|
|
|
if (!processedBodyMath) return
|
New approach to MathJax-ifying equations
closes LS-1601
flag=new_math_equation_handling
The previous approach was to replace the equation image with the
equation's LaTeX in canvas' backend, but not all user content sent
to the browser passes through UserContent.escape. Discussions
and legacy quiz questions included. The backend approach also suffered
from the an ugly visual where the LaTeX is displayed onscreen until
MathJax typesets it.
In a previous commit, I caught Discussion replies in apiUserContent
where the screenreader assistive mathml is injected into the DOM
adjacent to the image. That worked but we now had 2 places
where the replacement was taking place, and quiz questions are
still being missed.
A better approach is to handle it all in a central location, which
is with the code that detects math is on the page. The new approach
is to inject the LaTeX into the DOM adjacent to the image just before
MathJax does its processing, then removes the image when it finished.
This way the equation image is displayed to the user while MathJaX
does its work, and since we look for new math in a MutationObserver
watching the whole document, we never miss any equation images on the page.
Because we are looking for mutations anywhere on the page, there may
be nodes we want to ignore (e.g. the quiz timer). This is handled
by adding to the ignore_list css selector in main.js
test plan:
- with the "Updated math equation handling" flag on
(and optionally 'Support LaTex math equations almost everywhere")
- double check that equations created with the rce equation editor
are processed with mathjax all over canvas
> expect equation images to be visible until replaced by MathJax
typeset versions
- Discussions:
- reply to a discussion with an equation (inline and equation editor)
> expect them to be typeset by mathjax
- edit a reply and save
> expect the the reply to have it's math processed by mathjax
- Legacy Quizzes
- create a quiz, set it so 1 question per page
- add a couple questions with equations
- preview the quiz, moving forward and back thru the questions
> expect the questions go have their equations typeset by mathjax
Change-Id: I9e2ec4fd53de06748156bbd4adadac7e2b1e205f
Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/252222
Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com>
Reviewed-by: Jackson Howe <jackson.howe@instructure.com>
QA-Review: Robin Kuss <rkuss@instructure.com>
Product-Review: Peyton Craighill <pcraighill@instructure.com>
2020-11-07 22:41:14 +08:00
|
|
|
for (let m = 0; m < mutationList.length; ++m) {
|
Load mathjax if we find any inline LaTex
If the LaTex the user enters in the equation editor has errors, MathJax
will typeset it, with the bad parts in red. Unfortunately the services
canvas uses to generate the equation image simply fails. The equation
editor now verifies the image can be created and if not will insert the
raw LaTex into the RCE delimited by \(...\). Once the content is saved
MathJax will typeset it (includeing the red, but hey, that's better than
what used to happen)
now also looks for $$ or \( starting delimiters mathjax uses to identify
equations
and looks for math on wiki pages, which was missing before (that is not
behind the flag)
had to skip some screenreader_gradebook specs that started failing with
this change. The gradebook team is as baffled as I am. Will create a ticket
for them to investigate.
if MathJax finds LaTex errors (which you'll see as red in the preview
area), the service that generates the equation image fails. This detects
that and puts the raw LaTex back into the RCE's content. On saving,
MathJax can process it, though it will still show the red. This is better
than losing the equation because the image was missing.
closes LS-1488
flag=inline_math_everywhere
test plan
- turn on SiteAdmin feature "Updated math equation handling"
(flag=new_math_equation_handling) and the RootAccount feature
"Support LaTex math equations almost everywhere"
(flag=inline_math_everywhere)
- in the RCE, enter \(your equation here\)
- enter $$your equation here$$
- save
> expect the first equation to be typeset and inline
> expect the second equation to be typeset and a block
- the equations can span over multiple lines too
- edit an eq with the eq editor
> expect it to be typeset too
- in the RCE, click on the equation toolbar button
- in the advanced pane of the equation editor, enter \var = 27
> expect the \var part to be red in the preview area (because it's undefined)
- click Insert Equation
> expect the raw LaTex to be in the RCE, surrounded by \(...\)
- save
> expect the equation to get typeset (and \var will still be red)
- have an assignment with a student submission
- grade the submission and include an equation in the comments
for example: \(y = x^2\)
- view the assignment as the student
> expect the equation to be renered in the comment
- put some math in an assignment's title
> expect to see it in the assignments page
- create a page with inline math in it
> expect the math to be typeset
- create a discussion with math
- reply to the discussion with inline math in it
- edit the inline math in the reply
> expect the math to be typeset each time
- have a student submit an assignemnt
- as the teacher go to speedgrader
> expect typeset math everywhere
- add a comment with math
> expect it to get typeset
- goto /assignments/:id/submissions/:user_id
> expect comments with math to be typeset
- add a comment with math
> epxect it go get typeset
- old quizzes mostly work. While editing a question, inline
math is not typeset, but will be when previewed or being
taken
- new module items can have math in their title, but if you edit
the title, it's not typeset (this has baffled me, but it's
got to be an extremely rare case)
- load the calendar and flipping between Week, Month, Agenda views
> expect entries with inline math in their title to be typeset
- loading the calendar in different initial Views
> expect events with math to be typeset
- create a new event with math (e.g. "\(x^2\)"in the title
> expect it to be typeset when saved
- open an event in the calendar that has math in its body
> expect it to be typeset
Change-Id: Id5e1e822fad29a52bf21573e62976a4482afcf43
Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/248246
Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com>
Reviewed-by: Charley Kline <ckline@instructure.com>
QA-Review: Robin Kuss <rkuss@instructure.com>
Product-Review: Peyton Craighill <pcraighill@instructure.com>
2020-09-23 06:13:35 +08:00
|
|
|
if (mutationList[m]?.addedNodes?.length) {
|
New approach to MathJax-ifying equations
closes LS-1601
flag=new_math_equation_handling
The previous approach was to replace the equation image with the
equation's LaTeX in canvas' backend, but not all user content sent
to the browser passes through UserContent.escape. Discussions
and legacy quiz questions included. The backend approach also suffered
from the an ugly visual where the LaTeX is displayed onscreen until
MathJax typesets it.
In a previous commit, I caught Discussion replies in apiUserContent
where the screenreader assistive mathml is injected into the DOM
adjacent to the image. That worked but we now had 2 places
where the replacement was taking place, and quiz questions are
still being missed.
A better approach is to handle it all in a central location, which
is with the code that detects math is on the page. The new approach
is to inject the LaTeX into the DOM adjacent to the image just before
MathJax does its processing, then removes the image when it finished.
This way the equation image is displayed to the user while MathJaX
does its work, and since we look for new math in a MutationObserver
watching the whole document, we never miss any equation images on the page.
Because we are looking for mutations anywhere on the page, there may
be nodes we want to ignore (e.g. the quiz timer). This is handled
by adding to the ignore_list css selector in main.js
test plan:
- with the "Updated math equation handling" flag on
(and optionally 'Support LaTex math equations almost everywhere")
- double check that equations created with the rce equation editor
are processed with mathjax all over canvas
> expect equation images to be visible until replaced by MathJax
typeset versions
- Discussions:
- reply to a discussion with an equation (inline and equation editor)
> expect them to be typeset by mathjax
- edit a reply and save
> expect the the reply to have it's math processed by mathjax
- Legacy Quizzes
- create a quiz, set it so 1 question per page
- add a couple questions with equations
- preview the quiz, moving forward and back thru the questions
> expect the questions go have their equations typeset by mathjax
Change-Id: I9e2ec4fd53de06748156bbd4adadac7e2b1e205f
Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/252222
Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com>
Reviewed-by: Jackson Howe <jackson.howe@instructure.com>
QA-Review: Robin Kuss <rkuss@instructure.com>
Product-Review: Peyton Craighill <pcraighill@instructure.com>
2020-11-07 22:41:14 +08:00
|
|
|
const addedNodes = mutationList[m].addedNodes
|
|
|
|
for (let n = 0; n < addedNodes.length; ++n) {
|
|
|
|
const node = addedNodes[n]
|
2020-11-17 00:17:48 +08:00
|
|
|
if (node.nodeType !== Node.ELEMENT_NODE) continue
|
2020-11-22 07:36:48 +08:00
|
|
|
const processNewMathEvent = new CustomEvent(mathml.processNewMathEventName, {
|
|
|
|
detail: {target: node}
|
|
|
|
})
|
2020-11-17 00:17:48 +08:00
|
|
|
window.dispatchEvent(processNewMathEvent)
|
New approach to MathJax-ifying equations
closes LS-1601
flag=new_math_equation_handling
The previous approach was to replace the equation image with the
equation's LaTeX in canvas' backend, but not all user content sent
to the browser passes through UserContent.escape. Discussions
and legacy quiz questions included. The backend approach also suffered
from the an ugly visual where the LaTeX is displayed onscreen until
MathJax typesets it.
In a previous commit, I caught Discussion replies in apiUserContent
where the screenreader assistive mathml is injected into the DOM
adjacent to the image. That worked but we now had 2 places
where the replacement was taking place, and quiz questions are
still being missed.
A better approach is to handle it all in a central location, which
is with the code that detects math is on the page. The new approach
is to inject the LaTeX into the DOM adjacent to the image just before
MathJax does its processing, then removes the image when it finished.
This way the equation image is displayed to the user while MathJaX
does its work, and since we look for new math in a MutationObserver
watching the whole document, we never miss any equation images on the page.
Because we are looking for mutations anywhere on the page, there may
be nodes we want to ignore (e.g. the quiz timer). This is handled
by adding to the ignore_list css selector in main.js
test plan:
- with the "Updated math equation handling" flag on
(and optionally 'Support LaTex math equations almost everywhere")
- double check that equations created with the rce equation editor
are processed with mathjax all over canvas
> expect equation images to be visible until replaced by MathJax
typeset versions
- Discussions:
- reply to a discussion with an equation (inline and equation editor)
> expect them to be typeset by mathjax
- edit a reply and save
> expect the the reply to have it's math processed by mathjax
- Legacy Quizzes
- create a quiz, set it so 1 question per page
- add a couple questions with equations
- preview the quiz, moving forward and back thru the questions
> expect the questions go have their equations typeset by mathjax
Change-Id: I9e2ec4fd53de06748156bbd4adadac7e2b1e205f
Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/252222
Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com>
Reviewed-by: Jackson Howe <jackson.howe@instructure.com>
QA-Review: Robin Kuss <rkuss@instructure.com>
Product-Review: Peyton Craighill <pcraighill@instructure.com>
2020-11-07 22:41:14 +08:00
|
|
|
}
|
Load mathjax if we find any inline LaTex
If the LaTex the user enters in the equation editor has errors, MathJax
will typeset it, with the bad parts in red. Unfortunately the services
canvas uses to generate the equation image simply fails. The equation
editor now verifies the image can be created and if not will insert the
raw LaTex into the RCE delimited by \(...\). Once the content is saved
MathJax will typeset it (includeing the red, but hey, that's better than
what used to happen)
now also looks for $$ or \( starting delimiters mathjax uses to identify
equations
and looks for math on wiki pages, which was missing before (that is not
behind the flag)
had to skip some screenreader_gradebook specs that started failing with
this change. The gradebook team is as baffled as I am. Will create a ticket
for them to investigate.
if MathJax finds LaTex errors (which you'll see as red in the preview
area), the service that generates the equation image fails. This detects
that and puts the raw LaTex back into the RCE's content. On saving,
MathJax can process it, though it will still show the red. This is better
than losing the equation because the image was missing.
closes LS-1488
flag=inline_math_everywhere
test plan
- turn on SiteAdmin feature "Updated math equation handling"
(flag=new_math_equation_handling) and the RootAccount feature
"Support LaTex math equations almost everywhere"
(flag=inline_math_everywhere)
- in the RCE, enter \(your equation here\)
- enter $$your equation here$$
- save
> expect the first equation to be typeset and inline
> expect the second equation to be typeset and a block
- the equations can span over multiple lines too
- edit an eq with the eq editor
> expect it to be typeset too
- in the RCE, click on the equation toolbar button
- in the advanced pane of the equation editor, enter \var = 27
> expect the \var part to be red in the preview area (because it's undefined)
- click Insert Equation
> expect the raw LaTex to be in the RCE, surrounded by \(...\)
- save
> expect the equation to get typeset (and \var will still be red)
- have an assignment with a student submission
- grade the submission and include an equation in the comments
for example: \(y = x^2\)
- view the assignment as the student
> expect the equation to be renered in the comment
- put some math in an assignment's title
> expect to see it in the assignments page
- create a page with inline math in it
> expect the math to be typeset
- create a discussion with math
- reply to the discussion with inline math in it
- edit the inline math in the reply
> expect the math to be typeset each time
- have a student submit an assignemnt
- as the teacher go to speedgrader
> expect typeset math everywhere
- add a comment with math
> expect it to get typeset
- goto /assignments/:id/submissions/:user_id
> expect comments with math to be typeset
- add a comment with math
> epxect it go get typeset
- old quizzes mostly work. While editing a question, inline
math is not typeset, but will be when previewed or being
taken
- new module items can have math in their title, but if you edit
the title, it's not typeset (this has baffled me, but it's
got to be an extremely rare case)
- load the calendar and flipping between Week, Month, Agenda views
> expect entries with inline math in their title to be typeset
- loading the calendar in different initial Views
> expect events with math to be typeset
- create a new event with math (e.g. "\(x^2\)"in the title
> expect it to be typeset when saved
- open an event in the calendar that has math in its body
> expect it to be typeset
Change-Id: Id5e1e822fad29a52bf21573e62976a4482afcf43
Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/248246
Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com>
Reviewed-by: Charley Kline <ckline@instructure.com>
QA-Review: Robin Kuss <rkuss@instructure.com>
Product-Review: Peyton Craighill <pcraighill@instructure.com>
2020-09-23 06:13:35 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
observer.observe(document.body, {
|
|
|
|
childList: true,
|
|
|
|
subtree: true
|
|
|
|
})
|
Redo the locale polyfiller using new features from @formatjs
Fixes FOO-2330
flag=none
Canvas supports locales that not all browsers support, so we have
to check for those cases and pull in a polyfilled version of the
Intl functions that we use (DateTimeFormat, NumberFormat, and
RelativeTimeFormat) when a locale is called for that the browser
does not support.
The first time the locale polyfiller was implemented, a lot of
tests had to be done to see if there was an available polyfill for
the given locale; this somehow broke Chrome after Version 92 so it
was disabled for Chrome. However, latest versions of the @formatjs
polyfillers are much smarter and can perform those checks and
fallbacks themselves, which makes the Canvas polyfiller code way
simpler and more stable.
An additional issue was uncovered: when the locale is being polyfilled,
NONE of the native locales can be accessed any more, so code relying on
being able to get at, say, 'en-US' to do date arithmetic was failing.
So when a polyfill loads, we save the browser's version as Native*
(so Intl.DateTimeFormat --> Intl.NativeDateTimeFormat) so it can
be accessed if needed (shouldn't be anywhere except in the ui/shared
datetime support code).
Another issue uncovered is that when a polyfill is necessary, it
seems to take a long time... it can be SECONDS before it is fully
loaded and its Promises resolve, at least in dev. Unfortunately a
lot of front-end code can start up and begin to use Intl functions
during that time, possibly with unpredictable results. The only real
answer is to make the execution of immediate bundles, and the call
to ready() to finish front-end initialization, wait pending the
resolution of the Promise indicating that the locales have loaded.
This is a bit unfortunate as it delays the execution of front-end
code, but will only be noticeable in locales that need polyfilling
because if a native locale is detected, the bundle loading and
call to ready() will happen immediately as before.
This commit does the following:
- changes the Rails js_env to include LOCALES instead of LOCALE.
LOCALES is a full list of locale strings in fallback order, so
that if `sv-SE-x-k12` isn't found, it will try `sv-SE` and
`sv-x-k12` and `sv` before finally falling back to `en`.
The front-end startup code backfills ENV.LOCALE to ENV.LOCALES[0]
for backward compatibility.
- up-revs @formatjs to a more recent version that implements the
check if a polyfill is available and leverages the LOCALES list
to find an available polyfill.
- Rewrites intl-polyfills to be smarter about detecting when a
polyfill is necessary and whether it is possible.
- Makes it easier to add new Intl subsystems to the polyfill code
should they start getting used in the Canvas code somewhere.
- Fixes up the helpers that relied upon the 'en-US' locale
specifically. They now specifically check for the Native version
of an Intl subsystem first.
- Fixes up the changeTimezone helpers in ui/shared/datetime because
they relied on the `en-US` locale always being available, which
is not true when the locale has been polyfilled. That was kind of
sketchy anyway because it relied on new Date() parsing a fairly
free-form English date and time string; it now constructs an
ISO8601 string which is much more supported as an argument to
new Date().
Test plan:
* Try some different locale scenarios and observe the behavior of
Canvas in that language in general, and also specifically how it
formats dates and times (this may be faster to do in console).
* Pay particular attention to places where datepickers are used,
specifically, create a new assignment and fiddle with the due
dates down near the bottom.
* Locale scenarios to try:
a native locale like de or es
-should just work
a native locale with an extension like sv-x-k12
-should just work
a polyfillable locale like cy or nn
-should work with a console message saying it is polyfilled
the one non-polyfillable locale: Kreyòl Ayisyen
-should work via a fallback all the way to 'en' on console
Change-Id: I93a1f2c3f0b3002747f564aba24c93d77244383e
Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/284509
Reviewed-by: Ahmad Amireh <ahmad@instructure.com>
QA-Review: Charley Kline <ckline@instructure.com>
Product-Review: Charley Kline <ckline@instructure.com>
Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com>
2022-02-05 08:03:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// This is because most pages use this and by having it all in it's own chunk it makes webpack
|
|
|
|
// split out a ton of stuff (like @instructure/ui-view) into multiple chunks because its chunking
|
|
|
|
// algorithm decides that because that chunk would either be too small or it would cause more than
|
|
|
|
// our maxAsyncRequests it should concat it into mutlple parents.
|
|
|
|
require.include('./features/navigation_header')
|
|
|
|
|
|
|
|
if (!window.bundles) window.bundles = []
|
|
|
|
|
|
|
|
// If you add to this be sure there is support for it in the intl-polyfills package!
|
|
|
|
const intlSubsystemsInUse = ['DateTimeFormat', 'RelativeTimeFormat', 'NumberFormat']
|
|
|
|
|
|
|
|
// Do we have native support in the given Intl subsystem for one of the current
|
|
|
|
// locale fallbacks?
|
|
|
|
function noNativeSupport(sys) {
|
|
|
|
const locales = [...ENV.LOCALES]
|
|
|
|
// 'en' is the final fallback, don't settle for that unless it's the only
|
|
|
|
// available locale, in which case there is obviously native support.
|
|
|
|
if (locales.length < 1 || (locales.length === 1 && locales[0] === 'en')) return false
|
|
|
|
if (locales.slice(-1)[0] === 'en') locales.pop()
|
|
|
|
for (const locale of locales) {
|
|
|
|
const native = Intl[sys].supportedLocalesOf([locale])
|
|
|
|
if (native.length > 0) return false
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
async function maybePolyfillLocaleThenGo() {
|
2022-02-17 00:12:16 +08:00
|
|
|
await import(`../public/javascripts/translations/${ENV.LOCALE}`)
|
|
|
|
advanceReadiness('localeFiles')
|
|
|
|
|
Redo the locale polyfiller using new features from @formatjs
Fixes FOO-2330
flag=none
Canvas supports locales that not all browsers support, so we have
to check for those cases and pull in a polyfilled version of the
Intl functions that we use (DateTimeFormat, NumberFormat, and
RelativeTimeFormat) when a locale is called for that the browser
does not support.
The first time the locale polyfiller was implemented, a lot of
tests had to be done to see if there was an available polyfill for
the given locale; this somehow broke Chrome after Version 92 so it
was disabled for Chrome. However, latest versions of the @formatjs
polyfillers are much smarter and can perform those checks and
fallbacks themselves, which makes the Canvas polyfiller code way
simpler and more stable.
An additional issue was uncovered: when the locale is being polyfilled,
NONE of the native locales can be accessed any more, so code relying on
being able to get at, say, 'en-US' to do date arithmetic was failing.
So when a polyfill loads, we save the browser's version as Native*
(so Intl.DateTimeFormat --> Intl.NativeDateTimeFormat) so it can
be accessed if needed (shouldn't be anywhere except in the ui/shared
datetime support code).
Another issue uncovered is that when a polyfill is necessary, it
seems to take a long time... it can be SECONDS before it is fully
loaded and its Promises resolve, at least in dev. Unfortunately a
lot of front-end code can start up and begin to use Intl functions
during that time, possibly with unpredictable results. The only real
answer is to make the execution of immediate bundles, and the call
to ready() to finish front-end initialization, wait pending the
resolution of the Promise indicating that the locales have loaded.
This is a bit unfortunate as it delays the execution of front-end
code, but will only be noticeable in locales that need polyfilling
because if a native locale is detected, the bundle loading and
call to ready() will happen immediately as before.
This commit does the following:
- changes the Rails js_env to include LOCALES instead of LOCALE.
LOCALES is a full list of locale strings in fallback order, so
that if `sv-SE-x-k12` isn't found, it will try `sv-SE` and
`sv-x-k12` and `sv` before finally falling back to `en`.
The front-end startup code backfills ENV.LOCALE to ENV.LOCALES[0]
for backward compatibility.
- up-revs @formatjs to a more recent version that implements the
check if a polyfill is available and leverages the LOCALES list
to find an available polyfill.
- Rewrites intl-polyfills to be smarter about detecting when a
polyfill is necessary and whether it is possible.
- Makes it easier to add new Intl subsystems to the polyfill code
should they start getting used in the Canvas code somewhere.
- Fixes up the helpers that relied upon the 'en-US' locale
specifically. They now specifically check for the Native version
of an Intl subsystem first.
- Fixes up the changeTimezone helpers in ui/shared/datetime because
they relied on the `en-US` locale always being available, which
is not true when the locale has been polyfilled. That was kind of
sketchy anyway because it relied on new Date() parsing a fairly
free-form English date and time string; it now constructs an
ISO8601 string which is much more supported as an argument to
new Date().
Test plan:
* Try some different locale scenarios and observe the behavior of
Canvas in that language in general, and also specifically how it
formats dates and times (this may be faster to do in console).
* Pay particular attention to places where datepickers are used,
specifically, create a new assignment and fiddle with the due
dates down near the bottom.
* Locale scenarios to try:
a native locale like de or es
-should just work
a native locale with an extension like sv-x-k12
-should just work
a polyfillable locale like cy or nn
-should work with a console message saying it is polyfilled
the one non-polyfillable locale: Kreyòl Ayisyen
-should work via a fallback all the way to 'en' on console
Change-Id: I93a1f2c3f0b3002747f564aba24c93d77244383e
Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/284509
Reviewed-by: Ahmad Amireh <ahmad@instructure.com>
QA-Review: Charley Kline <ckline@instructure.com>
Product-Review: Charley Kline <ckline@instructure.com>
Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com>
2022-02-05 08:03:25 +08:00
|
|
|
// If any Intl subsystem has no native support for the current locale, start
|
|
|
|
// trying to polyfill that locale from @formatjs. Note that this (possibly slow)
|
|
|
|
// process only executes at all if polyfilling was detected to be necessary.
|
|
|
|
if (intlSubsystemsInUse.some(noNativeSupport)) {
|
|
|
|
/* eslint-disable no-console */
|
|
|
|
try {
|
|
|
|
const im = await import('intl-polyfills')
|
|
|
|
const result = await im.loadAllLocalePolyfills(ENV.LOCALES, intlSubsystemsInUse)
|
|
|
|
result.forEach(r => {
|
|
|
|
if (r.error)
|
|
|
|
console.error(`${r.subsys} polyfill for locale "${r.locale}" failed: ${r.error}`)
|
|
|
|
if (r.source === 'polyfill')
|
|
|
|
console.info(`${r.subsys} polyfilled "${r.loaded}" for locale "${r.locale}"`)
|
|
|
|
})
|
|
|
|
} catch (e) {
|
|
|
|
console.error(`Locale polyfill load failed: ${e.message}`)
|
|
|
|
}
|
|
|
|
/* eslint-enable no-console */
|
|
|
|
}
|
2022-02-17 00:12:16 +08:00
|
|
|
|
Redo the locale polyfiller using new features from @formatjs
Fixes FOO-2330
flag=none
Canvas supports locales that not all browsers support, so we have
to check for those cases and pull in a polyfilled version of the
Intl functions that we use (DateTimeFormat, NumberFormat, and
RelativeTimeFormat) when a locale is called for that the browser
does not support.
The first time the locale polyfiller was implemented, a lot of
tests had to be done to see if there was an available polyfill for
the given locale; this somehow broke Chrome after Version 92 so it
was disabled for Chrome. However, latest versions of the @formatjs
polyfillers are much smarter and can perform those checks and
fallbacks themselves, which makes the Canvas polyfiller code way
simpler and more stable.
An additional issue was uncovered: when the locale is being polyfilled,
NONE of the native locales can be accessed any more, so code relying on
being able to get at, say, 'en-US' to do date arithmetic was failing.
So when a polyfill loads, we save the browser's version as Native*
(so Intl.DateTimeFormat --> Intl.NativeDateTimeFormat) so it can
be accessed if needed (shouldn't be anywhere except in the ui/shared
datetime support code).
Another issue uncovered is that when a polyfill is necessary, it
seems to take a long time... it can be SECONDS before it is fully
loaded and its Promises resolve, at least in dev. Unfortunately a
lot of front-end code can start up and begin to use Intl functions
during that time, possibly with unpredictable results. The only real
answer is to make the execution of immediate bundles, and the call
to ready() to finish front-end initialization, wait pending the
resolution of the Promise indicating that the locales have loaded.
This is a bit unfortunate as it delays the execution of front-end
code, but will only be noticeable in locales that need polyfilling
because if a native locale is detected, the bundle loading and
call to ready() will happen immediately as before.
This commit does the following:
- changes the Rails js_env to include LOCALES instead of LOCALE.
LOCALES is a full list of locale strings in fallback order, so
that if `sv-SE-x-k12` isn't found, it will try `sv-SE` and
`sv-x-k12` and `sv` before finally falling back to `en`.
The front-end startup code backfills ENV.LOCALE to ENV.LOCALES[0]
for backward compatibility.
- up-revs @formatjs to a more recent version that implements the
check if a polyfill is available and leverages the LOCALES list
to find an available polyfill.
- Rewrites intl-polyfills to be smarter about detecting when a
polyfill is necessary and whether it is possible.
- Makes it easier to add new Intl subsystems to the polyfill code
should they start getting used in the Canvas code somewhere.
- Fixes up the helpers that relied upon the 'en-US' locale
specifically. They now specifically check for the Native version
of an Intl subsystem first.
- Fixes up the changeTimezone helpers in ui/shared/datetime because
they relied on the `en-US` locale always being available, which
is not true when the locale has been polyfilled. That was kind of
sketchy anyway because it relied on new Date() parsing a fairly
free-form English date and time string; it now constructs an
ISO8601 string which is much more supported as an argument to
new Date().
Test plan:
* Try some different locale scenarios and observe the behavior of
Canvas in that language in general, and also specifically how it
formats dates and times (this may be faster to do in console).
* Pay particular attention to places where datepickers are used,
specifically, create a new assignment and fiddle with the due
dates down near the bottom.
* Locale scenarios to try:
a native locale like de or es
-should just work
a native locale with an extension like sv-x-k12
-should just work
a polyfillable locale like cy or nn
-should work with a console message saying it is polyfilled
the one non-polyfillable locale: Kreyòl Ayisyen
-should work via a fallback all the way to 'en' on console
Change-Id: I93a1f2c3f0b3002747f564aba24c93d77244383e
Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/284509
Reviewed-by: Ahmad Amireh <ahmad@instructure.com>
QA-Review: Charley Kline <ckline@instructure.com>
Product-Review: Charley Kline <ckline@instructure.com>
Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com>
2022-02-05 08:03:25 +08:00
|
|
|
// After possible polyfilling has completed, now we can start evaluating any
|
|
|
|
// queueud JS bundles, arrange for tasks to run after the document is fully ready,
|
|
|
|
// and advance the readiness state.
|
|
|
|
advanceReadiness('localePolyfills')
|
2022-02-17 00:12:16 +08:00
|
|
|
|
|
|
|
window.bundles.push = loadBundle
|
Redo the locale polyfiller using new features from @formatjs
Fixes FOO-2330
flag=none
Canvas supports locales that not all browsers support, so we have
to check for those cases and pull in a polyfilled version of the
Intl functions that we use (DateTimeFormat, NumberFormat, and
RelativeTimeFormat) when a locale is called for that the browser
does not support.
The first time the locale polyfiller was implemented, a lot of
tests had to be done to see if there was an available polyfill for
the given locale; this somehow broke Chrome after Version 92 so it
was disabled for Chrome. However, latest versions of the @formatjs
polyfillers are much smarter and can perform those checks and
fallbacks themselves, which makes the Canvas polyfiller code way
simpler and more stable.
An additional issue was uncovered: when the locale is being polyfilled,
NONE of the native locales can be accessed any more, so code relying on
being able to get at, say, 'en-US' to do date arithmetic was failing.
So when a polyfill loads, we save the browser's version as Native*
(so Intl.DateTimeFormat --> Intl.NativeDateTimeFormat) so it can
be accessed if needed (shouldn't be anywhere except in the ui/shared
datetime support code).
Another issue uncovered is that when a polyfill is necessary, it
seems to take a long time... it can be SECONDS before it is fully
loaded and its Promises resolve, at least in dev. Unfortunately a
lot of front-end code can start up and begin to use Intl functions
during that time, possibly with unpredictable results. The only real
answer is to make the execution of immediate bundles, and the call
to ready() to finish front-end initialization, wait pending the
resolution of the Promise indicating that the locales have loaded.
This is a bit unfortunate as it delays the execution of front-end
code, but will only be noticeable in locales that need polyfilling
because if a native locale is detected, the bundle loading and
call to ready() will happen immediately as before.
This commit does the following:
- changes the Rails js_env to include LOCALES instead of LOCALE.
LOCALES is a full list of locale strings in fallback order, so
that if `sv-SE-x-k12` isn't found, it will try `sv-SE` and
`sv-x-k12` and `sv` before finally falling back to `en`.
The front-end startup code backfills ENV.LOCALE to ENV.LOCALES[0]
for backward compatibility.
- up-revs @formatjs to a more recent version that implements the
check if a polyfill is available and leverages the LOCALES list
to find an available polyfill.
- Rewrites intl-polyfills to be smarter about detecting when a
polyfill is necessary and whether it is possible.
- Makes it easier to add new Intl subsystems to the polyfill code
should they start getting used in the Canvas code somewhere.
- Fixes up the helpers that relied upon the 'en-US' locale
specifically. They now specifically check for the Native version
of an Intl subsystem first.
- Fixes up the changeTimezone helpers in ui/shared/datetime because
they relied on the `en-US` locale always being available, which
is not true when the locale has been polyfilled. That was kind of
sketchy anyway because it relied on new Date() parsing a fairly
free-form English date and time string; it now constructs an
ISO8601 string which is much more supported as an argument to
new Date().
Test plan:
* Try some different locale scenarios and observe the behavior of
Canvas in that language in general, and also specifically how it
formats dates and times (this may be faster to do in console).
* Pay particular attention to places where datepickers are used,
specifically, create a new assignment and fiddle with the due
dates down near the bottom.
* Locale scenarios to try:
a native locale like de or es
-should just work
a native locale with an extension like sv-x-k12
-should just work
a polyfillable locale like cy or nn
-should work with a console message saying it is polyfilled
the one non-polyfillable locale: Kreyòl Ayisyen
-should work via a fallback all the way to 'en' on console
Change-Id: I93a1f2c3f0b3002747f564aba24c93d77244383e
Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/284509
Reviewed-by: Ahmad Amireh <ahmad@instructure.com>
QA-Review: Charley Kline <ckline@instructure.com>
Product-Review: Charley Kline <ckline@instructure.com>
Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com>
2022-02-05 08:03:25 +08:00
|
|
|
window.bundles.forEach(loadBundle)
|
|
|
|
ready(afterDocumentReady)
|
|
|
|
}
|
|
|
|
|
|
|
|
maybePolyfillLocaleThenGo().catch(e =>
|
|
|
|
// eslint-disable-next-line no-console
|
|
|
|
console.error(`Front-end bundles did not successfully start! (${e.message})`)
|
|
|
|
)
|
|
|
|
|
|
|
|
if (ENV.csp)
|
|
|
|
// eslint-disable-next-line promise/catch-or-return
|
|
|
|
import('./boot/initializers/setupCSP').then(({default: setupCSP}) => setupCSP(window.document))
|
|
|
|
if (ENV.INCOMPLETE_REGISTRATION) import('./boot/initializers/warnOnIncompleteRegistration')
|
|
|
|
if (ENV.badge_counts) import('./boot/initializers/showBadgeCounts')
|
|
|
|
|
|
|
|
$('html').removeClass('scripts-not-loaded')
|
|
|
|
|
|
|
|
$('.help_dialog_trigger').click(event => {
|
|
|
|
event.preventDefault()
|
|
|
|
// eslint-disable-next-line promise/catch-or-return
|
|
|
|
import('./boot/initializers/enableHelpDialog').then(({default: helpDialog}) => helpDialog.open())
|
|
|
|
})
|
|
|
|
|
|
|
|
// Backbone routes
|
|
|
|
$('body').on(
|
|
|
|
'click',
|
|
|
|
'[data-pushstate]',
|
|
|
|
preventDefault(function () {
|
|
|
|
Backbone.history.navigate($(this).attr('href'), true)
|
|
|
|
})
|
|
|
|
)
|
|
|
|
|
|
|
|
if (
|
|
|
|
window.ENV.NEW_USER_TUTORIALS &&
|
|
|
|
window.ENV.NEW_USER_TUTORIALS.is_enabled &&
|
|
|
|
window.ENV.context_asset_string &&
|
|
|
|
splitAssetString(window.ENV.context_asset_string)[0] === 'courses'
|
|
|
|
) {
|
|
|
|
// eslint-disable-next-line promise/catch-or-return
|
|
|
|
import('./features/new_user_tutorial/index').then(({default: initializeNewUserTutorials}) => {
|
|
|
|
initializeNewUserTutorials()
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
;(window.requestIdleCallback || window.setTimeout)(() => {
|
|
|
|
// eslint-disable-next-line promise/catch-or-return
|
|
|
|
import('./boot/initializers/runOnEveryPageButDontBlockAnythingElse').then(() =>
|
|
|
|
advanceReadiness('asyncInitializers')
|
|
|
|
)
|
2019-05-17 04:30:07 +08:00
|
|
|
})
|