changeset 35:cd02cd04bc9d

fix [img]
author Franklin Schmidt <fschmidt@gmail.com>
date Mon, 15 Aug 2022 22:57:06 -0600
parents 20d1f23225fe
children 21090996a131
files src/changes.txt src/formats/bbcode.js
diffstat 2 files changed, 52 insertions(+), 122 deletions(-) [+]
line wrap: on
line diff
diff -r 20d1f23225fe -r cd02cd04bc9d src/changes.txt
--- a/src/changes.txt	Mon Aug 15 21:35:44 2022 -0600
+++ b/src/changes.txt	Mon Aug 15 22:57:06 2022 -0600
@@ -1,6 +1,8 @@
 changes, most recent at top
 
 
+Removed complex parameterized tags: [tag value1=”xxx” value2=”yyy”]something[/tag]  This is over-engineering and shouldn't be in BBCode.
+
 Removed sceditor.command with its get(), set(), and remove().  It is better to work with sceditor.commands directly.  I also added an options.onCreate callback which lets one work with the final editor.commands .
 
 Remove DOMPurify.  This was a huge amount of incomprehensible code that adds little value.  XSS should basically be handled on the server side, and if one is using bbcode then it isn't an issue anyway.
diff -r 20d1f23225fe -r cd02cd04bc9d src/formats/bbcode.js
--- a/src/formats/bbcode.js	Mon Aug 15 21:35:44 2022 -0600
+++ b/src/formats/bbcode.js	Mon Aug 15 22:57:06 2022 -0600
@@ -160,19 +160,15 @@
 					caller,
 					selected,
 					function (url, width, height) {
-						var attrs  = '';
-
-						if (width) {
-							attrs += ' width=' + width;
+						if( width || height ) {
+							editor.insertText(
+								'[img=' + width + 'x' + height + ']' + url + '[/img]'
+							);
+						} else {
+							editor.insertText(
+								'[img]' + url + '[/img]'
+							);
 						}
-
-						if (height) {
-							attrs += ' height=' + height;
-						}
-
-						editor.insertText(
-							'[img' + attrs + ']' + url + '[/img]'
-						);
 					}
 				);
 			}
@@ -342,7 +338,7 @@
 				return '[font=' + _stripQuotes(font) + ']' +
 					content + '[/font]';
 			},
-			html: '<font face="{defaultattr}">{0}</font>'
+			html: '<font face="{attrib}">{0}</font>'
 		},
 		// END_COMMAND
 
@@ -393,7 +389,7 @@
 
 				return '[size=' + size + ']' + content + '[/size]';
 			},
-			html: '<font size="{defaultattr}">{!0}</font>'
+			html: '<font size="{attrib}">{!0}</font>'
 		},
 		// END_COMMAND
 
@@ -418,9 +414,9 @@
 				return '[color=' + _normaliseColour(color) + ']' +
 					content + '[/color]';
 			},
-			html: function (token, attrs, content) {
+			html: function (token, attrib, content) {
 				return '<font color="' +
-					escapeEntities(_normaliseColour(attrs.defaultattr), true) +
+					escapeEntities(_normaliseColour(attrib), true) +
 					'">' + content + '</font>';
 			}
 		},
@@ -521,7 +517,7 @@
 			format: function (element, content) {
 				return attr(element, EMOTICON_DATA_ATTR) + content;
 			},
-			html: function (token, attrs, content, editor) {
+			html: function (token, attrib, content, editor) {
 				return editor.allEmoticons[content] || token.val + content + token.closing.val;
 			}
 		},
@@ -569,33 +565,29 @@
 				if ((element.complete && (width || height)) ||
 					(width && height)) {
 
-					attribs = '=' + dom.width(element) + 'x' +
-						dom.height(element);
+					attribs = '=' + width + 'x' +
+						height;
 				}
 
 				return '[img' + attribs + ']' + attr(element, 'src') + '[/img]';
 			},
-			html: function (token, attrs, content) {
+			html: function (token, attrib, content) {
 				var	undef, width, height, match,
 					attribs = '';
 
-				// handle [img width=340 height=240]url[/img]
-				width  = attrs.width;
-				height = attrs.height;
-
 				// handle [img=340x240]url[/img]
-				if (attrs.defaultattr) {
-					match = attrs.defaultattr.split(/x/i);
+				if (attrib) {
+					match = attrib.split(/x/i);
 
 					width  = match[0];
-					height = (match.length === 2 ? match[1] : match[0]);
+					height = match[1];
 				}
 
-				if (width !== undef) {
+				if (width) {
 					attribs += ' width="' + escapeEntities(width, true) + '"';
 				}
 
-				if (height !== undef) {
+				if (height) {
 					attribs += ' height="' + escapeEntities(height, true) + '"';
 				}
 
@@ -630,11 +622,11 @@
 					return '[url=' + url + ']' + content + '[/url]';
 				}
 			},
-			html: function (token, attrs, content) {
-				attrs.defaultattr =
-					escapeEntities(attrs.defaultattr, true) || content;
+			html: function (token, attrib, content) {
+				attrib =
+					escapeEntities(attrib, true) || content;
 
-				return '<a href="' + escapeUriScheme(attrs.defaultattr) + '">' +
+				return '<a href="' + escapeUriScheme(attrib) + '">' +
 					content + '</a>';
 			}
 		},
@@ -643,9 +635,9 @@
 		// START_COMMAND: E-mail
 		email: {
 			quoteType: QuoteType.never,
-			html: function (token, attrs, content) {
+			html: function (token, attrib, content) {
 				return '<a href="mailto:' +
-					(escapeEntities(attrs.defaultattr, true) || content) +
+					(escapeEntities(attrib, true) || content) +
 					'">' + content + '</a>';
 			}
 		},
@@ -690,9 +682,9 @@
 
 				return '[quote' + author + ']' + content + '[/quote]';
 			},
-			html: function (token, attrs, content) {
-				if (attrs.defaultattr) {
-					content = '<cite>' + escapeEntities(attrs.defaultattr) +
+			html: function (token, attrib, content) {
+				if (attrib) {
+					content = '<cite>' + escapeEntities(attrib) +
 						'</cite>' + content;
 				}
 
@@ -961,7 +953,7 @@
 	 * @property {string} type
 	 * @property {string} name
 	 * @property {string} val
-	 * @property {Object.<string, string>} attrs
+	 * @property {string} attrib
 	 * @property {array} children
 	 * @property {TokenizeToken} closing
 	 */
@@ -973,7 +965,7 @@
 	 *                       should be one of tokenType
 	 * @param  {string} name The name of this token
 	 * @param  {string} val The originally matched string
-	 * @param  {array} attrs Any attributes. Only set on
+	 * @param  {string} attrib Any attributes. Only set on
 	 *                       TOKEN_TYPE_OPEN tokens
 	 * @param  {array} children Any children of this token
 	 * @param  {TokenizeToken} closing This tokens closing tag.
@@ -983,13 +975,13 @@
 	 * @memberOf BBCodeParser.prototype
 	 */
 	// eslint-disable-next-line max-params
-	function TokenizeToken(type, name, val, attrs, children, closing) {
+	function TokenizeToken(type, name, val, attrib, children, closing) {
 		var base      = this;
 
 		base.type     = type;
 		base.name     = name;
 		base.val      = val;
-		base.attrs    = attrs || {};
+		base.attrib   = attrib;
 		base.children = children || [];
 		base.closing  = closing || null;
 	};
@@ -1008,7 +1000,7 @@
 				base.type,
 				base.name,
 				base.val,
-				extend({}, base.attrs),
+				base.attrib,
 				[],
 				base.closing ? base.closing.clone() : null
 			);
@@ -1133,8 +1125,8 @@
 		 * @private
 		 */
 		function tokenizeTag(type, val) {
-			var matches, attrs, name,
-				openRegex  = /\[([^\]\s=]+)(?:([^\]]+))?\]/,
+			var matches, attrib, name,
+				openRegex  = /\[([^\]\s=]+)(?:=([^\]]+))?\]/,
 				closeRegex = /\[\/([^\[\]]+)\]/;
 
 			// Extract the name and attributes from opening tags and
@@ -1143,7 +1135,7 @@
 				name = lower(matches[1]);
 
 				if (matches[2] && (matches[2] = matches[2].trim())) {
-					attrs = tokenizeAttrs(matches[2]);
+					attrib = _stripQuotes(matches[2]);
 				}
 			}
 
@@ -1165,60 +1157,7 @@
 				name = '#';
 			}
 
-			return new TokenizeToken(type, name, val, attrs);
-		}
-
-		/**
-		 * Extracts the individual attributes from a string containing
-		 * all the attributes.
-		 *
-		 * @param {string} attrs
-		 * @return {Object} Assoc array of attributes
-		 * @private
-		 */
-		function tokenizeAttrs(attrs) {
-			var	matches,
-				/*
-				([^\s=]+)				Anything that's not a space or equals
-				=						Equals sign =
-				(?:
-					(?:
-						(["'])					The opening quote
-						(
-							(?:\\\2|[^\2])*?	Anything that isn't the
-												unescaped opening quote
-						)
-						\2						The opening quote again which
-												will close the string
-					)
-						|				If not a quoted string then match
-					(
-						(?:.(?!\s\S+=))*.?		Anything that isn't part of
-												[space][non-space][=] which
-												would be a new attribute
-					)
-				)
-				*/
-				attrRegex = /([^\s=]+)=(?:(?:(["'])((?:\\\2|[^\2])*?)\2)|((?:.(?!\s\S+=))*.))/g,
-				ret       = {};
-
-			// if only one attribute then remove the = from the start and
-			// strip any quotes
-			if (attrs.charAt(0) === '=' && attrs.indexOf('=', 1) < 0) {
-				ret.defaultattr = _stripQuotes(attrs.substr(1));
-			} else {
-				if (attrs.charAt(0) === '=') {
-					attrs = 'defaultattr' + attrs;
-				}
-
-				// No need to strip quotes here, the regex will do that.
-				while ((matches = attrRegex.exec(attrs))) {
-					ret[lower(matches[1])] =
-						_stripQuotes(matches[3]) || matches[4];
-				}
-			}
-
-			return ret;
+			return new TokenizeToken(type, name, val, attrib);
 		}
 
 		/**
@@ -1841,15 +1780,15 @@
 						}
 
 						if (!isFunction(bbcode.html)) {
-							token.attrs['0'] = content;
+							token['0'] = content;
 							html = formatBBCodeString(
 								bbcode.html,
-								token.attrs
+								token
 							);
 						} else {
 							html = bbcode.html(
 								token,
-								token.attrs,
+								token.attrib,
 								content,
 								editor
 							);
@@ -1983,23 +1922,12 @@
 
 					// Convert the tag and it's attributes to BBCode
 					ret += '[' + token.name;
-					if (token.attrs) {
-						if (token.attrs.defaultattr) {
-							ret += '=' + quote(
-								token.attrs.defaultattr,
-								quoteType,
-								'defaultattr'
-							);
-
-							delete token.attrs.defaultattr;
-						}
-
-						for (attr in token.attrs) {
-							if (token.attrs.hasOwnProperty(attr)) {
-								ret += ' ' + attr + '=' +
-									quote(token.attrs[attr], quoteType, attr);
-							}
-						}
+					if (token.attrib) {
+						ret += '=' + quote(
+							token.attrib,
+							quoteType
+						);
+						delete token.attrib;
 					}
 					ret += ']';
 
@@ -2047,11 +1975,11 @@
 		 * @return {string}
 		 * @private
 		 */
-		function quote(str, quoteType, name) {
+		function quote(str, quoteType) {
 			var	needsQuotes = /\s|=/.test(str);
 
 			if (isFunction(quoteType)) {
-				return quoteType(str, name);
+				return quoteType(str);
 			}
 
 			if (quoteType === QuoteType.never ||