@windward/core 0.2.3 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/babel.config.js +1 -1
- package/components/Content/Blocks/Accordion.vue +37 -0
- package/components/Content/Blocks/ClickableIcons.vue +107 -20
- package/components/Content/Blocks/Email.vue +9 -0
- package/components/Content/Blocks/Image.vue +48 -20
- package/components/Content/Blocks/UserUpload/ManageDataTableUserFiles.vue +1 -1
- package/components/Content/Blocks/UserUpload.vue +1 -1
- package/components/Content/Blocks/Video.vue +80 -9
- package/components/Navigation/Items/AskTheExpert.vue +2 -1
- package/components/Navigation/Items/CourseGlossaryToolNav.vue +2 -1
- package/components/Settings/AccordionSettings.vue +64 -4
- package/components/Settings/BlockQuoteSettings.vue +9 -1
- package/components/Settings/ClickableIconsSettings.vue +104 -13
- package/components/Settings/EmailSettings.vue +13 -13
- package/components/Settings/FeedbackSettings.vue +2 -1
- package/components/Settings/HorizontalRuleSettings.vue +2 -1
- package/components/Settings/ImageSettings.vue +148 -39
- package/components/Settings/MathSettings.vue +6 -5
- package/components/Settings/OpenResponseCollateSettings.vue +5 -1
- package/components/Settings/OpenResponseSettings.vue +9 -4
- package/components/Settings/ScenarioChoiceSettings.vue +15 -4
- package/components/Settings/TabSettings.vue +12 -4
- package/components/Settings/TextEditorSettings.vue +14 -7
- package/components/Settings/UserUploadSettings.vue +11 -4
- package/components/Settings/VideoSettings.vue +121 -66
- package/components/utils/ContentViewer.vue +6 -1
- package/components/utils/MathExpressionEditor.vue +10 -5
- package/components/utils/TinyMCEWrapper.vue +120 -19
- package/components/utils/assets/tinymce/content/dark/content.scss +4 -0
- package/components/utils/assets/tinymce/{css/content.scss → content/global.scss} +38 -37
- package/components/utils/assets/tinymce/content/light/content.scss +4 -0
- package/components/utils/assets/tinymce/ui/dark/content.scss +803 -0
- package/components/utils/assets/tinymce/ui/dark/skin.scss +4727 -0
- package/components/utils/assets/tinymce/ui/global.scss +19 -0
- package/components/utils/assets/tinymce/ui/light/content.scss +822 -0
- package/components/utils/assets/tinymce/ui/light/skin.scss +4731 -0
- package/components/utils/glossary/CourseGlossary.vue +4 -3
- package/components/utils/glossary/CourseGlossaryForm.vue +1 -1
- package/config/tinymce.config.ts +22 -14
- package/helpers/FillInBlankHelper.ts +34 -28
- package/helpers/GlossaryHelper.ts +90 -73
- package/helpers/MathHelper.ts +49 -28
- package/helpers/tinymce/plugin.ts +9 -7
- package/i18n/en-US/components/content/blocks/image.ts +1 -1
- package/i18n/en-US/components/settings/clickable_icon.ts +2 -0
- package/i18n/en-US/components/settings/image.ts +6 -1
- package/i18n/en-US/shared/settings.ts +3 -0
- package/i18n/es-ES/components/content/blocks/image.ts +1 -1
- package/i18n/es-ES/components/settings/clickable_icon.ts +2 -0
- package/i18n/es-ES/components/settings/image.ts +8 -1
- package/i18n/es-ES/shared/settings.ts +3 -0
- package/i18n/sv-SE/components/content/blocks/image.ts +1 -1
- package/i18n/sv-SE/components/settings/clickable_icon.ts +2 -0
- package/i18n/sv-SE/components/settings/image.ts +6 -1
- package/i18n/sv-SE/shared/settings.ts +3 -0
- package/package.json +4 -3
- package/test/Components/Settings/AccordionSettings.spec.js +16 -2
- package/test/__mocks__/componentsMock.js +57 -97
- package/test/__mocks__/contentBlockMock.js +7 -1
- package/test/__mocks__/contentSettingsMock.js +8 -1
- package/test/__mocks__/helpersMock.js +9 -0
- package/test/__mocks__/modelMock.js +101 -31
- package/test/helpers/MathHelper.spec.js +22 -3
- package/tsconfig.json +1 -0
- package/.idea/codeStyles/Project.xml +0 -58
- package/.idea/codeStyles/codeStyleConfig.xml +0 -5
- package/.idea/inspectionProfiles/Project_Default.xml +0 -6
- package/.idea/modules.xml +0 -8
- package/.idea/php-docker-settings.xml +0 -24
- package/.idea/php.xml +0 -19
- package/.idea/vcs.xml +0 -6
- package/.idea/watcherTasks.xml +0 -4
- package/.idea/windward-ui-plugin-core.iml +0 -8
- package/coverage/clover.xml +0 -223
- package/coverage/coverage-final.json +0 -16
- package/coverage/lcov-report/base.css +0 -224
- package/coverage/lcov-report/block-navigation.js +0 -87
- package/coverage/lcov-report/components/Content/Blocks/Accordion.vue.html +0 -430
- package/coverage/lcov-report/components/Content/Blocks/Image.vue.html +0 -394
- package/coverage/lcov-report/components/Content/Blocks/Math.vue.html +0 -262
- package/coverage/lcov-report/components/Content/Blocks/RichText.vue.html +0 -295
- package/coverage/lcov-report/components/Content/Blocks/Tab.vue.html +0 -415
- package/coverage/lcov-report/components/Content/Blocks/Table.vue.html +0 -667
- package/coverage/lcov-report/components/Content/Blocks/Video.vue.html +0 -2275
- package/coverage/lcov-report/components/Content/Blocks/index.html +0 -206
- package/coverage/lcov-report/components/utils/ContentViewer.vue.html +0 -199
- package/coverage/lcov-report/components/utils/MathExpressionEditor.vue.html +0 -919
- package/coverage/lcov-report/components/utils/MathLiveWrapper.vue.html +0 -343
- package/coverage/lcov-report/components/utils/TinyMCEWrapper.vue.html +0 -271
- package/coverage/lcov-report/components/utils/index.html +0 -161
- package/coverage/lcov-report/config/index.html +0 -116
- package/coverage/lcov-report/config/tinymce.config.js.html +0 -493
- package/coverage/lcov-report/favicon.png +0 -0
- package/coverage/lcov-report/helpers/MathHelper.ts.html +0 -793
- package/coverage/lcov-report/helpers/index.html +0 -116
- package/coverage/lcov-report/helpers/tinymce/index.html +0 -116
- package/coverage/lcov-report/helpers/tinymce/plugin.ts.html +0 -334
- package/coverage/lcov-report/index.html +0 -191
- package/coverage/lcov-report/prettify.css +0 -1
- package/coverage/lcov-report/prettify.js +0 -2
- package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/coverage/lcov-report/sorter.js +0 -196
- package/coverage/lcov-report/test/index.html +0 -116
- package/coverage/lcov-report/test/mocks.js.html +0 -457
- package/coverage/lcov.info +0 -403
- package/lib/helpers/GlossaryHelper.d.ts +0 -9
- package/lib/helpers/GlossaryHelper.js +0 -118
- package/lib/helpers/GlossaryTerm.d.ts +0 -10
- package/lib/helpers/GlossaryTerm.js +0 -22
- package/lib/helpers/MathHelper.d.ts +0 -99
- package/lib/helpers/MathHelper.js +0 -194
- package/lib/helpers/tinymce/plugin.d.ts +0 -2
- package/lib/helpers/tinymce/plugin.js +0 -86
- package/lib/i18n/en-US/components/content/blocks/image.d.ts +0 -6
- package/lib/i18n/en-US/components/content/blocks/image.js +0 -7
- package/lib/i18n/en-US/components/content/blocks/index.d.ts +0 -75
- package/lib/i18n/en-US/components/content/blocks/index.js +0 -14
- package/lib/i18n/en-US/components/content/blocks/tab.d.ts +0 -5
- package/lib/i18n/en-US/components/content/blocks/tab.js +0 -6
- package/lib/i18n/en-US/components/content/blocks/table.d.ts +0 -5
- package/lib/i18n/en-US/components/content/blocks/table.js +0 -6
- package/lib/i18n/en-US/components/content/blocks/user_upload.d.ts +0 -13
- package/lib/i18n/en-US/components/content/blocks/user_upload.js +0 -14
- package/lib/i18n/en-US/components/content/blocks/video.d.ts +0 -48
- package/lib/i18n/en-US/components/content/blocks/video.js +0 -49
- package/lib/i18n/en-US/components/content/index.d.ts +0 -77
- package/lib/i18n/en-US/components/content/index.js +0 -6
- package/lib/i18n/en-US/components/index.d.ts +0 -140
- package/lib/i18n/en-US/components/index.js +0 -12
- package/lib/i18n/en-US/components/navigation/image.d.ts +0 -5
- package/lib/i18n/en-US/components/navigation/image.js +0 -6
- package/lib/i18n/en-US/components/navigation/index.d.ts +0 -10
- package/lib/i18n/en-US/components/navigation/index.js +0 -8
- package/lib/i18n/en-US/components/navigation/user_upload.d.ts +0 -4
- package/lib/i18n/en-US/components/navigation/user_upload.js +0 -5
- package/lib/i18n/en-US/components/settings/clickable_icon.d.ts +0 -6
- package/lib/i18n/en-US/components/settings/clickable_icon.js +0 -7
- package/lib/i18n/en-US/components/settings/image.d.ts +0 -2
- package/lib/i18n/en-US/components/settings/image.js +0 -3
- package/lib/i18n/en-US/components/settings/index.d.ts +0 -39
- package/lib/i18n/en-US/components/settings/index.js +0 -14
- package/lib/i18n/en-US/components/settings/text_editor.d.ts +0 -8
- package/lib/i18n/en-US/components/settings/text_editor.js +0 -9
- package/lib/i18n/en-US/components/settings/user_upload.d.ts +0 -12
- package/lib/i18n/en-US/components/settings/user_upload.js +0 -13
- package/lib/i18n/en-US/components/settings/video.d.ts +0 -13
- package/lib/i18n/en-US/components/settings/video.js +0 -14
- package/lib/i18n/en-US/components/utils/index.d.ts +0 -15
- package/lib/i18n/en-US/components/utils/index.js +0 -6
- package/lib/i18n/en-US/components/utils/tiny_mce_wrapper.d.ts +0 -13
- package/lib/i18n/en-US/components/utils/tiny_mce_wrapper.js +0 -14
- package/lib/i18n/en-US/index.d.ts +0 -197
- package/lib/i18n/en-US/index.js +0 -16
- package/lib/i18n/en-US/modules/index.d.ts +0 -2
- package/lib/i18n/en-US/modules/index.js +0 -6
- package/lib/i18n/en-US/pages/glossary.d.ts +0 -8
- package/lib/i18n/en-US/pages/glossary.js +0 -9
- package/lib/i18n/en-US/pages/index.d.ts +0 -13
- package/lib/i18n/en-US/pages/index.js +0 -8
- package/lib/i18n/en-US/pages/user_upload.d.ts +0 -4
- package/lib/i18n/en-US/pages/user_upload.js +0 -5
- package/lib/i18n/en-US/shared/content_blocks.d.ts +0 -20
- package/lib/i18n/en-US/shared/content_blocks.js +0 -21
- package/lib/i18n/en-US/shared/index.d.ts +0 -39
- package/lib/i18n/en-US/shared/index.js +0 -10
- package/lib/i18n/en-US/shared/menu.d.ts +0 -4
- package/lib/i18n/en-US/shared/menu.js +0 -5
- package/lib/i18n/en-US/shared/settings.d.ts +0 -15
- package/lib/i18n/en-US/shared/settings.js +0 -16
- package/lib/i18n/en-US.d.ts +0 -197
- package/lib/i18n/en-US.js +0 -15
- package/lib/models/UserFileAsset.d.ts +0 -5
- package/lib/models/UserFileAsset.js +0 -37
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
<DialogBox
|
|
15
15
|
v-model="dialog"
|
|
16
16
|
color="primary"
|
|
17
|
-
max-width="
|
|
17
|
+
max-width="600"
|
|
18
18
|
:trigger="
|
|
19
19
|
$PermissionService.userHasAccessTo(
|
|
20
20
|
'windward.global.course,windward.organization.course.contentBlock',
|
|
@@ -145,14 +145,15 @@
|
|
|
145
145
|
<script>
|
|
146
146
|
import { mapGetters, mapMutations } from 'vuex'
|
|
147
147
|
import _ from 'lodash'
|
|
148
|
+
import DialogBox from '~/components/Core/DialogBox.vue'
|
|
148
149
|
import Crypto from '~/helpers/Crypto'
|
|
149
150
|
import Course from '~/models/Course'
|
|
150
|
-
import SpeedDial from '~/components/SpeedDial.vue'
|
|
151
|
+
import SpeedDial from '~/components/Core/SpeedDial.vue'
|
|
151
152
|
|
|
152
153
|
import CourseGlossaryForm from './CourseGlossaryForm'
|
|
153
154
|
export default {
|
|
154
155
|
name: 'CourseGlossary',
|
|
155
|
-
components: { CourseGlossaryForm, SpeedDial },
|
|
156
|
+
components: { DialogBox, CourseGlossaryForm, SpeedDial },
|
|
156
157
|
layout: 'course',
|
|
157
158
|
middleware: ['auth'],
|
|
158
159
|
props: {},
|
package/config/tinymce.config.ts
CHANGED
|
@@ -24,6 +24,14 @@ export default {
|
|
|
24
24
|
cmd: false,
|
|
25
25
|
text: 'i',
|
|
26
26
|
},
|
|
27
|
+
{
|
|
28
|
+
cmd: false,
|
|
29
|
+
text: '\\$',
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
cmd: false,
|
|
33
|
+
text: '\\%',
|
|
34
|
+
},
|
|
27
35
|
{
|
|
28
36
|
cmd: true,
|
|
29
37
|
text: '\\pi',
|
|
@@ -31,44 +39,43 @@ export default {
|
|
|
31
39
|
},
|
|
32
40
|
{
|
|
33
41
|
cmd: true,
|
|
34
|
-
text: '
|
|
35
|
-
latex: '
|
|
42
|
+
text: 'x^2',
|
|
43
|
+
latex: '^2',
|
|
36
44
|
},
|
|
37
45
|
{
|
|
38
46
|
cmd: true,
|
|
39
47
|
text: '{x}^{y}',
|
|
40
|
-
latex: '
|
|
48
|
+
latex: '^\\placeholder{}',
|
|
41
49
|
},
|
|
42
50
|
{
|
|
43
51
|
cmd: true,
|
|
44
52
|
text: '{x}_{y}',
|
|
45
|
-
latex: '
|
|
53
|
+
latex: '_\\placeholder{}',
|
|
46
54
|
},
|
|
47
55
|
{
|
|
48
56
|
text: '\\sqrt{x}',
|
|
49
|
-
latex: '\\sqrt{
|
|
57
|
+
latex: '\\sqrt{\\placeholder{}}',
|
|
50
58
|
cmd: true,
|
|
51
59
|
},
|
|
52
60
|
{
|
|
53
|
-
latex: '\\sqrt[\\placeholder{
|
|
61
|
+
latex: '\\sqrt[\\placeholder{}]{\\placeholder{}}',
|
|
54
62
|
text: '\\sqrt[n]{x}',
|
|
55
63
|
cmd: true,
|
|
56
64
|
},
|
|
57
65
|
{
|
|
58
|
-
cmd:
|
|
66
|
+
cmd: true,
|
|
59
67
|
text: '\\frac{x}{y}',
|
|
60
|
-
latex:
|
|
61
|
-
'\\frac\n' +
|
|
62
|
-
' {\\placeholder[numerator]{?}}\n' +
|
|
63
|
-
' {\\placeholder[denominator]{?}}',
|
|
68
|
+
latex: '\\frac',
|
|
64
69
|
},
|
|
65
70
|
{
|
|
66
|
-
cmd:
|
|
71
|
+
cmd: true,
|
|
67
72
|
text: '\\left|x\\right|',
|
|
73
|
+
latex: '\\left|\\placeholder{}\\right|',
|
|
68
74
|
},
|
|
69
75
|
{
|
|
70
|
-
cmd:
|
|
71
|
-
text: '\\left\\{\\right\\}',
|
|
76
|
+
cmd: true,
|
|
77
|
+
text: '\\left\\{x\\right\\}',
|
|
78
|
+
latex: '\\left\\{\\placeholder{}\\right\\}',
|
|
72
79
|
},
|
|
73
80
|
{
|
|
74
81
|
cmd: false,
|
|
@@ -78,6 +85,7 @@ export default {
|
|
|
78
85
|
cmd: false,
|
|
79
86
|
text: '(x,y)',
|
|
80
87
|
},
|
|
88
|
+
|
|
81
89
|
],
|
|
82
90
|
},
|
|
83
91
|
{
|
|
@@ -1,53 +1,59 @@
|
|
|
1
|
-
|
|
2
1
|
export default class FillInBlankHelper {
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
private static FillBlankRegex =
|
|
3
|
+
/<span.*?.class="windward-fill-blank".*?>(.*?)<\/span>/gi
|
|
5
4
|
|
|
6
5
|
public static containsFillInBlank(content: string): boolean {
|
|
7
|
-
const regex = new RegExp(this.FillBlankRegex)
|
|
6
|
+
const regex = new RegExp(this.FillBlankRegex)
|
|
8
7
|
|
|
9
|
-
return regex.exec(content) !== null
|
|
8
|
+
return regex.exec(content) !== null
|
|
10
9
|
}
|
|
11
10
|
|
|
12
11
|
public static makeToolTip(htmlString: string): string {
|
|
13
|
-
const parser = new DOMParser()
|
|
14
|
-
const doc = parser.parseFromString(htmlString,
|
|
12
|
+
const parser: any = new DOMParser()
|
|
13
|
+
const doc: any = parser.parseFromString(htmlString, 'text/html')
|
|
15
14
|
// doc.body.firstChild can be null
|
|
16
|
-
let answer = doc.body.firstChild ? doc.body.firstChild.textContent :
|
|
17
|
-
let feedback =
|
|
18
|
-
if (
|
|
19
|
-
|
|
15
|
+
let answer = doc.body.firstChild ? doc.body.firstChild.textContent : ''
|
|
16
|
+
let feedback = ''
|
|
17
|
+
if (
|
|
18
|
+
doc.body.getElementsByClassName('windward-fill-blank')[0][
|
|
19
|
+
'dataset'
|
|
20
|
+
]['feedback'] !== undefined
|
|
21
|
+
) {
|
|
22
|
+
feedback = doc.body.getElementsByClassName(
|
|
23
|
+
'windward-fill-blank'
|
|
24
|
+
)[0]['dataset']['feedback']
|
|
20
25
|
}
|
|
21
26
|
|
|
22
27
|
return (
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
28
|
+
'<plugin-core-fill-in-blank-input answer="' +
|
|
29
|
+
answer +
|
|
30
|
+
'" description="' +
|
|
31
|
+
feedback +
|
|
32
|
+
'">' +
|
|
33
|
+
'</template>' +
|
|
34
|
+
'</plugin-core-fill-in-blank-input>'
|
|
35
|
+
)
|
|
26
36
|
}
|
|
27
37
|
|
|
28
|
-
public escapeHtml(html) {
|
|
29
|
-
var text = document.createTextNode(html)
|
|
30
|
-
var p = document.createElement(
|
|
31
|
-
p.appendChild(text)
|
|
32
|
-
return p.innerHTML
|
|
38
|
+
public escapeHtml(html: any) {
|
|
39
|
+
var text = document.createTextNode(html)
|
|
40
|
+
var p = document.createElement('p')
|
|
41
|
+
p.appendChild(text)
|
|
42
|
+
return p.innerHTML
|
|
33
43
|
}
|
|
34
44
|
|
|
35
45
|
public static renderFillInTHeBlankHtml(content: string, glossary: any) {
|
|
36
|
-
const regex = new RegExp(this.FillBlankRegex)
|
|
37
|
-
|
|
46
|
+
const regex = new RegExp(this.FillBlankRegex)
|
|
38
47
|
|
|
39
|
-
let match
|
|
48
|
+
let match
|
|
40
49
|
while ((match = regex.exec(content)) !== null) {
|
|
41
50
|
// This is necessary to avoid infinite loops with zero-width matches
|
|
42
51
|
if (match.index === regex.lastIndex) {
|
|
43
|
-
regex.lastIndex
|
|
52
|
+
regex.lastIndex++
|
|
44
53
|
}
|
|
45
|
-
content = content.replace(
|
|
46
|
-
match[0],
|
|
47
|
-
this.makeToolTip(match[0])
|
|
48
|
-
);
|
|
54
|
+
content = content.replace(match[0], this.makeToolTip(match[0]))
|
|
49
55
|
}
|
|
50
56
|
|
|
51
|
-
return content
|
|
57
|
+
return content
|
|
52
58
|
}
|
|
53
59
|
}
|
|
@@ -1,53 +1,49 @@
|
|
|
1
|
-
import GlossaryTerm from
|
|
1
|
+
import GlossaryTerm from '../helpers/GlossaryTerm'
|
|
2
2
|
import * as _ from 'lodash'
|
|
3
3
|
|
|
4
4
|
export default class GlossaryHelper {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
+
|
|
33
|
-
alternate_forms
|
|
34
|
-
+
|
|
35
|
-
related_terms
|
|
36
|
-
+
|
|
37
|
-
'</plugin-core-glossary-tool-tip>')
|
|
38
|
-
|
|
5
|
+
private static glossaryRegex =
|
|
6
|
+
/<span.*?.class="glossary-word".*?>(.*?)<\/span>/g
|
|
7
|
+
public static makeToolTip(term: GlossaryTerm, text: String): string {
|
|
8
|
+
let word = _.isString(term.term)
|
|
9
|
+
? '<template v-slot:term>' + text + '</template>'
|
|
10
|
+
: ''
|
|
11
|
+
let definition = _.isString(term.definition)
|
|
12
|
+
? '<template v-slot:definition>' + term.definition + '</template>'
|
|
13
|
+
: ''
|
|
14
|
+
let alternate_forms = _.isString(term.alternate_forms)
|
|
15
|
+
? '<template v-slot:alternate_forms>' +
|
|
16
|
+
term.alternate_forms +
|
|
17
|
+
'</template>'
|
|
18
|
+
: ''
|
|
19
|
+
let related_terms = _.isString(term.related_term)
|
|
20
|
+
? '<template v-slot:related_terms>' +
|
|
21
|
+
term.related_term +
|
|
22
|
+
'</template>'
|
|
23
|
+
: ''
|
|
24
|
+
return (
|
|
25
|
+
'<plugin-core-glossary-tool-tip>' +
|
|
26
|
+
word +
|
|
27
|
+
definition +
|
|
28
|
+
alternate_forms +
|
|
29
|
+
related_terms +
|
|
30
|
+
'</plugin-core-glossary-tool-tip>'
|
|
31
|
+
)
|
|
39
32
|
}
|
|
40
|
-
public static containsGlossaryTerms(content
|
|
33
|
+
public static containsGlossaryTerms(content: string): boolean {
|
|
41
34
|
const regex = new RegExp(this.glossaryRegex)
|
|
42
35
|
|
|
43
36
|
return regex.exec(content) !== null
|
|
44
37
|
}
|
|
45
38
|
|
|
46
|
-
public static getContentVerifiedGlossaryTerms(
|
|
47
|
-
|
|
39
|
+
public static getContentVerifiedGlossaryTerms(
|
|
40
|
+
content: string,
|
|
41
|
+
glossary: any
|
|
42
|
+
) {
|
|
43
|
+
const regex = new RegExp(this.glossaryRegex)
|
|
48
44
|
const currentGlossary = glossary
|
|
49
45
|
|
|
50
|
-
let match
|
|
46
|
+
let match: any
|
|
51
47
|
const verifiedTerms: GlossaryTerm[] = []
|
|
52
48
|
while ((match = regex.exec(content)) !== null) {
|
|
53
49
|
// This is necessary to avoid infinite loops with zero-width matches
|
|
@@ -56,28 +52,40 @@ export default class GlossaryHelper {
|
|
|
56
52
|
}
|
|
57
53
|
|
|
58
54
|
// The result can be accessed through the `m`-variable.
|
|
59
|
-
currentGlossary.forEach((term) => {
|
|
55
|
+
currentGlossary.forEach((term: any) => {
|
|
60
56
|
let addTerm = true
|
|
61
|
-
verifiedTerms.forEach((verifiedTerm)=>{
|
|
62
|
-
if
|
|
57
|
+
verifiedTerms.forEach((verifiedTerm) => {
|
|
58
|
+
if (
|
|
59
|
+
_.trim(_.toLower(verifiedTerm.term)) ===
|
|
60
|
+
_.trim(_.toLower(term.term))
|
|
61
|
+
) {
|
|
63
62
|
addTerm = false
|
|
64
63
|
}
|
|
65
|
-
|
|
66
|
-
if (
|
|
64
|
+
})
|
|
65
|
+
if (
|
|
66
|
+
_.trim(_.toLower(match[1])) ===
|
|
67
|
+
_.trim(_.toLower(term.term)) &&
|
|
68
|
+
addTerm
|
|
69
|
+
) {
|
|
67
70
|
verifiedTerms.push(new GlossaryTerm(term))
|
|
68
71
|
}
|
|
69
72
|
})
|
|
70
|
-
|
|
71
73
|
}
|
|
72
74
|
|
|
73
75
|
return verifiedTerms
|
|
74
76
|
}
|
|
75
77
|
|
|
76
|
-
public static getContentUnVerifiedGlossaryTerms(
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
const
|
|
78
|
+
public static getContentUnVerifiedGlossaryTerms(
|
|
79
|
+
content: string,
|
|
80
|
+
glossary: any
|
|
81
|
+
) {
|
|
82
|
+
const regex: any = new RegExp(this.glossaryRegex)
|
|
83
|
+
|
|
84
|
+
let match: any
|
|
85
|
+
const verifiedTerms = this.getContentVerifiedGlossaryTerms(
|
|
86
|
+
content,
|
|
87
|
+
glossary
|
|
88
|
+
)
|
|
81
89
|
const unVerifiedTerms: GlossaryTerm[] = []
|
|
82
90
|
while ((match = regex.exec(content)) !== null) {
|
|
83
91
|
// This is necessary to avoid infinite loops with zero-width matches
|
|
@@ -87,33 +95,41 @@ export default class GlossaryHelper {
|
|
|
87
95
|
|
|
88
96
|
let inGlossary = []
|
|
89
97
|
|
|
90
|
-
inGlossary = glossary.filter(item =>
|
|
91
|
-
if
|
|
98
|
+
inGlossary = glossary.filter((item: any) => {
|
|
99
|
+
if (
|
|
100
|
+
_.trim(_.toLower(item.term)) === _.trim(_.toLower(match[1]))
|
|
101
|
+
) {
|
|
92
102
|
return item
|
|
93
|
-
|
|
94
103
|
}
|
|
95
|
-
})
|
|
104
|
+
})
|
|
96
105
|
|
|
97
106
|
let inUnverifiedArray = false
|
|
98
|
-
unVerifiedTerms.forEach((unVerifiedTerm)=>{
|
|
99
|
-
if
|
|
107
|
+
unVerifiedTerms.forEach((unVerifiedTerm: any) => {
|
|
108
|
+
if (
|
|
109
|
+
_.trim(_.toLower(unVerifiedTerm.term)) ===
|
|
110
|
+
_.trim(_.toLower(match[1]))
|
|
111
|
+
) {
|
|
100
112
|
inUnverifiedArray = true
|
|
101
113
|
}
|
|
102
114
|
})
|
|
103
|
-
if (
|
|
104
|
-
unVerifiedTerms.push(
|
|
115
|
+
if (inGlossary.length === 0 && !inUnverifiedArray) {
|
|
116
|
+
unVerifiedTerms.push(
|
|
117
|
+
new GlossaryTerm({
|
|
118
|
+
term: _.trim(match[1]),
|
|
119
|
+
definition: 'n/a',
|
|
120
|
+
})
|
|
121
|
+
)
|
|
105
122
|
}
|
|
106
|
-
|
|
107
|
-
|
|
108
123
|
}
|
|
109
124
|
|
|
110
125
|
return unVerifiedTerms
|
|
111
126
|
}
|
|
112
|
-
public static renderGlossaryWordsHtml(content
|
|
113
|
-
const regex = new RegExp(
|
|
114
|
-
const currentGlossary = glossary
|
|
127
|
+
public static renderGlossaryWordsHtml(content: string, glossary: any) {
|
|
128
|
+
const regex: any = new RegExp(this.glossaryRegex)
|
|
129
|
+
const currentGlossary: any = glossary
|
|
130
|
+
|
|
131
|
+
let match: any = []
|
|
115
132
|
|
|
116
|
-
let match
|
|
117
133
|
while ((match = regex.exec(content)) !== null) {
|
|
118
134
|
// This is necessary to avoid infinite loops with zero-width matches
|
|
119
135
|
if (match.index === regex.lastIndex) {
|
|
@@ -121,15 +137,16 @@ export default class GlossaryHelper {
|
|
|
121
137
|
}
|
|
122
138
|
|
|
123
139
|
// The result can be accessed through the `m`-variable.
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
140
|
+
currentGlossary.forEach((term: any) => {
|
|
141
|
+
if (
|
|
142
|
+
_.trim(_.toLower(match[1])) === _.trim(_.toLower(term.term))
|
|
143
|
+
) {
|
|
144
|
+
content = content.replace(
|
|
145
|
+
match[0],
|
|
146
|
+
this.makeToolTip(term, match[1])
|
|
147
|
+
)
|
|
148
|
+
}
|
|
149
|
+
})
|
|
133
150
|
}
|
|
134
151
|
|
|
135
152
|
return content
|
package/helpers/MathHelper.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as mathLiveObject from 'mathlive'
|
|
2
2
|
import * as _ from 'lodash'
|
|
3
|
-
import { MathMLToLaTeX } from 'mathml-to-latex'
|
|
3
|
+
import { MathMLToLaTeX } from 'mathml-to-latex'
|
|
4
4
|
export default class MathHelper {
|
|
5
5
|
/**
|
|
6
6
|
* expose mathlive object
|
|
@@ -67,38 +67,59 @@ export default class MathHelper {
|
|
|
67
67
|
return content
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
+
|
|
70
71
|
/**
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
* @
|
|
72
|
+
* Wraps math content.
|
|
73
|
+
*
|
|
74
|
+
* @param {string} match - The matched string to be wrapped.
|
|
75
|
+
* @param {string} content - The content to be replaced.
|
|
76
|
+
* @param {string} temp - The temporary string.
|
|
77
|
+
* @return {string} - The replaced content with wrapped math content.
|
|
78
|
+
*/
|
|
79
|
+
private static wrapMathContentMatch(match : string, content: string, temp: string): string {
|
|
80
|
+
let wrapped = `<span class ='windward-math-content'>${match}</span> `;
|
|
81
|
+
if (match.match(/\$\$.*?\$\$/g) !== null && temp !== '') {
|
|
82
|
+
wrapped = `<span class ='windward-math-content'>$$$${temp}$$$</span> `;
|
|
83
|
+
}
|
|
84
|
+
return content.replaceAll(match, wrapped);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Checks if the given content already has a specific template wrapped around it.
|
|
89
|
+
*
|
|
90
|
+
* @param {string} content - The original content to be checked.
|
|
91
|
+
* @param {string} match - The template string to be compared against.
|
|
92
|
+
* @param {string} temp - The temp string to be compared against for final template.
|
|
93
|
+
* @return {boolean} - True if the content already contains the specified template, false otherwise.
|
|
94
|
+
*/
|
|
95
|
+
private static contentAlreadyWrapped(content: string, match: string, temp: string): boolean {
|
|
96
|
+
const wrappedTemplates = [
|
|
97
|
+
`<span class=\"windward-math-content\" contenteditable=\"true\">$$${temp}$$</span>`,
|
|
98
|
+
`<span class='windward-math-content'>$$${temp}$$</span>`,
|
|
99
|
+
`<span class ='windward-math-content'>$$${temp}$$</span>`,
|
|
100
|
+
`<span class=\"windward-math-content\">$$${temp}$$</span>`];
|
|
101
|
+
return _.some(wrappedTemplates, template => _.includes(content, template));
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Wraps math content for TinyMCE.
|
|
106
|
+
*
|
|
107
|
+
* @param {string} content - The content to be wrapped.
|
|
108
|
+
* @returns {string} - The wrapped content.
|
|
75
109
|
*/
|
|
76
110
|
public static wrapMathContentForTinyMCE(content: string): string {
|
|
77
|
-
const regex = /(\*\*|\$\$)(.*?)\1/g
|
|
78
|
-
const matches = content.match(regex)
|
|
111
|
+
const regex = /(\*\*|\$\$)(.*?)\1/g;
|
|
112
|
+
const matches = content.match(regex);
|
|
113
|
+
|
|
79
114
|
if (matches) {
|
|
80
115
|
matches.forEach((match) => {
|
|
81
|
-
const temp = match.replace(/\$\$/g, '')
|
|
82
|
-
if (
|
|
83
|
-
content =
|
|
84
|
-
match,
|
|
85
|
-
"<span class ='windward-math-content'>$$$" +
|
|
86
|
-
temp +
|
|
87
|
-
'$$$</span>'
|
|
88
|
-
)
|
|
89
|
-
}
|
|
90
|
-
if (match.match(/\*\*(.*?)\*\*/g) !== null) {
|
|
91
|
-
content = content.replace(
|
|
92
|
-
match,
|
|
93
|
-
"<span class ='windward-math-content'>" +
|
|
94
|
-
match +
|
|
95
|
-
'</span>'
|
|
96
|
-
)
|
|
116
|
+
const temp = match.replace(/\$\$/g, '');
|
|
117
|
+
if (!this.contentAlreadyWrapped(content, match, temp)) {
|
|
118
|
+
content = this.wrapMathContentMatch(match, content, temp);
|
|
97
119
|
}
|
|
98
|
-
})
|
|
120
|
+
});
|
|
99
121
|
}
|
|
100
|
-
|
|
101
|
-
return content
|
|
122
|
+
return content;
|
|
102
123
|
}
|
|
103
124
|
|
|
104
125
|
/**
|
|
@@ -109,7 +130,7 @@ export default class MathHelper {
|
|
|
109
130
|
*/
|
|
110
131
|
public static checkMathContentWrappedForTMCE(content: string): boolean {
|
|
111
132
|
const regex =
|
|
112
|
-
|
|
133
|
+
/<span\s+class.*?=.*?(windward-math-content).*?>(.*?)<\/span>/g
|
|
113
134
|
|
|
114
135
|
return regex.exec(content) !== null
|
|
115
136
|
}
|
|
@@ -184,7 +205,7 @@ export default class MathHelper {
|
|
|
184
205
|
MathHelper.convertContentLatexToHtml(
|
|
185
206
|
MathHelper.convertContentMathMLtoLatex(content)
|
|
186
207
|
)
|
|
187
|
-
).replace(/contenteditable="true"/g, '')
|
|
208
|
+
).replace(/contenteditable="true"/g, '')
|
|
188
209
|
}
|
|
189
210
|
|
|
190
211
|
/**
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import MathHelper from "../MathHelper";
|
|
1
2
|
const WindwardPlugins = function (editor: any) {
|
|
2
3
|
let formula: any
|
|
3
4
|
let fillInBlank: any
|
|
@@ -12,8 +13,6 @@ const WindwardPlugins = function (editor: any) {
|
|
|
12
13
|
return editor.windowManager.openUrl({
|
|
13
14
|
url: '/plugins/tinymce/math',
|
|
14
15
|
title: 'Equation editor',
|
|
15
|
-
width: window.innerWidth*.50,
|
|
16
|
-
height: window.innerHeight*.75,
|
|
17
16
|
buttons: [
|
|
18
17
|
{
|
|
19
18
|
type: 'cancel',
|
|
@@ -32,7 +31,7 @@ const WindwardPlugins = function (editor: any) {
|
|
|
32
31
|
editor.selection.setContent(
|
|
33
32
|
` <span class='windward-math-content'>` +
|
|
34
33
|
formula +
|
|
35
|
-
`</span
|
|
34
|
+
`</span> `
|
|
36
35
|
)
|
|
37
36
|
|
|
38
37
|
editor.windowManager.close()
|
|
@@ -69,10 +68,15 @@ const WindwardPlugins = function (editor: any) {
|
|
|
69
68
|
setOnClickEquationContent(editor)
|
|
70
69
|
setOnClickFillInBlank(editor)
|
|
71
70
|
})
|
|
71
|
+
|
|
72
72
|
editor.on('SetContent', function () {
|
|
73
73
|
setOnClickEquationContent(editor)
|
|
74
74
|
setOnClickFillInBlank(editor)
|
|
75
75
|
})
|
|
76
|
+
editor.on('input', function () {
|
|
77
|
+
setOnClickEquationContent(editor)
|
|
78
|
+
setOnClickFillInBlank(editor)
|
|
79
|
+
})
|
|
76
80
|
function setOnClickEquationContent(editor: any) {
|
|
77
81
|
const tinymceDoc = editor.getDoc()
|
|
78
82
|
const mqSpan = tinymceDoc.getElementsByClassName(
|
|
@@ -86,7 +90,7 @@ const WindwardPlugins = function (editor: any) {
|
|
|
86
90
|
continue
|
|
87
91
|
}
|
|
88
92
|
|
|
89
|
-
equationContent.
|
|
93
|
+
equationContent.ondblclick = (event: any) => {
|
|
90
94
|
event.stopPropagation()
|
|
91
95
|
editor.execCommand('equation-window', {
|
|
92
96
|
latex: event.target.innerText,
|
|
@@ -100,8 +104,6 @@ const WindwardPlugins = function (editor: any) {
|
|
|
100
104
|
return editor.windowManager.openUrl({
|
|
101
105
|
url: '/plugins/tinymce/FIB',
|
|
102
106
|
title: 'Fill in the blank',
|
|
103
|
-
width: window.innerWidth*.50,
|
|
104
|
-
height: window.innerHeight*.75,
|
|
105
107
|
buttons: [
|
|
106
108
|
{
|
|
107
109
|
type: 'cancel',
|
|
@@ -193,7 +195,7 @@ const WindwardPlugins = function (editor: any) {
|
|
|
193
195
|
continue
|
|
194
196
|
}
|
|
195
197
|
|
|
196
|
-
fib.
|
|
198
|
+
fib.ondblclick = (event: any) => {
|
|
197
199
|
event.stopPropagation()
|
|
198
200
|
editor.execCommand('fib-window', {
|
|
199
201
|
answer: event.target.innerText,
|
|
@@ -8,10 +8,12 @@ export default {
|
|
|
8
8
|
item_color: 'Item Color',
|
|
9
9
|
item_text: 'Item Text',
|
|
10
10
|
autocolor: 'Auto-color Options',
|
|
11
|
+
icon_image: 'Use image for icon',
|
|
11
12
|
display: {
|
|
12
13
|
show_title: 'Always Show Title',
|
|
13
14
|
show_background: 'Show Background',
|
|
14
15
|
round_icon: 'Round Icons',
|
|
15
16
|
italic_icon: 'Italic Icons',
|
|
17
|
+
large_icon: 'Large Icons',
|
|
16
18
|
},
|
|
17
19
|
}
|
|
@@ -2,11 +2,16 @@ export default {
|
|
|
2
2
|
hide_background: 'Hide Background',
|
|
3
3
|
modal: 'Click to open in modal',
|
|
4
4
|
decorative: 'Decorative Image',
|
|
5
|
-
|
|
5
|
+
decorative_toggle_description:
|
|
6
6
|
'To meet accessibility standards, alt text is required for all images except for purely decorative images. This setting will add the proper alt text and screen reader text for learners.',
|
|
7
|
+
inherit_global_toggle_description:
|
|
8
|
+
'When enabled, the selected image will use alt text and screen reader text stored on the file, managed in the file manager. When disabled, the selected image will have its own unique alt text and screen reader text that is not shared globally on the file.',
|
|
7
9
|
alt_description:
|
|
8
10
|
'Alternative text is descriptive text that conveys the meaning and context of a visual item in a digital setting, intended for users who are visually impaired or otherwise unable to visually identify an image. This should be short and clear.',
|
|
9
11
|
screenreader: 'Screen Reader Text',
|
|
10
12
|
screenreader_description:
|
|
11
13
|
'Screen reader text can be added to give a user using assistive technology more information about the elements on the page',
|
|
14
|
+
inherit: 'Inherit global settings',
|
|
15
|
+
inherit_no_alt: 'No global alt text available for file',
|
|
16
|
+
inherit_no_aria: 'No global screen reader text available for file',
|
|
12
17
|
}
|