dont let tinymce strip span tags

closes CNVS-19814

adds "span" to the config string of valid elements, that's the fix.  To
make testing these easier in the future I created some integration-ish
tests for the config that actually stand up an instance and feed
an html string through it to see what it does with them.  That should
make testing these easier in the future.

also cleaned up a few missing semicolons
and inconsistent key/val styles.

TEST PLAN:
 - Go to any tinymce editor
 - switch to the HTML editor
 - add some code with a span tag
 - toggle back and forth between RCE and html editor
 - the span should not get stripped out
 - then follow the acceptance plan on the ticket to make sure their
    specific code example works (all the way through saving the context)

Change-Id: I51ff6a6bf9d1f823fa581fbb92ac83e7ad5f3e3e
Reviewed-on: https://gerrit.instructure.com/52251
Reviewed-by: Cody Cutrer <cody@instructure.com>
Tested-by: Jenkins
QA-Review: August Thornton <august@instructure.com>
Product-Review: Ethan Vizitei <evizitei@instructure.com>
This commit is contained in:
Ethan Vizitei 2015-04-15 10:12:50 -06:00
parent 937244a8e9
commit 029265e40f
2 changed files with 52 additions and 25 deletions

View File

@ -46,9 +46,9 @@ define([], function(){
return {
selector: "#" + this.idAttribute,
toolbar: this.toolbar(),
theme : "modern",
skin : "light",
skin_url : "/vendor/tinymce_themes/light",
theme: "modern",
skin: "light",
skin_url: "/vendor/tinymce_themes/light",
plugins: "autolink,media,paste,table,textcolor,link,directionality",
external_plugins: {
"instructure_image": "/javascripts/tinymce_plugins/instructure_image/plugin.js",
@ -66,11 +66,11 @@ define([], function(){
resize: true,
block_formats: "Paragraph=p;Header 2=h2;Header 3=h3;Header 4=h4;Preformatted=pre",
extended_valid_elements : "@[id|accesskey|class|dir|lang|style|tabindex|title|contenteditable|contextmenu|draggable|dropzone|hidden|spellcheck|translate|align|role|aria-labelledby|aria-atomic|aria-busy|aria-controls|aria-describedby|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[src|width|height|name|align|style|class|sandbox|allowfullscreen|webkitallowfullscreen|mozallowfullscreen],i[iclass],a[hidden|href|target|rel|media|hreflang|type|charset|name|rev|shape|coords|download],div,#p,h2,h3,h4,h5,h6,header,ul,ol,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],title,tr[char|charoff|valign|bgcolor],ul[compact]",
extended_valid_elements: "@[id|accesskey|class|dir|lang|style|tabindex|title|contenteditable|contextmenu|draggable|dropzone|hidden|spellcheck|translate|align|role|aria-labelledby|aria-atomic|aria-busy|aria-controls|aria-describedby|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[src|width|height|name|align|style|class|sandbox|allowfullscreen|webkitallowfullscreen|mozallowfullscreen],i[iclass],a[hidden|href|target|rel|media|hreflang|type|charset|name|rev|shape|coords|download],div,span,#p,h2,h3,h4,h5,h6,header,ul,ol,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],title,tr[char|charoff|valign|bgcolor],ul[compact]",
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',
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",
content_css: "/stylesheets_compiled/legacy_normal_contrast/bundles/what_gets_loaded_inside_the_tinymce_editor.css",
browser_spellcheck : true
browser_spellcheck: true
};
};
@ -84,7 +84,7 @@ define([], function(){
* @return {String} comma delimited set of external buttons
*/
EditorConfig.prototype.external_buttons = function(){
var externals = ""
var externals = "";
for(var idx in this.extraButtons) {
if(this.extraButtons.length <= this.maxButtons || idx < this.maxButtons - 1) {
externals = externals + ",instructure_external_button_" + this.extraButtons[idx].id;
@ -119,9 +119,9 @@ define([], function(){
* name doesn't need to happen 3 places or not work.
* @private
*/
EditorConfig.prototype.formatBtnGroup = 'bold,italic,underline,forecolor,backcolor,removeformat,alignleft,aligncenter,alignright';
EditorConfig.prototype.positionBtnGroup = 'outdent,indent,superscript,subscript,bullist,numlist';
EditorConfig.prototype.fontBtnGroup = 'ltr,rtl,fontsizeselect,formatselect';
EditorConfig.prototype.formatBtnGroup = "bold,italic,underline,forecolor,backcolor,removeformat,alignleft,aligncenter,alignright";
EditorConfig.prototype.positionBtnGroup = "outdent,indent,superscript,subscript,bullist,numlist";
EditorConfig.prototype.fontBtnGroup = "ltr,rtl,fontsizeselect,formatselect";
/**
@ -148,7 +148,7 @@ define([], function(){
} else {
buttons1 = this.formatBtnGroup + "," + this.positionBtnGroup + "," + instBtnGroup + "," + this.fontBtnGroup;
}
return [buttons1,buttons2,buttons3];
return [buttons1, buttons2, buttons3];
};
@ -162,7 +162,7 @@ define([], function(){
*/
EditorConfig.prototype.toolbar = function(){
var instructure_buttons = this.buildInstructureButtons();
return this.balanceButtons(instructure_buttons)
return this.balanceButtons(instructure_buttons);
};
return EditorConfig;

View File

@ -1,11 +1,17 @@
define ['tinymce.config'], (EditorConfig)->
define [
'jquery'
'tinymce.config'
'compiled/editor/stocktiny'
], ($,EditorConfig, tinymce)->
INST = null
largeScreenWidth = 1300
dom_id = "some_textarea"
tinymce = { baseURL: "/base/url" }
toolbar1 = "bold,italic,underline,forecolor,backcolor,removeformat,alignleft,aligncenter,alignright"
toolbar2 = "outdent,indent,superscript,subscript,bullist,numlist,table,instructure_links,unlink,instructure_image,instructure_equation"
fake_tinymce = { baseURL: "/base/url" }
toolbar1 = "bold,italic,underline,forecolor,backcolor,removeformat," +
"alignleft,aligncenter,alignright"
toolbar2 = "outdent,indent,superscript,subscript,bullist,numlist,table," +
"instructure_links,unlink,instructure_image,instructure_equation"
toolbar3 = "ltr,rtl,fontsizeselect,formatselect"
module "EditorConfig",
@ -20,14 +26,14 @@ define ['tinymce.config'], (EditorConfig)->
test 'buttons spread across rows for narrow windowing', ->
width = 100
config = new EditorConfig(tinymce, INST, width, dom_id)
config = new EditorConfig(fake_tinymce, INST, width, dom_id)
toolbar = config.toolbar()
ok(toolbar[0] is toolbar1)
ok(toolbar[1] is toolbar2)
ok(toolbar[2] is toolbar3)
test 'buttons go on the first row for large windowing', ->
config = new EditorConfig(tinymce, INST, largeScreenWidth, dom_id)
config = new EditorConfig(fake_tinymce, INST, largeScreenWidth, dom_id)
toolbar = config.toolbar()
equal(toolbar[0], "#{toolbar1},#{toolbar2},#{toolbar3}")
ok(toolbar[1] is "")
@ -35,40 +41,61 @@ define ['tinymce.config'], (EditorConfig)->
test "adding a few extra buttons", ->
INST.editorButtons = [{id: 'example', name: 'new_button'}]
config = new EditorConfig(tinymce, INST, largeScreenWidth, dom_id)
config = new EditorConfig(fake_tinymce, INST, largeScreenWidth, dom_id)
toolbar = config.toolbar()
ok(toolbar[0].match(/instructure_external_button_example/))
test "calculating an external button clump", ->
INST.editorButtons = [{id: 'example', name: 'new_button'}]
INST.maxVisibleEditorButtons = 0
config = new EditorConfig(tinymce, INST, largeScreenWidth, dom_id)
config = new EditorConfig(fake_tinymce, INST, largeScreenWidth, dom_id)
btns = config.external_buttons()
equal(btns, ",instructure_external_button_clump")
test "default config has static attributes", ->
INST.maxVisibleEditorButtons = 2
config = new EditorConfig(tinymce, INST, largeScreenWidth, dom_id)
config = new EditorConfig(fake_tinymce, INST, largeScreenWidth, dom_id)
schema = config.defaultConfig()
equal(schema.skin, 'light')
test "default config includes toolbar", ->
INST.maxVisibleEditorButtons = 2
config = new EditorConfig(tinymce, INST, largeScreenWidth, dom_id)
config = new EditorConfig(fake_tinymce, INST, largeScreenWidth, dom_id)
schema = config.defaultConfig()
equal(schema.toolbar[0], config.toolbar()[0])
test "it builds a selector from the id", ->
config = new EditorConfig(tinymce, INST, largeScreenWidth, dom_id)
config = new EditorConfig(fake_tinymce, INST, largeScreenWidth, dom_id)
schema = config.defaultConfig()
equal(schema.selector, "#some_textarea")
test "it loads up the right skin_url from an absolute path", ->
config = new EditorConfig(tinymce, INST, largeScreenWidth, dom_id)
config = new EditorConfig(fake_tinymce, INST, largeScreenWidth, dom_id)
schema = config.defaultConfig()
equal(schema.skin_url, "/vendor/tinymce_themes/light")
test "browser spellcheck enabled by default", ->
config = new EditorConfig(tinymce, INST, largeScreenWidth, dom_id)
config = new EditorConfig(fake_tinymce, INST, largeScreenWidth, dom_id)
schema = config.defaultConfig()
equal(schema.browser_spellcheck, true)
module "Tinymce Config Integration",
setup: ->
$("body").append("<textarea id=42></textarea>")
teardown: ->
$("textarea#42").remove()
asyncTest "configured not to strip spans", ->
expect(1)
$textarea = $("textarea#42")
config = new EditorConfig(tinymce, INST, 1000, "42")
configHash = $.extend(config.defaultConfig(),{
plugins: "",
external_plugins: {},
init_instance_callback: (editor)->
start()
content = editor.setContent("<span></span>")
ok(content.match("<span></span>"))
})
tinymce.init(configHash)