Jump to content

Regex with style?!


dazhall

Recommended Posts

Hi Guys,

 

I'm trying to do a function that will look at my styles and then go through the rest of the html document and add those styles inline to the particular tag. Eg:

 

The styles:

 

<style type="text/css">
h1 { font-family: Verdana, Arial, Helvetica, sans-serif; }
p.myclass { color: #CC0000; }
p.myclass a { text-decoration: none; color: #FFCC00; }
</style>

 

The html:

 

<h1>Lorem ipsum dolor sit amet</h1>
<p class="myclass">consectetuer adipiscing <a href="#">elit</a>. Sed vel velit eu lorem dignissim iaculis.</p>

 

The result:

 

<h1 style="font-family: Verdana, Arial, Helvetica, sans-serif;">Lorem ipsum dolor sit amet</h1>
<p style="color: #CC0000;">consectetuer adipiscing <a style="text-decoration: none; color: #FFCC00;" href="#">elit</a>. Sed vel velit eu lorem dignissim iaculis.</p>

 

Impossible? I think not, well not entirely! I'm just drowning in regex expressions! If anyone has seen anything like it before then shout up, or if anyone can offer any help I'd be extremely appreciative!

 

Oh, why am I wanting to do this I hear you cry?! I'm doing a script that send out html emails, and I need to attach the style dynamically based up the template.

 

Thanks!

Link to comment
Share on other sites

Because Google Mail (and other email clients) don't like styles sheets! and unfortunately the only way to get around it is to add inline styles to every tag. Now beacuse the content is dynamic there could be <p> or <ul> all over the place and the user wont be able to add inline styles to each tag, nor should they have to. So, the code will look thorugh the template we create and add those inline styles automatically.

Link to comment
Share on other sites

I've decided to limit myself to one style, so no classes or cascading styles - it's difficult enough as it is. I'm thinking it should be relatively easy just to regex a p { or li {. I could limit it to to a set number of styles, as really i'm only going to be using p, ul, li , h1/2/3/4/5, a etc.

Link to comment
Share on other sites

Here's a start:

 

<pre>
<?php
$css = <<<CSS
<style type="text/css">
h1 { font-family: Verdana, Arial, Helvetica, sans-serif; }
h2 { text-decoration: none; color: #FFCC00; }
p { color: #CC0000; }
</style>
CSS;

function parse_css($css) {
	preg_match_all('/^\s*(\w+)\s*\{\s*([^}]+?)\s*\}/m', $css, $matches, PREG_SET_ORDER);
	foreach ($matches as $idx => &$array) {
		// Remove the whole match.
		array_shift($matches[$idx]);
	}
	return $matches;
}

$pieces = parse_css($css);
print_r($pieces);

?>
</pre>

Link to comment
Share on other sites

Because Google Mail (and other email clients) don't like styles sheets! and unfortunately the only way to get around it is to add inline styles to every tag. Now beacuse the content is dynamic there could be <p> or <ul> all over the place and the user wont be able to add inline styles to each tag, nor should they have to. So, the code will look thorugh the template we create and add those inline styles automatically.

 

Hmm your going to have this problem even with inline styles, its just the way it goes with Yahoo, MSN etc etc. I produce a lot of email shots for our clients and the best thing you can do is to create an embedded stylesheet and XHTML your email document.

Link to comment
Share on other sites

Thanks for that!

 

Right, so I've modified it a wee bit to get it working more like I'd like it to:

 

<?php

$css = '<style type="text/css">
	h1 { font-family: Arial, Helvetica, sans-serif; }
	h2 { text-decoration: none; color: #666666; }
	p { color: #333333; }
	p.error { color: #CC0000; }
	a { color: #green; }
	</style>';

$html = '<h1>Regex CSS Replacement Test</h1><h2>It\'s Regex with style!</h2><p>As you can clearly see it\'s possible to use regular expresions to search through your style sheet and hard code the syles into the html tags.</p><p class="error">It\'s red good! It all <a href="http://www.moodle.co.uk">links</a> into my plan!</p>';

function parse_css($css,$html) {
preg_match_all('/^\s*(\w+)\.*(\w*)\s*\{\s*([^}]+?)\s*\}/m', $css, $matches, PREG_SET_ORDER);
foreach ($matches as $idx => $array) {
	// Remove the whole match.
	array_shift($matches[$idx]);
}

foreach ($matches as $match) {

	if ($match[1]=="") {
		$open = '<'.$match[0].'>';
		$taggedOpen = '<'.$match[0].' style="'.$match[2].'">';
	} else {
		$open = '<'.$match[0].' class="'.$match[1].'">';
		$taggedOpen = '<'.$match[0].' style="'.$match[2].'">';
	}

	$html = str_replace($open,$taggedOpen,$html);
}
return $html;
}

echo parse_css($css,$html);

?>

 

What I'm trying to do now is get rid of my str_replace in favour of preg_replace. The problem I'm having is catering for tags such as <a> where the 'class' attribute could be either side of the 'href' attribute. I thought I was starting to get the hang of the syntax for regex now, but my attempts haven't quite worked!

Link to comment
Share on other sites

Now I know this isn't right, but it's the start Ive made so far, what I think I need to do is change the (.*^class) and (.*) to something more restrictive, as (.*^class) gets tags within tags (like an <a> inside a <p>). But it's a start! Any help is appreciated!

Link to comment
Share on other sites

This isn't perfect--it's not entirely flexible and a callback would be better--but it does what you want:

 

<pre>
<?php

$css = '<style type="text/css">
	h1 { font-family: Arial, Helvetica, sans-serif; }
	h2 { text-decoration: none; color: #666666; }
	p.error { color: #CC0000; }
	p { color: #333333; }
	a { color: green; }
	</style>';

$html = '<h1>Regex CSS Replacement Test</h1><h2>It\'s Regex with style!</h2><p>As you can clearly see it\'s possible to use regular expresions to search through your style sheet and hard code the syles into the html tags.</p><p class="error">It\'s red good! It all <a href="http://www.moodle.co.uk">links</a> into my plan!</p>';

function parse_css($css,$html) {
preg_match_all('/^\s*(\w+)\.*(\w*)\s*\{\s*([^}]+?)\s*\}/m', $css, $matches, PREG_SET_ORDER);
foreach ($matches as $idx => $array) {
	// Remove the whole match.
	array_shift($matches[$idx]);
}

foreach ($matches as $match) {

	$regex = '/<' . preg_quote($match[0], '/') . '\s?([^>]*)';
	if ($match[1]) {
		$regex .= 'class="' . preg_quote($match[1], '/') . '"([^>]*)';
	}
	$regex .= '\s?>/i';

	echo htmlspecialchars($regex), '<br>';

	$taggedOpen = '<'.$match[0].' \1 \2 style="'.$match[2].'">';

	$html = preg_replace($regex, $taggedOpen, $html);
}
return $html;
}


echo parse_css($css,$html);

?>
</pre>

Link to comment
Share on other sites

Thanks again! What I need to do though is modify it so that it works with these styles:

<style type="text/css">
	h1 { font-family: Arial, Helvetica, sans-serif; }
	h2 { text-decoration: none; color: #666666; }
	p.error { color: #CC0000; }
	p { color: #333333; }
	a { color: green; }
	a.error { color: pink; }
	</style>

Like so:

<p class="error">It\'s red good! It all <a href="http://www.moodle.co.uk" class="error">links</a> into my plan!</p>

Oh sorry, I forgot to post the changes that I made! I got it to this:

<?php

$css = '<style type="text/css">
	h1 { font-family: Arial, Helvetica, sans-serif; }
	h2 { text-decoration: underline; color: #666666; }
	p { color: #333333; }
	p.error { color: #CC0000; }
	a { color: green; }
	a.error { color: pink; }
	</style>';

$html = '<h1>Regex CSS Replacement Test</h1><h2>It\'s Regex with style!</h2><p>As you can clearly see it\'s possible to use regular expresions to search through your style sheet and hard code the syles into the html tags.</p><p class="error">It\'s red good! It all <a href="http://www.moodle.co.uk" class="error">links</a> into my plan!</p>';

function parse_css($css,$html) {
preg_match_all('/^\s*(\w+)\.*(\w*)\s*\{\s*([^}]+?)\s*\}/m', $css, $matches, PREG_SET_ORDER);
foreach ($matches as $idx => $array) {
	// Remove the whole match.
	array_shift($matches[$idx]);
}

foreach ($matches as $match) {
	if ($match[1]=="") {
		$html = preg_replace("/<$match[0](.*^class)>/","<$match[0] style=\"$match[2]\"$1>",$html);
	} else {
		$html = preg_replace("/<$match[0](.*)class=[\"|\']$match[1][\"|\'](.*)>/","<$match[0]$1style=\"$match[2]\"$2>",$html);
	}
}
return $html;
}

echo parse_css($css,$html);

?>

Link to comment
Share on other sites

Changes marked with #####:

 

<?php

$css = '<style type="text/css">
	h1 { font-family: Arial, Helvetica, sans-serif; }
	h2 { text-decoration: underline; color: #666666; }
	p { color: #333333; }
	p.error { color: #CC0000; }
	a { color: green; }
	a.error { color: pink; }
	</style>';

$html = '<h1>Regex CSS Replacement Test</h1><h2>It\'s Regex with style!</h2><p>As you can clearly see it\'s possible to use regular expresions to search through your style sheet and hard code the syles into the html tags.</p><p class="error">It\'s red good! It all <a href="http://www.moodle.co.uk" class="error">links</a> into my plan!</p>';

function parse_css($css,$html) {
preg_match_all('/^\s*(\w+)\.*(\w*)\s*\{\s*([^}]+?)\s*\}/m', $css, $matches, PREG_SET_ORDER);
foreach ($matches as $idx => $array) {
	// Remove the whole match.
	array_shift($matches[$idx]);
}

##### Sort descending so tags with classes come before those without.
array_multisort($matches, SORT_DESC);

foreach ($matches as $match) {
	if ($match[1]=="") {
		##### Ignore the match if it already contains a style attribute.
		$html = preg_replace("/<$match[0](((?!style)[^>])*)>/","<$match[0] style=\"$match[2]\"$1>",$html);
	} else {
		$html = preg_replace("/<$match[0]([^>]*)class=[\"|\']$match[1][\"|\']([^>]*)>/","<$match[0]$1style=\"$match[2]\"$2>",$html);
	}
}
return $html;
}

echo parse_css($css,$html);

?>

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.