@instructure/canvas-rce
Version:
A component wrapping Canvas's usage of Tinymce
359 lines (357 loc) • 18.3 kB
JavaScript
/*
* Copyright (C) 2021 - 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/>.
*/
function elemsToTinyStringConfig(list) {
return Object.entries(list).map(pair => {
const [tag, attrs] = pair;
if (attrs.length === 0) {
return tag;
} else {
const attrStr = attrs.map(attr => {
if (typeof attr === 'string') {
return attr;
} else if (typeof attr === 'object') {
return Object.entries(attr).map(([key, value]) => `${key}=${value}`);
}
}).join('|');
return `${tag}[${attrStr}]`;
}
}).join();
}
const defaultTinymceConfig = {
// ============================================================================
// Values in this section have acceptable defaults which you may want
// to override (though you really should provide content_css)
// ============================================================================
auto_focus: false,
// any values provided (in an array) will be merged into the standard then sorted
// you provide the translations
block_formats: undefined,
// replace to provide your own
body_class: 'default-theme',
// urls to branding css go here
content_css: [],
// these are up to you
directionality: 'ltr',
height: undefined,
// '400px' is s the standard height
language: 'en',
// any menubar entries here will be appended to the standard menubar
menubar: undefined,
// any menus here will be merged into the standard menubar menus
menu: undefined,
// any toolbar data here will be merged into the standard toolbars
toolbar: undefined,
color_map: [
// First row
// tiny mce's default first row colors
'#BFEDD2', 'Light Green', '#FBEEB8', 'Light Orange', '#F8CAC6', 'Light Red', '#ECCAFA', 'Light Purple', '#C2E0F4', 'Light Blue',
// Second row
'#03893D',
// InstUI Green45
'Green', '#CF4A00',
// InstUI Orange45
'Orange', '#E62429',
// InstUI Red45
'Red', '#9E58BD',
// InstUI Violet45
'Purple', '#2B7ABC',
// InstUI Blue45
'Blue',
// Third row
'#027634',
// InstUI Green57
'Dark Green', '#B34000',
// InstUI Orange57
'Dark Orange', '#C71F23',
// InstUI Red57
'Dark Red', '#9242B4',
// InstUI Violet57
'Dark Purple', '#0E68B3',
// InstUI Blue57
'Dark Blue',
// Fourth row
'#FFFFFF', 'White', '#6A7883',
// InstUI Grey45
'Light Gray', '#3F515E',
// InstUI Grey82
'Gray', '#273540',
// InstUI Grey125
'Dark Gray', '#000000', 'Black'],
// plugins included here will be added to the standard set
plugins: undefined,
// ==================================================================================
// values below this line define standard behavior and probably shouldn't be changed
// but will be used if you do
// ==================================================================================
branding: false,
browser_spellcheck: true,
content_style: '',
convert_urls: false,
// fonts specified here need to either be web-safe or self-hosted and loaded in app/stylesheets/bundles/fonts.scss
font_formats: "Lato Extended=Lato Extended,Helvetica Neue,Helvetica,Arial,sans-serif; Balsamiq Sans=Balsamiq Sans,Lato Extended,Helvetica Neue,Helvetica,Arial,sans-serif; Architect's Daughter=Architects Daughter,Lato Extended,Helvetica Neue,Helvetica,Arial,sans-serif; Arial=arial,helvetica,sans-serif; Arial Black=arial black,avant garde; Courier New=courier new,courier; Georgia=georgia,palatino; Tahoma=tahoma,arial,helvetica,sans-serif; Times New Roman=times new roman,times; Trebuchet MS=trebuchet ms,geneva; Verdana=verdana,geneva; Open Dyslexic=OpenDyslexic; Open Dyslexic Mono=OpenDyslexicMono, Monaco, Menlo, Consolas, Courier New, monospace;",
language_load: false,
language_url: 'none',
toolbar_mode: 'floating',
mobile: {
theme: 'silver'
},
preview_styles: 'font-family font-size font-weight font-style text-decoration text-transform border border-radius outline text-shadow',
remove_script_host: true,
resize: true,
// will get set from textareaId
// selector: '#textarea2',
skin: false,
statusbar: false,
// part of unifying tinymce and canvas_sanitize's element whitelist
// copied from
// https://www.tiny.cloud/docs-3x/reference/configuration/Configuration3x@valid_elements/#defaultruleset
// then edited.
//
// this list needs to be kept in sync with the list in gems/canvas_sanitize/lib/canvas_sanitize/canvas_sanitize.rb
valid_elements: elemsToTinyStringConfig({
'@': ['id', 'class', 'style', 'title', 'dir<ltr?rtl', 'lang', 'xml::lang', 'role'],
a: ['rel', 'rev', 'charset', 'hreflang', 'tabindex', 'accesskey', 'type', 'name', 'href', 'target', 'title', 'class', 'data-old-link'],
'strong/b': [],
'em/i': [],
'strike/s': [],
u: [],
'#p': [],
'-ol': ['type', 'compact'],
'-ul': ['type', 'compact'],
'-li': [],
br: [],
img: ['longdesc', 'usemap', 'src', 'border', 'alt', 'title', 'hspace', 'vspace', 'width', 'height', 'align', 'role', 'data-old-link'],
'-sub': [],
'-sup': [],
'-blockquote': ['cite'],
'-table': [{
border: '0'
}, 'cellspacing', 'cellpadding', 'width', 'frame', 'rules', 'height', 'align', 'summary', 'bgcolor', 'background', 'bordercolor'],
'-tr': ['rowspan', 'width', 'height', 'align', 'valign', 'bgcolor', 'background', 'bordercolor'],
tbody: [],
thead: [],
tfoot: [],
'#td': ['colspan', 'rowspan', 'width', 'height', 'align', 'valign', 'bgcolor', 'background', 'bordercolor', 'scope'],
'#th': ['colspan', 'rowspan', 'width', 'height', 'align', 'valign', 'scope'],
caption: [],
'-div': [],
'-span': [],
'-code': [],
'-pre': [],
address: [],
'-h1': [],
'-h2': [],
'-h3': [],
'-h4': [],
'-h5': [],
'-h6': [],
hr: ['size', 'noshade'],
'-font': ['face', 'size', 'color'],
dd: [],
dl: [],
dt: [],
cite: [],
abbr: [],
acronym: [],
del: ['datetime', 'cite'],
ins: ['datetime', 'cite'],
object: ['classid', 'width', 'height', 'codebase', '*'],
param: ['name', 'value', '_value'],
embed: ['type', 'width', 'height', 'src', '*'],
map: ['name'],
area: ['shape', 'coords', 'href', 'alt', 'target'],
bdo: [],
col: ['align', 'char', 'charoff', 'span', 'valign', 'width'],
colgroup: ['align', 'char', 'charoff', 'span', 'valign', 'width'],
dfn: [],
kbd: [],
q: ['cite'],
samp: [],
small: [],
tt: [],
var: [],
big: [],
figure: [],
figcaption: [],
source: ['media', 'width', 'height', 'sizes', 'src', 'srcset', 'type', 'data-old-link'],
track: [],
mark: [],
article: [],
aside: [],
details: [],
footer: [],
header: [],
nav: [],
section: [],
summary: [],
time: []
}),
extended_valid_elements: elemsToTinyStringConfig({
'@': ['id', 'accesskey', 'class', 'dir', 'lang', 'style', 'tabindex', 'title', 'contenteditable', 'contextmenu', 'draggable', 'dropzone', 'hidden', 'longdesc', 'spellcheck', 'translate', 'align', 'role', 'aria-labelledby', 'aria-atomic', 'aria-busy', 'aria-controls', 'aria-describedby', 'aria-description', 'aria-disabled', 'aria-dropeffect', 'aria-flowto', 'aria-grabbed', 'aria-haspopup', 'aria-hidden', 'aria-invalid', 'aria-label', 'aria-labelledby', 'aria-live', 'aria-owns', 'aria-relevant', 'aria-autocomplete', 'aria-checked', 'aria-disabled', 'aria-expanded', 'aria-haspopup', 'aria-hidden', 'aria-invalid', 'aria-label', 'aria-level', 'aria-multiline', 'aria-multiselectable', 'aria-orientation', 'aria-pressed', 'aria-readonly', 'aria-required', 'aria-selected', 'aria-sort', 'aria-valuemax', 'aria-valuemin', 'aria-valuenow', 'aria-valuetext'],
iframe: ['id', 'data-media-type', 'title', 'src', 'width', 'height', 'name', 'align', 'style', 'class', 'sandbox', 'loading', 'allowfullscreen', 'webkitallowfullscreen', 'mozallowfullscreen', 'allow', 'data-old-link'],
i: ['iclass'],
a: ['hidden', 'href', 'target', 'rel', 'media', 'hreflang', 'type', 'charset', 'name', 'rev', 'shape', 'coords', 'download', 'alt'],
'#p': [],
li: ['value'],
'-ol': ['reversed', 'start', 'type', 'compact'],
pre: ['width'],
table: ['border', 'summary', 'width', 'frame', 'rules', 'cellspacing', 'cellpadding', 'bgcolor'],
tbody: ['char', 'charoff', 'valign'],
td: ['colspan', 'rowspan', 'headers', 'abbr', 'axis', 'scope', 'align', 'char', 'charoff', 'valign', 'nowrap', 'bgcolor', 'width', 'height'],
tfoot: ['char', 'charoff', 'valign'],
th: ['colspan', 'rowspan', 'headers', 'scope', 'abbr', 'axis', 'align', 'char', 'charoff', 'valign', 'nowrap', 'bgcolor', 'width', 'height'],
thead: ['char', 'charoff', 'valign'],
tr: ['char', 'charoff', 'valign', 'bgcolor'],
'-ul': ['compact'],
video: ['name', 'src', 'allowfullscreen', 'muted', 'poster', 'width', 'height', 'controls', 'playsinline'],
audio: ['name', 'src', 'muted', 'controls'],
annotation: ['href', 'xref', 'definitionURL', 'encoding', 'cd', 'name', 'src'],
'annotation-xml': ['href', 'xref', 'definitionURL', 'encoding', 'cd', 'name', 'src'],
maction: ['href', 'xref', 'mathcolor', 'mathbackground', 'actiontype', 'selection'],
maligngroup: ['href', 'xref', 'mathcolor', 'mathbackground', 'groupalign'],
malignmark: ['href', 'xref', 'mathcolor', 'mathbackground', 'edge'],
math: ['xmlns', 'href', 'xref', 'display', 'maxwidth', 'overflow', 'altimg', 'altimg-width', 'altimg-height', 'altimg-valign', 'alttext', 'cdgroup', 'mathcolor', 'mathbackground', 'scriptlevel', 'displaystyle', 'scriptsizemultiplier', 'scriptminsize', 'infixlinebreakstyle', 'decimalpoint', 'mathvariant', 'mathsize', 'width', 'height', 'valign', 'form', 'fence', 'separator', 'lspace', 'rspace', 'stretchy', 'symmetric', 'maxsize', 'minsize', 'largeop', 'movablelimits', 'accent', 'linebreak', 'lineleading', 'linebreakstyle', 'linebreakmultchar', 'indentalign', 'indentshift', 'indenttarget', 'indentalignfirst', 'indentshiftfirst', 'indentalignlast', 'indentshiftlast', 'depth', 'lquote', 'rquote', 'linethickness', 'munalign', 'denomalign', 'bevelled', 'voffset', 'open', 'close', 'separators', 'notation', 'subscriptshift', 'superscriptshift', 'accentunder', 'align', 'rowalign', 'columnalign', 'groupalign', 'alignmentscope', 'columnwidth', 'rowspacing', 'columnspacing', 'rowlines', 'columnlines', 'frame', 'framespacing', 'equalrows', 'equalcolumns', 'side', 'minlabelspacing', 'rowspan', 'columnspan', 'edge', 'stackalign', 'charalign', 'charspacing', 'longdivstyle', 'position', 'shift', 'location', 'crossout', 'length', 'leftoverhang', 'rightoverhang', 'mslinethickness', 'selection'],
menclose: ['href', 'xref', 'mathcolor', 'mathbackground', 'notation'],
merror: ['href', 'xref', 'mathcolor', 'mathbackground'],
mfenced: ['href', 'xref', 'mathcolor', 'mathbackground', 'open', 'close', 'separators'],
mfrac: ['href', 'xref', 'mathcolor', 'mathbackground', 'linethickness', 'munalign', 'denomalign', 'bevelled'],
mglyph: ['href', 'xref', 'mathcolor', 'mathbackground', 'src', 'alt', 'width', 'height', 'valign'],
mi: ['href', 'xref', 'mathcolor', 'mathbackground', 'mathvariant', 'mathsize'],
mlabeledtr: ['href', 'xref', 'mathcolor', 'mathbackground'],
mlongdiv: ['href', 'xref', 'mathcolor', 'mathbackground', 'longdivstyle', 'align', 'stackalign', 'charalign', 'charspacing'],
mmultiscripts: ['href', 'xref', 'mathcolor', 'mathbackground', 'subscriptshift', 'superscriptshift'],
mn: ['href', 'xref', 'mathcolor', 'mathbackground', 'mathvariant', 'mathsize'],
mo: ['href', 'xref', 'mathcolor', 'mathbackground', 'mathvariant', 'mathsize', 'form', 'fence', 'separator', 'lspace', 'rspace', 'stretchy', 'symmetric', 'maxsize', 'minsize', 'largeop', 'movablelimits', 'accent', 'linebreak', 'lineleading', 'linebreakstyle', 'linebreakmultchar', 'indentalign', 'indentshift', 'indenttarget', 'indentalignfirst', 'indentshiftfirst', 'indentalignlast', 'indentshiftlast'],
mover: ['href', 'xref', 'mathcolor', 'mathbackground', 'accent', 'align'],
mpadded: ['href', 'xref', 'mathcolor', 'mathbackground', 'height', 'depth', 'width', 'lspace', 'voffset'],
mphantom: ['href', 'xref', 'mathcolor', 'mathbackground'],
mprescripts: ['href', 'xref', 'mathcolor', 'mathbackground'],
mroot: ['href', 'xref', 'mathcolor', 'mathbackground'],
mrow: ['href', 'xref', 'mathcolor', 'mathbackground'],
ms: ['href', 'xref', 'mathcolor', 'mathbackground', 'mathvariant', 'mathsize', 'lquote', 'rquote'],
mscarries: ['href', 'xref', 'mathcolor', 'mathbackground', 'position', 'location', 'crossout', 'scriptsizemultiplier'],
mscarry: ['href', 'xref', 'mathcolor', 'mathbackground', 'location', 'crossout'],
msgroup: ['href', 'xref', 'mathcolor', 'mathbackground', 'position', 'shift'],
msline: ['href', 'xref', 'mathcolor', 'mathbackground', 'position', 'length', 'leftoverhang', 'rightoverhang', 'mslinethickness'],
mspace: ['href', 'xref', 'mathcolor', 'mathbackground', 'mathvariant', 'mathsize'],
msqrt: ['href', 'xref', 'mathcolor', 'mathbackground'],
msrow: ['href', 'xref', 'mathcolor', 'mathbackground', 'position'],
mstack: ['href', 'xref', 'mathcolor', 'mathbackground', 'align', 'stackalign', 'charalign', 'charspacing'],
mstyle: ['href', 'xref', 'mathcolor', 'mathbackground', 'scriptlevel', 'displaystyle', 'scriptsizemultiplier', 'scriptminsize', 'infixlinebreakstyle', 'decimalpoint', 'mathvariant', 'mathsize', 'width', 'height', 'valign', 'form', 'fence', 'separator', 'lspace', 'rspace', 'stretchy', 'symmetric', 'maxsize', 'minsize', 'largeop', 'movablelimits', 'accent', 'linebreak', 'lineleading', 'linebreakstyle', 'linebreakmultchar', 'indentalign', 'indentshift', 'indenttarget', 'indentalignfirst', 'indentshiftfirst', 'indentalignlast', 'indentshiftlast', 'depth', 'lquote', 'rquote', 'linethickness', 'munalign', 'denomalign', 'bevelled', 'voffset', 'open', 'close', 'separators', 'notation', 'subscriptshift', 'superscriptshift', 'accentunder', 'align', 'rowalign', 'columnalign', 'groupalign', 'alignmentscope', 'columnwidth', 'rowspacing', 'columnspacing', 'rowlines', 'columnlines', 'frame', 'framespacing', 'equalrows', 'equalcolumns', 'side', 'minlabelspacing', 'rowspan', 'columnspan', 'edge', 'stackalign', 'charalign', 'charspacing', 'longdivstyle', 'position', 'shift', 'location', 'crossout', 'length', 'leftoverhang', 'rightoverhang', 'mslinethickness', 'selection'],
msub: ['href', 'xref', 'mathcolor', 'mathbackground', 'subscriptshift'],
msubsup: ['href', 'xref', 'mathcolor', 'mathbackground', 'subscriptshift', 'superscriptshift'],
msup: ['href', 'xref', 'mathcolor', 'mathbackground', 'superscriptshift'],
mtable: ['href', 'xref', 'mathcolor', 'mathbackground', 'align', 'rowalign', 'columnalign', 'groupalign', 'alignmentscope', 'columnwidth', 'width', 'rowspacing', 'columnspacing', 'rowlines', 'columnlines', 'frame', 'framespacing', 'equalrows', 'equalcolumns', 'displaystyle', 'side', 'minlabelspacing'],
mtd: ['href', 'xref', 'mathcolor', 'mathbackground', 'rowspan', 'columnspan', 'rowalign', 'columnalign', 'groupalign'],
mtext: ['href', 'xref', 'mathcolor', 'mathbackground', 'mathvariant', 'mathsize', 'width', 'height', 'depth', 'linebreak'],
mtr: ['href', 'xref', 'mathcolor', 'mathbackground', 'rowalign', 'columnalign', 'groupalign'],
munder: ['href', 'xref', 'mathcolor', 'mathbackground', 'accentunder', 'align'],
munderover: ['href', 'xref', 'mathcolor', 'mathbackground', 'accent', 'accentunder', 'align'],
none: ['href', 'xref', 'mathcolor', 'mathbackground'],
semantics: ['href', 'xref', 'definitionURL', 'encoding'],
picture: [],
ruby: [],
rp: [],
rt: [],
g: ['*'],
circle: ['*']
}),
non_empty_elements: 'td th iframe video audio object script a i area base basefont br col frame hr img input isindex link meta param embed source wbr track ruby',
// tiny's external link create/edit dialog config
target_list: false,
// don't show the target list when creating/editing links
link_title: false,
// don't show the title input when creating/editing links
default_link_target: '_blank',
// Remove the ability to add h1 tags (since there will already be an h1 on the page)
// but preserve the default Formats menu config otherwise
style_formats: [{
title: 'Headings',
items: [{
title: 'Heading 2',
format: 'h2'
}, {
title: 'Heading 3',
format: 'h3'
}, {
title: 'Heading 4',
format: 'h4'
}, {
title: 'Heading 5',
format: 'h5'
}, {
title: 'Heading 6',
format: 'h6'
}]
}, {
title: 'Inline',
items: [{
title: 'Bold',
format: 'bold'
}, {
title: 'Italic',
format: 'italic'
}, {
title: 'Underline',
format: 'underline'
}, {
title: 'Strikethrough',
format: 'strikethrough'
}, {
title: 'Superscript',
format: 'superscript'
}, {
title: 'Subscript',
format: 'subscript'
}, {
title: 'Code',
format: 'code'
}]
}, {
title: 'Blocks',
items: [{
title: 'Paragraph',
format: 'p'
}, {
title: 'Blockquote',
format: 'blockquote'
}, {
title: 'Div',
format: 'div'
}, {
title: 'Pre',
format: 'pre'
}]
}, {
title: 'Align',
items: [{
title: 'Left',
format: 'alignleft'
}, {
title: 'Center',
format: 'aligncenter'
}, {
title: 'Right',
format: 'alignright'
}, {
title: 'Justify',
format: 'alignjustify'
}]
}]
};
export default defaultTinymceConfig;