HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavascriptMinor

Remove specific CSS rules from WYSIWYG text

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
csswysiwygtextremovespecificrulesfrom

Problem

I have created a working function for cleaning some specific styles within the text from a WYSIWYG editor.

var rulesText = textArea.value;

  var selector = "a:link, span.MsoHyperlink";
  var pattern = new RegExp(selector.replace(/\./g, "\\.") + "\\s*{[^}]*?}", "gim");

  rulesText = rulesText.replace(pattern,"");

  var nextSelector = "a:visited, span.MsoHyperlinkFollowed";
  var nextPattern = new RegExp(nextSelector.replace(/\./g, "\\.") + "\\s*{[^}]*?}", "gim");

  rulesText = rulesText.replace(nextPattern,"");

  textArea.value = rulesText;

  console.log("FIRED!");


Here are the styles being cleaned:

a:link, span.MsoHyperlink
{mso-style-unhide:no;
color:blue;
text-decoration:underline;
text-underline:single;}

a:visited, span.MsoHyperlinkFollowed
{mso-style-noshow:yes;
mso-style-priority:99;
color:purple;
mso-themecolor:followedhyperlink;
text-decoration:underline;
text-underline:single;}


This solution seems a bit wonky to me... And I feel like there is definitely more room for elegance. How can improve on this, possibly combine the two RegExp instances, and make sure that multiple instances of this are being removed?

Solution

As selectors are static(known beforehand) and are not going to change, there is no need to use RegExp constructor syntax to create regex. By saying that,

var selector = "a:link, span.MsoHyperlink";
var pattern = new RegExp(selector.replace(/\./g, "\\.") + "\\s*{[^}]*?}", "gim");


seems unnecessary. With these two statements, you're creating two extra variables, an additional replace and then creating a regular expression from string.
Same is for other selector too.

What if there are 10 more CSS rules to be removed? Will you create 10 more strings, 10 more regex and 10 replacements? And what if there are 100 such rules?

The point is, this is not maintainable solution and the code written is way too much for string removals.


possibly combine the two RegExp instances, and make sure that multiple instances of this are being removed?

The two regex can be combined using OR condition in regex with g flag to replace all occurrences.

First, using regex literal syntax to create regex

var linksRegex = /a:link, span\.MsoHyperlink\s*{[^}]*?}/gim; // First selector regex


and

var visitedLinksRegex = /a:visited, span\.MsoHyperlinkFollowed\s*{[^}]*?}/gim; // Second selector regex


Using OR condition(|), the two regex can be combined as

/a:link, span\.MsoHyperlink\s*{[^}]*?}|a:visited, span\.MsoHyperlinkFollowed\s*{[^}]*?}/


This works. But, there is duplication of the part \s{[^}]?} which can be removed using groups

/(a:link, span\.MsoHyperlink|a:visited, span\.MsoHyperlinkFollowed)\s*{[^}]*?}/


I'll suggest to use \s* instead of space between two selectors which will match any number of any space characters(space, tab, vertical tabs, etc.)

/(a:link,\s*span\.MsoHyperlink|a:visited,\s*span\.MsoHyperlinkFollowed)\s*{[^}]*?}/


To match the CSS rule properties of a selector use [\s\S]?} where [\s\S] will match any character(space characters and non-space characters) thus no need of m flag anymore, while ? following it will make the regex lazy. See http://www.regular-expressions.info/repeat.html. Lazy repetition will match fewer characters to satisfy the following condition in regex. So, [\s\S]*?} will match anything until } character.

Note: . does not match new-line character even with m-multiline flag Demo. Work-around is to use [\s\S] which matches any character. See Javascript regex multiline flag doesn't work

With these changes the regex will become

/(a:link,\s*span\.MsoHyperlink|a:visited,\s*span\.MsoHyperlinkFollowed)[\s\S]*?}/gi


Here's demo.

Final Code:

var regex = /(a:link,\s*span\.MsoHyperlink|a:visited,\s*span\.MsoHyperlinkFollowed)[\s\S]*?}/gi;

textArea.value = textArea.value.replace(regex, '');


Here's working demo in action to try it out.



function replaceRules() {
var regex = /(a:link,\sspan\.MsoHyperlink|a:visited,\sspan\.MsoHyperlinkFollowed)[\s\S]*?}/gi;

var textArea = document.querySelector('textarea');
textArea.value = textArea.value.replace(regex, '');
}

input {
margin-bottom: 5px;
color: green;
padding: 5px;
}

textarea {
width: 100%;
}



body {
background: red;
}

a:link, span.MsoHyperlink {
mso-style-unhide: no;
color: blue;
text-decoration: underline;
text-underline: single;
}

a:visited, span.MsoHyperlinkFollowed
{mso-style-noshow:yes;
mso-style-priority:99;
color:purple;
mso-themecolor:followedhyperlink;
text-decoration:underline;
text-underline:single;}

a {
color: gray;
}

Code Snippets

var selector = "a:link, span.MsoHyperlink";
var pattern = new RegExp(selector.replace(/\./g, "\\.") + "\\s*{[^}]*?}", "gim");
var linksRegex = /a:link, span\.MsoHyperlink\s*{[^}]*?}/gim; // First selector regex
var visitedLinksRegex = /a:visited, span\.MsoHyperlinkFollowed\s*{[^}]*?}/gim; // Second selector regex
/a:link, span\.MsoHyperlink\s*{[^}]*?}|a:visited, span\.MsoHyperlinkFollowed\s*{[^}]*?}/
/(a:link, span\.MsoHyperlink|a:visited, span\.MsoHyperlinkFollowed)\s*{[^}]*?}/

Context

StackExchange Code Review Q#157824, answer score: 3

Revisions (0)

No revisions yet.