wysihtml5x-rails 0.4.4 → 0.4.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,5 +1,5 @@
1
1
  module Wysihtml5x
2
2
  module Rails
3
- VERSION = "0.4.4"
3
+ VERSION = "0.4.5"
4
4
  end
5
5
  end
@@ -36,6 +36,7 @@ var wysihtml5ParserRules = {
36
36
  /**
37
37
  * CSS Class white-list
38
38
  * Following CSS classes won't be removed when parsed by the wysihtml5 HTML parser
39
+ * If all classes should pass "any" as classes value. Ex: "classes": "any"
39
40
  */
40
41
  "classes": {
41
42
  "wysiwyg-clear-both": 1,
@@ -88,7 +89,7 @@ var wysihtml5ParserRules = {
88
89
  },
89
90
  "styles": {
90
91
  "float": ["left", "right"],
91
- "textAlign": ["left", "right", "center"]
92
+ "text-align": ["left", "right", "center"]
92
93
  }
93
94
  },
94
95
 
@@ -150,11 +151,16 @@ var wysihtml5ParserRules = {
150
151
  * - add_class: converts and deletes the given HTML4 attribute (align, clear, ...) via the given method to a css class
151
152
  * The following methods are implemented in wysihtml5.dom.parse:
152
153
  * - align_text: converts align attribute values (right/left/center/justify) to their corresponding css class "wysiwyg-text-align-*")
153
- * <p align="center">foo</p> ... becomes ... <p> class="wysiwyg-text-align-center">foo</p>
154
+ * <p align="center">foo</p> ... becomes ... <p class="wysiwyg-text-align-center">foo</p>
154
155
  * - clear_br: converts clear attribute values left/right/all/both to their corresponding css class "wysiwyg-clear-*"
155
156
  * <br clear="all"> ... becomes ... <br class="wysiwyg-clear-both">
156
157
  * - align_img: converts align attribute values (right/left) on <img> to their corresponding css class "wysiwyg-float-*"
157
- *
158
+ *
159
+ * - add_style: converts and deletes the given HTML4 attribute (align) via the given method to a css style
160
+ * The following methods are implemented in wysihtml5.dom.parse:
161
+ * - align_text: converts align attribute values (right/left/center) to their corresponding css style)
162
+ * <p align="center">foo</p> ... becomes ... <p style="text-align:center">foo</p>
163
+ *
158
164
  * - remove: removes the element and its content
159
165
  *
160
166
  * - unwrap removes element but leaves content
@@ -17,8 +17,15 @@ if (Object.defineProperty && Object.getOwnPropertyDescriptor && Object.getOwnPro
17
17
  }
18
18
  );
19
19
  })();
20
+ }
21
+
22
+ // isArray polyfill for ie8
23
+ if(!Array.isArray) {
24
+ Array.isArray = function(arg) {
25
+ return Object.prototype.toString.call(arg) === '[object Array]';
26
+ };
20
27
  };/**
21
- * @license wysihtml5x v0.4.4
28
+ * @license wysihtml5x v0.4.5
22
29
  * https://github.com/Edicy/wysihtml5
23
30
  *
24
31
  * Author: Christopher Blum (https://github.com/tiff)
@@ -29,7 +36,7 @@ if (Object.defineProperty && Object.getOwnPropertyDescriptor && Object.getOwnPro
29
36
  *
30
37
  */
31
38
  var wysihtml5 = {
32
- version: "0.4.4",
39
+ version: "0.4.5",
33
40
 
34
41
  // namespaces
35
42
  commands: {},
@@ -4535,9 +4542,20 @@ wysihtml5.browser = (function() {
4535
4542
  * @example
4536
4543
  * wysihtml5.lang.array([1, 2]).contains(1);
4537
4544
  * // => true
4545
+ *
4546
+ * Can be used to match array with array. If intersection is found true is returned
4538
4547
  */
4539
4548
  contains: function(needle) {
4549
+ if (Array.isArray(needle)) {
4550
+ for (var i = needle.length; i--;) {
4551
+ if (wysihtml5.lang.array(arr).indexOf(needle[i]) !== -1) {
4552
+ return true;
4553
+ }
4554
+ }
4555
+ return false;
4556
+ } else {
4540
4557
  return wysihtml5.lang.array(arr).indexOf(needle) !== -1;
4558
+ }
4541
4559
  },
4542
4560
 
4543
4561
  /**
@@ -4618,7 +4636,28 @@ wysihtml5.browser = (function() {
4618
4636
  }
4619
4637
  return A;
4620
4638
  }
4639
+ },
4640
+
4641
+ /* ReturnS new array without duplicate entries
4642
+ *
4643
+ * @example
4644
+ * var uniq = wysihtml5.lang.array([1,2,3,2,1,4]).unique();
4645
+ * // => [1,2,3,4]
4646
+ */
4647
+ unique: function() {
4648
+ var vals = [],
4649
+ max = arr.length,
4650
+ idx = 0;
4651
+
4652
+ while (idx < max) {
4653
+ if (!wysihtml5.lang.array(vals).contains(arr[idx])) {
4654
+ vals.push(arr[idx]);
4655
+ }
4656
+ idx++;
4657
+ }
4658
+ return vals;
4621
4659
  }
4660
+
4622
4661
  };
4623
4662
  };
4624
4663
  ;wysihtml5.lang.Dispatcher = Base.extend(
@@ -4801,8 +4840,8 @@ wysihtml5.browser = (function() {
4801
4840
  MAX_DISPLAY_LENGTH = 100,
4802
4841
  BRACKETS = { ")": "(", "]": "[", "}": "{" };
4803
4842
 
4804
- function autoLink(element) {
4805
- if (_hasParentThatShouldBeIgnored(element)) {
4843
+ function autoLink(element, ignoreInClasses) {
4844
+ if (_hasParentThatShouldBeIgnored(element, ignoreInClasses)) {
4806
4845
  return element;
4807
4846
  }
4808
4847
 
@@ -4810,7 +4849,7 @@ wysihtml5.browser = (function() {
4810
4849
  element = element.ownerDocument.body;
4811
4850
  }
4812
4851
 
4813
- return _parseNode(element);
4852
+ return _parseNode(element, ignoreInClasses);
4814
4853
  }
4815
4854
 
4816
4855
  /**
@@ -4873,11 +4912,14 @@ wysihtml5.browser = (function() {
4873
4912
  parentNode.removeChild(textNode);
4874
4913
  }
4875
4914
 
4876
- function _hasParentThatShouldBeIgnored(node) {
4915
+ function _hasParentThatShouldBeIgnored(node, ignoreInClasses) {
4877
4916
  var nodeName;
4878
4917
  while (node.parentNode) {
4879
4918
  node = node.parentNode;
4880
4919
  nodeName = node.nodeName;
4920
+ if (node.className && wysihtml5.lang.array(node.className.split(' ')).contains(ignoreInClasses)) {
4921
+ return true;
4922
+ }
4881
4923
  if (IGNORE_URLS_IN.contains(nodeName)) {
4882
4924
  return true;
4883
4925
  } else if (nodeName === "body") {
@@ -4887,12 +4929,17 @@ wysihtml5.browser = (function() {
4887
4929
  return false;
4888
4930
  }
4889
4931
 
4890
- function _parseNode(element) {
4932
+ function _parseNode(element, ignoreInClasses) {
4891
4933
  if (IGNORE_URLS_IN.contains(element.nodeName)) {
4892
4934
  return;
4893
4935
  }
4894
4936
 
4937
+ if (element.className && wysihtml5.lang.array(element.className.split(' ')).contains(ignoreInClasses)) {
4938
+ return;
4939
+ }
4940
+
4895
4941
  if (element.nodeType === wysihtml5.TEXT_NODE && element.data.match(URL_REG_EXP)) {
4942
+ console.log(element);
4896
4943
  _wrapMatchesInNode(element);
4897
4944
  return;
4898
4945
  }
@@ -4902,7 +4949,7 @@ wysihtml5.browser = (function() {
4902
4949
  i = 0;
4903
4950
 
4904
4951
  for (; i<childNodesLength; i++) {
4905
- _parseNode(childNodes[i]);
4952
+ _parseNode(childNodes[i], ignoreInClasses);
4906
4953
  }
4907
4954
 
4908
4955
  return element;
@@ -5812,7 +5859,7 @@ wysihtml5.dom.parse = (function() {
5812
5859
  if (cleanUp &&
5813
5860
  newNode.nodeName.toLowerCase() === DEFAULT_NODE_NAME &&
5814
5861
  (!newNode.childNodes.length ||
5815
- ((/^\s*$/gi).test(newNode.innerHTML) && oldNode.className !== "_wysihtml5-temp-placeholder") ||
5862
+ ((/^\s*$/gi).test(newNode.innerHTML) && oldNode.className !== "_wysihtml5-temp-placeholder" && oldNode.className !== "rangySelectionBoundary") ||
5816
5863
  !newNode.attributes.length)
5817
5864
  ) {
5818
5865
  fragment = newNode.ownerDocument.createDocumentFragment();
@@ -5881,13 +5928,6 @@ wysihtml5.dom.parse = (function() {
5881
5928
  } else if (rule.unwrap) {
5882
5929
  return false;
5883
5930
  }
5884
-
5885
- // tests if type condition is met or node should be removed/unwrapped
5886
-
5887
- if (rule.one_of_type && !_testTypes(oldNode, currentRules, rule.one_of_type)) {
5888
- return (rule.remove_action && rule.remove_action == "unwrap") ? false : null;
5889
- }
5890
-
5891
5931
  rule = typeof(rule) === "string" ? { rename_tag: rule } : rule;
5892
5932
  } else if (oldNode.firstChild) {
5893
5933
  rule = { rename_tag: DEFAULT_NODE_NAME };
@@ -5895,9 +5935,15 @@ wysihtml5.dom.parse = (function() {
5895
5935
  // Remove empty unknown elements
5896
5936
  return null;
5897
5937
  }
5938
+
5898
5939
  newNode = oldNode.ownerDocument.createElement(rule.rename_tag || nodeName);
5899
5940
  _handleAttributes(oldNode, newNode, rule);
5900
5941
  _handleStyles(oldNode, newNode, rule);
5942
+ // tests if type condition is met or node should be removed/unwrapped
5943
+ if (rule.one_of_type && !_testTypes(newNode, currentRules, rule.one_of_type)) {
5944
+ return (rule.remove_action && rule.remove_action == "unwrap") ? false : null;
5945
+ }
5946
+
5901
5947
  oldNode = null;
5902
5948
 
5903
5949
  if (newNode.normalize) { newNode.normalize(); }
@@ -5908,7 +5954,7 @@ wysihtml5.dom.parse = (function() {
5908
5954
  var definition, type;
5909
5955
 
5910
5956
  // do not interfere with placeholder span or pasting caret position is not maintained
5911
- if (oldNode.nodeName === "SPAN" && oldNode.className === "_wysihtml5-temp-placeholder") {
5957
+ if (oldNode.nodeName === "SPAN" && (oldNode.className === "_wysihtml5-temp-placeholder" || oldNode.className === "rangySelectionBoundary")) {
5912
5958
  return true;
5913
5959
  }
5914
5960
 
@@ -5960,7 +6006,7 @@ wysihtml5.dom.parse = (function() {
5960
6006
  styleProp = nodeStyles[sp].split(':');
5961
6007
 
5962
6008
  if (styleProp[0].replace(/\s/g, '').toLowerCase() === s) {
5963
- if (definition.styles[s] === true || styleProp[1].replace(/\s/g, '').toLowerCase() === definition.styles[s]) {
6009
+ if (definition.styles[s] === true || definition.styles[s] === 1 || wysihtml5.lang.array(definition.styles[s]).contains(styleProp[1].replace(/\s/g, '').toLowerCase()) ) {
5964
6010
  return true;
5965
6011
  }
5966
6012
  }
@@ -6010,13 +6056,14 @@ wysihtml5.dom.parse = (function() {
6010
6056
  var attributes = {}, // fresh new set of attributes to set on newNode
6011
6057
  setClass = rule.set_class, // classes to set
6012
6058
  addClass = rule.add_class, // add classes based on existing attributes
6059
+ addStyle = rule.add_style, // add styles based on existing attributes
6013
6060
  setAttributes = rule.set_attributes, // attributes to set on the current node
6014
6061
  checkAttributes = rule.check_attributes, // check/convert values of attributes
6015
6062
  allowedClasses = currentRules.classes,
6016
6063
  i = 0,
6017
6064
  classes = [],
6065
+ styles = [],
6018
6066
  newClasses = [],
6019
- newUniqueClasses = [],
6020
6067
  oldClasses = [],
6021
6068
  classesLength,
6022
6069
  newClassesLength,
@@ -6063,33 +6110,48 @@ wysihtml5.dom.parse = (function() {
6063
6110
  }
6064
6111
  }
6065
6112
 
6066
- // make sure that wysihtml5 temp class doesn't get stripped out
6067
- allowedClasses["_wysihtml5-temp-placeholder"] = 1;
6113
+ if (addStyle) {
6114
+ for (attributeName in addStyle) {
6115
+ method = addStyleMethods[addStyle[attributeName]];
6116
+ if (!method) {
6117
+ continue;
6118
+ }
6068
6119
 
6069
- // add old classes last
6070
- oldClasses = oldNode.getAttribute("class");
6071
- if (oldClasses) {
6072
- classes = classes.concat(oldClasses.split(WHITE_SPACE_REG_EXP));
6073
- }
6074
- classesLength = classes.length;
6075
- for (; i<classesLength; i++) {
6076
- currentClass = classes[i];
6077
- if (allowedClasses[currentClass]) {
6078
- newClasses.push(currentClass);
6120
+ newStyle = method(_getAttribute(oldNode, attributeName));
6121
+ if (typeof(newStyle) === "string") {
6122
+ styles.push(newStyle);
6123
+ }
6079
6124
  }
6080
6125
  }
6081
6126
 
6082
- // remove duplicate entries and preserve class specificity
6083
- newClassesLength = newClasses.length;
6084
- while (newClassesLength--) {
6085
- currentClass = newClasses[newClassesLength];
6086
- if (!wysihtml5.lang.array(newUniqueClasses).contains(currentClass)) {
6087
- newUniqueClasses.unshift(currentClass);
6127
+
6128
+ if (typeof(allowedClasses) === "string" && allowedClasses === "any" && oldNode.getAttribute("class")) {
6129
+ attributes["class"] = oldNode.getAttribute("class");
6130
+ } else {
6131
+ // make sure that wysihtml5 temp class doesn't get stripped out
6132
+ allowedClasses["_wysihtml5-temp-placeholder"] = 1;
6133
+ allowedClasses["_rangySelectionBoundary"] = 1;
6134
+
6135
+ // add old classes last
6136
+ oldClasses = oldNode.getAttribute("class");
6137
+ if (oldClasses) {
6138
+ classes = classes.concat(oldClasses.split(WHITE_SPACE_REG_EXP));
6139
+ }
6140
+ classesLength = classes.length;
6141
+ for (; i<classesLength; i++) {
6142
+ currentClass = classes[i];
6143
+ if (allowedClasses[currentClass]) {
6144
+ newClasses.push(currentClass);
6145
+ }
6146
+ }
6147
+
6148
+ if (newClasses.length) {
6149
+ attributes["class"] = wysihtml5.lang.array(newClasses).unique().join(" ");
6088
6150
  }
6089
6151
  }
6090
6152
 
6091
- if (newUniqueClasses.length) {
6092
- attributes["class"] = newUniqueClasses.join(" ");
6153
+ if (styles.length) {
6154
+ attributes["style"] = wysihtml5.lang.array(styles).unique().join(" ");
6093
6155
  }
6094
6156
 
6095
6157
  // set attributes on newNode
@@ -6234,6 +6296,20 @@ wysihtml5.dom.parse = (function() {
6234
6296
  })()
6235
6297
  };
6236
6298
 
6299
+ // ------------ style converter (converts an html attribute to a style) ------------ \\
6300
+ var addStyleMethods = {
6301
+ align_text: (function() {
6302
+ var mapping = {
6303
+ left: "text-align: left;",
6304
+ right: "text-align: right;",
6305
+ center: "text-align: center;"
6306
+ };
6307
+ return function(attributeValue) {
6308
+ return mapping[String(attributeValue).toLowerCase()];
6309
+ };
6310
+ })(),
6311
+ };
6312
+
6237
6313
  // ------------ class converter (converts an html attribute to a class name) ------------ \\
6238
6314
  var addClassMethods = {
6239
6315
  align_img: (function() {
@@ -8233,6 +8309,40 @@ wysihtml5.quirks.ensureProperClearing = (function() {
8233
8309
  return top;
8234
8310
  }
8235
8311
 
8312
+ // Provides the depth of ``descendant`` relative to ``ancestor``
8313
+ function getDepth(ancestor, descendant) {
8314
+ var ret = 0;
8315
+ while (descendant !== ancestor) {
8316
+ ret++;
8317
+ descendant = descendant.parentNode;
8318
+ if (!descendant)
8319
+ throw new Error("not a descendant of ancestor!");
8320
+ }
8321
+ return ret;
8322
+ }
8323
+
8324
+ // Should fix the obtained ranges that cannot surrond contents normally to apply changes upon
8325
+ // Being considerate to firefox that sets range start start out of span and end inside on doubleclick initiated selection
8326
+ function expandRangeToSurround(range) {
8327
+ if (range.canSurroundContents()) return;
8328
+
8329
+ var common = range.commonAncestorContainer,
8330
+ start_depth = getDepth(common, range.startContainer),
8331
+ end_depth = getDepth(common, range.endContainer);
8332
+
8333
+ while(!range.canSurroundContents()) {
8334
+ // In the following branches, we cannot just decrement the depth variables because the setStartBefore/setEndAfter may move the start or end of the range more than one level relative to ``common``. So we need to recompute the depth.
8335
+ if (start_depth > end_depth) {
8336
+ range.setStartBefore(range.startContainer);
8337
+ start_depth = getDepth(common, range.startContainer);
8338
+ }
8339
+ else {
8340
+ range.setEndAfter(range.endContainer);
8341
+ end_depth = getDepth(common, range.endContainer);
8342
+ }
8343
+ }
8344
+ }
8345
+
8236
8346
  wysihtml5.Selection = Base.extend(
8237
8347
  /** @scope wysihtml5.Selection.prototype */ {
8238
8348
  constructor: function(editor, contain, unselectableClass) {
@@ -8253,6 +8363,7 @@ wysihtml5.quirks.ensureProperClearing = (function() {
8253
8363
  */
8254
8364
  getBookmark: function() {
8255
8365
  var range = this.getRange();
8366
+ if (range) expandRangeToSurround(range);
8256
8367
  return range && range.cloneRange();
8257
8368
  },
8258
8369
 
@@ -8982,10 +9093,9 @@ wysihtml5.quirks.ensureProperClearing = (function() {
8982
9093
  function addStyle(el, cssStyle, regExp) {
8983
9094
  if (el.getAttribute('style')) {
8984
9095
  removeStyle(el, regExp);
8985
- if (el.getAttribute('style') && !(/\s+/).test(el.getAttribute('style'))) {
9096
+ if (el.getAttribute('style') && !(/^\s*$/).test(el.getAttribute('style'))) {
8986
9097
  el.setAttribute('style', cssStyle + ";" + el.getAttribute('style'));
8987
9098
  } else {
8988
-
8989
9099
  el.setAttribute('style', cssStyle);
8990
9100
  }
8991
9101
  } else {
@@ -9014,7 +9124,7 @@ wysihtml5.quirks.ensureProperClearing = (function() {
9014
9124
  if (el.getAttribute('style')) {
9015
9125
  s = el.getAttribute('style').split(';');
9016
9126
  for (var i = s.length; i--;) {
9017
- if (!s[i].match(regExp) && !(/\s/).test(s[i])) {
9127
+ if (!s[i].match(regExp) && !(/^\s*$/).test(s[i])) {
9018
9128
  s2.push(s[i]);
9019
9129
  }
9020
9130
  }
@@ -9033,11 +9143,11 @@ wysihtml5.quirks.ensureProperClearing = (function() {
9033
9143
 
9034
9144
  if (elStyle) {
9035
9145
  elStyle = elStyle.replace(/\s/gi, '').toLowerCase();
9036
- regexes.push(new RegExp("(^|\\s|;)" + style.replace(/\s/gi, '').replace(/([\(\)])/gi, "\\$1").toLowerCase().replace(";", ";?"), "gi"));
9146
+ regexes.push(new RegExp("(^|\\s|;)" + style.replace(/\s/gi, '').replace(/([\(\)])/gi, "\\$1").toLowerCase().replace(";", ";?").replace(/rgb\\\((\d+),(\d+),(\d+)\\\)/gi, "\\s?rgb\\($1,\\s?$2,\\s?$3\\)"), "gi"));
9037
9147
 
9038
9148
  for (var i = sSplit.length; i-- > 0;) {
9039
9149
  if (!(/^\s*$/).test(sSplit[i])) {
9040
- regexes.push(new RegExp("(^|\\s|;)" + sSplit[i].replace(/\s/gi, '').replace(/([\(\)])/gi, "\\$1").toLowerCase().replace(";", ";?"), "gi"));
9150
+ regexes.push(new RegExp("(^|\\s|;)" + sSplit[i].replace(/\s/gi, '').replace(/([\(\)])/gi, "\\$1").toLowerCase().replace(";", ";?").replace(/rgb\\\((\d+),(\d+),(\d+)\\\)/gi, "\\s?rgb\\($1,\\s?$2,\\s?$3\\)"), "gi"));
9041
9151
  }
9042
9152
  }
9043
9153
  for (var j = 0, jmax = regexes.length; j < jmax; j++) {
@@ -9048,15 +9158,11 @@ wysihtml5.quirks.ensureProperClearing = (function() {
9048
9158
  }
9049
9159
 
9050
9160
  return false;
9051
- };
9161
+ }
9052
9162
 
9053
9163
  function removeOrChangeStyle(el, style, regExp) {
9054
9164
 
9055
9165
  var exactRegex = getMatchingStyleRegexp(el, style);
9056
-
9057
- /*new RegExp("(^|\\s|;)" + style.replace(/\s/gi, '').replace(/([\(\)])/gi, "\\$1").toLowerCase().replace(";", ";?"), "gi"),
9058
- elStyle = el.getAttribute('style');*/
9059
-
9060
9166
  if (exactRegex) {
9061
9167
  // adding same style value on property again removes style
9062
9168
  removeStyle(el, exactRegex);
@@ -9066,7 +9172,7 @@ wysihtml5.quirks.ensureProperClearing = (function() {
9066
9172
  addStyle(el, style, regExp);
9067
9173
  return "change";
9068
9174
  }
9069
- };
9175
+ }
9070
9176
 
9071
9177
  function hasSameClasses(el1, el2) {
9072
9178
  return el1.className.replace(REG_EXP_WHITE_SPACE, " ") == el2.className.replace(REG_EXP_WHITE_SPACE, " ");
@@ -9117,7 +9223,7 @@ wysihtml5.quirks.ensureProperClearing = (function() {
9117
9223
  return offset > 0 && offset < node.childNodes.length;
9118
9224
  }
9119
9225
 
9120
- function splitNodeAt(node, descendantNode, descendantOffset) {
9226
+ function splitNodeAt(node, descendantNode, descendantOffset, container) {
9121
9227
  var newNode;
9122
9228
  if (rangy.dom.isCharacterDataNode(descendantNode)) {
9123
9229
  if (descendantOffset == 0) {
@@ -9131,17 +9237,21 @@ wysihtml5.quirks.ensureProperClearing = (function() {
9131
9237
  }
9132
9238
  }
9133
9239
  if (!newNode) {
9134
- newNode = descendantNode.cloneNode(false);
9135
- if (newNode.id) {
9136
- newNode.removeAttribute("id");
9137
- }
9138
- var child;
9139
- while ((child = descendantNode.childNodes[descendantOffset])) {
9140
- newNode.appendChild(child);
9240
+ if (!container || descendantNode !== container) {
9241
+
9242
+ newNode = descendantNode.cloneNode(false);
9243
+ if (newNode.id) {
9244
+ newNode.removeAttribute("id");
9245
+ }
9246
+ var child;
9247
+ while ((child = descendantNode.childNodes[descendantOffset])) {
9248
+ newNode.appendChild(child);
9249
+ }
9250
+ rangy.dom.insertAfter(newNode, descendantNode);
9251
+
9141
9252
  }
9142
- rangy.dom.insertAfter(newNode, descendantNode);
9143
9253
  }
9144
- return (descendantNode == node) ? newNode : splitNodeAt(node, newNode.parentNode, rangy.dom.getNodeIndex(newNode));
9254
+ return (descendantNode == node) ? newNode : splitNodeAt(node, newNode.parentNode, rangy.dom.getNodeIndex(newNode), container);
9145
9255
  }
9146
9256
 
9147
9257
  function Merge(firstNode) {
@@ -9185,7 +9295,7 @@ wysihtml5.quirks.ensureProperClearing = (function() {
9185
9295
  }
9186
9296
  };
9187
9297
 
9188
- function HTMLApplier(tagNames, cssClass, similarClassRegExp, normalize, cssStyle, similarStyleRegExp) {
9298
+ function HTMLApplier(tagNames, cssClass, similarClassRegExp, normalize, cssStyle, similarStyleRegExp, container) {
9189
9299
  this.tagNames = tagNames || [defaultTagName];
9190
9300
  this.cssClass = cssClass || ((cssClass === false) ? false : "");
9191
9301
  this.similarClassRegExp = similarClassRegExp;
@@ -9193,6 +9303,7 @@ wysihtml5.quirks.ensureProperClearing = (function() {
9193
9303
  this.similarStyleRegExp = similarStyleRegExp;
9194
9304
  this.normalize = normalize;
9195
9305
  this.applyToAnyTagName = false;
9306
+ this.container = container;
9196
9307
  }
9197
9308
 
9198
9309
  HTMLApplier.prototype = {
@@ -9325,6 +9436,9 @@ wysihtml5.quirks.ensureProperClearing = (function() {
9325
9436
  if (this.cssClass) {
9326
9437
  addClass(parent, this.cssClass, this.similarClassRegExp);
9327
9438
  }
9439
+ if (this.cssStyle) {
9440
+ addStyle(parent, this.cssStyle, this.similarStyleRegExp);
9441
+ }
9328
9442
  } else {
9329
9443
  var el = this.createContainer(rangy.dom.getDocument(textNode));
9330
9444
  textNode.parentNode.insertBefore(el, textNode);
@@ -9333,7 +9447,12 @@ wysihtml5.quirks.ensureProperClearing = (function() {
9333
9447
  },
9334
9448
 
9335
9449
  isRemovable: function(el) {
9336
- return rangy.dom.arrayContains(this.tagNames, el.tagName.toLowerCase()) && wysihtml5.lang.string(el.className).trim() == this.cssClass;
9450
+ return rangy.dom.arrayContains(this.tagNames, el.tagName.toLowerCase()) &&
9451
+ wysihtml5.lang.string(el.className).trim() === "" &&
9452
+ (
9453
+ !el.getAttribute('style') ||
9454
+ wysihtml5.lang.string(el.getAttribute('style')).trim() === ""
9455
+ );
9337
9456
  },
9338
9457
 
9339
9458
  undoToTextNode: function(textNode, range, ancestorWithClass, ancestorWithStyle) {
@@ -9346,11 +9465,11 @@ wysihtml5.quirks.ensureProperClearing = (function() {
9346
9465
  ancestorRange.selectNode(ancestor);
9347
9466
 
9348
9467
  if (ancestorRange.isPointInRange(range.endContainer, range.endOffset) && isSplitPoint(range.endContainer, range.endOffset)) {
9349
- splitNodeAt(ancestor, range.endContainer, range.endOffset);
9468
+ splitNodeAt(ancestor, range.endContainer, range.endOffset, this.container);
9350
9469
  range.setEndAfter(ancestor);
9351
9470
  }
9352
9471
  if (ancestorRange.isPointInRange(range.startContainer, range.startOffset) && isSplitPoint(range.startContainer, range.startOffset)) {
9353
- ancestor = splitNodeAt(ancestor, range.startContainer, range.startOffset);
9472
+ ancestor = splitNodeAt(ancestor, range.startContainer, range.startOffset, this.container);
9354
9473
  }
9355
9474
  }
9356
9475
 
@@ -9361,7 +9480,6 @@ wysihtml5.quirks.ensureProperClearing = (function() {
9361
9480
  if (styleMode && this.similarStyleRegExp) {
9362
9481
  styleChanged = (removeOrChangeStyle(ancestor, this.cssStyle, this.similarStyleRegExp) === "change");
9363
9482
  }
9364
-
9365
9483
  if (this.isRemovable(ancestor) && !styleChanged) {
9366
9484
  replaceWithOwnChildren(ancestor);
9367
9485
  }
@@ -9391,6 +9509,9 @@ wysihtml5.quirks.ensureProperClearing = (function() {
9391
9509
  if (!this.getAncestorWithClass(textNode)) {
9392
9510
  this.applyToTextNode(textNode);
9393
9511
  }
9512
+ if (!this.getAncestorWithStyle(textNode)) {
9513
+ this.applyToTextNode(textNode);
9514
+ }
9394
9515
  }
9395
9516
 
9396
9517
  range[ri].setStart(textNodes[0], 0);
@@ -10339,13 +10460,13 @@ wysihtml5.commands.formatCode = {
10339
10460
  return alias ? [tagName.toLowerCase(), alias.toLowerCase()] : [tagName.toLowerCase()];
10340
10461
  }
10341
10462
 
10342
- function _getApplier(tagName, className, classRegExp, cssStyle, styleRegExp) {
10463
+ function _getApplier(tagName, className, classRegExp, cssStyle, styleRegExp, container) {
10343
10464
  var identifier = tagName + ":" + className;
10344
10465
  if (cssStyle) {
10345
10466
  identifier += ":" + cssStyle;
10346
10467
  }
10347
10468
  if (!htmlApplier[identifier]) {
10348
- htmlApplier[identifier] = new wysihtml5.selection.HTMLApplier(_getTagNames(tagName), className, classRegExp, true, cssStyle, styleRegExp);
10469
+ htmlApplier[identifier] = new wysihtml5.selection.HTMLApplier(_getTagNames(tagName), className, classRegExp, true, cssStyle, styleRegExp, container);
10349
10470
  }
10350
10471
  return htmlApplier[identifier];
10351
10472
  }
@@ -10359,7 +10480,8 @@ wysihtml5.commands.formatCode = {
10359
10480
  return false;
10360
10481
  }
10361
10482
  composer.selection.getSelection().removeAllRanges();
10362
- _getApplier(tagName, className, classRegExp, cssStyle, styleRegExp).toggleRange(ownRanges);
10483
+
10484
+ _getApplier(tagName, className, classRegExp, cssStyle, styleRegExp, composer.element).toggleRange(ownRanges);
10363
10485
 
10364
10486
  if (!dontRestoreSelect) {
10365
10487
  range.setStart(ownRanges[0].startContainer, ownRanges[0].startOffset);
@@ -10428,7 +10550,7 @@ wysihtml5.commands.formatCode = {
10428
10550
  return false;
10429
10551
  }
10430
10552
 
10431
- return _getApplier(tagName, className, classRegExp, cssStyle, styleRegExp).isAppliedToRange(ownRanges);
10553
+ return _getApplier(tagName, className, classRegExp, cssStyle, styleRegExp, composer.element).isAppliedToRange(ownRanges);
10432
10554
  }
10433
10555
  };
10434
10556
  })(wysihtml5);
@@ -11488,13 +11610,22 @@ wysihtml5.views.View = Base.extend(
11488
11610
  this.parent.on("newword:composer", function() {
11489
11611
  if (dom.getTextContent(that.element).match(dom.autoLink.URL_REG_EXP)) {
11490
11612
  that.selection.executeAndRestore(function(startContainer, endContainer) {
11491
- dom.autoLink(endContainer.parentNode);
11613
+ var uneditables = that.element.querySelectorAll("." + that.config.uneditableContainerClassname),
11614
+ isInUneditable = false;
11615
+
11616
+ for (var i = uneditables.length; i--;) {
11617
+ if (wysihtml5.dom.contains(uneditables[i], endContainer)) {
11618
+ isInUneditable = true;
11619
+ }
11620
+ }
11621
+
11622
+ if (!isInUneditable) dom.autoLink(endContainer.parentNode, [that.config.uneditableContainerClassname]);
11492
11623
  });
11493
11624
  }
11494
11625
  });
11495
11626
 
11496
11627
  dom.observe(this.element, "blur", function() {
11497
- dom.autoLink(that.element);
11628
+ dom.autoLink(that.element, [that.config.uneditableContainerClassname]);
11498
11629
  });
11499
11630
  }
11500
11631
 
@@ -11928,7 +12059,7 @@ wysihtml5.views.View = Base.extend(
11928
12059
  }
11929
12060
  };
11930
12061
 
11931
- var handleDeleteKeyPress = function(selection, element) {
12062
+ var handleDeleteKeyPress = function(event, selection, element) {
11932
12063
  if (selection.isCollapsed()) {
11933
12064
  if (selection.caretIsInTheBeginnig()) {
11934
12065
  event.preventDefault();
@@ -12129,7 +12260,7 @@ wysihtml5.views.View = Base.extend(
12129
12260
  }
12130
12261
  if (keyCode === 8) {
12131
12262
  // delete key
12132
- handleDeleteKeyPress(that.selection, element);
12263
+ handleDeleteKeyPress(event, that.selection, element);
12133
12264
  } else if (keyCode === 9) {
12134
12265
  event.preventDefault();
12135
12266
  handleTabKeyDown(that, element);