Updated: Comment #25
Problem/Motivation
When using the Color module and switching color scheme, the css files are rewritten.
A problem occurs when an element has an id (#) that starts with a valid hex string (e.g. #bac is a valid hex string).
The css line with #bac in it will be replaced with a color (e.g. #ff0033 will change #background in a css line with #ff0033kground).
Proposed resolution
The solution proposed is to change the regular expression that filters the css tags to check for colors.
The current logic in #24 suggests a : followed by zero or more spaces, a # and three or six characters followed by a space (see #21).
Remaining tasks
Manual test if the regex and the replacement works properly.
The easiest way to test it is to patch Bartik with the following patch in #25 (https://drupal.org/files/color-css-bartik-manual-test-585172.patch).
Use Bartik as your theme and switch from the default color set to Firehouse.
All other manual testing is greatly encouraged.
Original report by @theresaanna
I am testing out a new theme using color module and I have two color schemes - my default and one other. Upon switching to my second color scheme, my "#background" id in style.css gets turned into "#fba6a6kground" after the conversion is done.
Here are my hex values:
'#B29269,#df783e,#F79F1A,#5C3F1C,#666666' => t('Sherbet (Default)'),
'#77E3FF,#3E6273,#293440,#454B4C,#666666' => t('Ocean Storms'),
| Comment | File | Size | Author |
|---|---|---|---|
| #35 | color_module_changes-585172-34.patch | 3.33 KB | mgifford |
| #34 | color_module_changes-585172-34.patch | 3.33 KB | kerby70 |
| #31 | 585172-drupal-color_rewrite-31.patch | 3.74 KB | markhalliwell |
| #31 | bartik-colors-original.txt | 2.16 KB | markhalliwell |
| #31 | bartik-colors-changed.txt | 2.17 KB | markhalliwell |
Comments
Comment #1
theresaanna commentedChanging "#background" to ".background" un-confused color.module. So it seems the "#" is what is prompting this change. Which is not surprising but I thought I'd mention it anyway!
Comment #2
mattyoung commented#bac is a legal css hex string. The color.module substitutes any #xxx string if xxx is a hex string it thinks it need to substitute. I have to make all my css id strings not begin with hex string to stop this. for example, if use #_background will solve the problem.
Comment #3
seanrDefinitely a bug - I just wasted some time on this too. Color.module's regexp needs to look for a # and three or six characters followed by a space.
Comment #4
seanrFlagging for 7 - anyone know if this is still an issue?
Comment #5
seanrComment #6
aspilicious commentedSomething like this?
// Find all colors in the stylesheet and the chunks in between.
$style = preg_split('/(#[0-9a-f]{6}|#[0-9a-f]{3})/i', $style, -1, PREG_SPLIT_DELIM_CAPTURE);
TO
// Find all colors in the stylesheet and the chunks in between.
$style = preg_split('/(#([0-9a-f]{6}|[0-9a-f]{3})[^0-9a-zA-Z])/i', $style, -1, PREG_SPLIT_DELIM_CAPTURE);
Comment #7
mr.baileys@aspilicious: the new regex should also take into account that hyphens and underscores are valid in CSS identifiers. So the regex you propose, while an improvement, could still rename "#bac-foo" to something else.
Comment #8
tim.plunkettMoving.
Comment #9
markhalliwellI agree with @seanr's in #3. The regex needs to only match against # and three or six characters followed by a space.
Comment #10
seanrIt may not alway be a space (i.e. #fff;). What about this?
\b being word boundary. That still doesn't get us around the hyphen issue though.
Comment #11
iflista commentedWorking with this.
Comment #12
thijsvdanker commentedUpdated the issue summary to match the current state of the issue.
Comment #13
mcrittenden commented@iflista please feel free to re-assign yourself if you'd like.
Comment #14
seanrI created a patch based on #10. Not perfect as mentioned, but it's definitely an improvement.
Comment #15
markhalliwellPatch looks good. We need to manually test that this fixes the issue though.
Comment #16
thijsvdanker commentedI've tweaked it a little bit.
With the patch from #14, the css id's with a dash or a direct colon after it are still captured while they shouldn't be:
http://rubular.com/r/QASUuvVh8m
I've extended the regex to check for one or more spaces and 1 semicolon.
My result: http://rubular.com/r/X4QupGFn4Z
As a result of adding the semicolon to the regex it (the semicolon) is not spitted out as a chunk anymore.
Therefor I've added the
on line 443.
To review it manually:
Add this to the top of bartik's style.css:
Add some styles to the different schemes of color.inc:
Start switching presets and check /sites/default/files/color/bartik-foobar/color.css.
Comment #17
mcrittenden commentedThe one downside that I can think of about the approach in #16 is that a semicolon is not strictly required in CSS if it's the last property in a rule. For example, this is valid CSS:
There's no semicolon after #000000 but it's still valid since it's the last rule, and the patch in #16 wouldn't catch that since it requires a semicolon be present. I'm not sure if this is really something we should worry about though, since I almost never see this in practice.
Thoughts?
Comment #18
thijsvdanker commented@mcrittenden: You're right.
I came up with:
/(#[0-9a-f]{6}\b|#[0-9a-f]{3}\b)\s*;*$/imbasically checking on an end-of-line.
but that fails on
#bac
{
bac-ground: #bac;
}
http://rubular.com/r/T7NeUVveZw
Patch attached, not sure if my regex-fu goes any further than this :)
Comment #19
markhalliwellI may not be getting the context of the function right now, but are we splitting these into "chunks" for any particular reason? Or are we just splitting them into chunks to try and find all the the hex values in the style sheet? It seems to me that this is just the wrong regex/function to begin with. Why iterate over each chunk when you can find them all at once?
Could we just not change this to
preg_match_alland just find the hex values? Maybe something like:Just a thought.
edit: note this regex only matches hexes inside curly brackets (to completely avoid #ids).
Comment #20
markhalliwellOops, forgot to upload a screenshot of my regex matches (note this has the "ims" pattern modifiers enabled):

Comment #21
thijsvdanker commentedThe stylesheet is splitted into chunks because the css identifiers are also analyzed (to see if it is a link, text, or something else).
Link and text are special properties, and when they are detected in the chunk that is not a color, their value gets colorshifted.
see _color_shift().
My last attempt:
/\:\s*(#[0-9a-f]{6}\b|#[0-9a-f]{3}\b)/ichecking for a colon before the start of the color.
Worked pretty good for me!
http://rubular.com/r/p4E771NmFb
As the colon is now part of the capture, it needs to be added to the color chunk.
Comment #22
markhalliwellFair enough, this fixes the immediate issue. I still don't agree that this is really the right approach overall (for figuring out the right colors), but that is part of a bigger refactoring issue anyway. I'll just have to live with how bad color is until 9.x.
@thijsvdanker, could you update the issue summary with your steps to reproduce. Someone someone else, please manually test. Provide screenshots and upload the modified bartik source and the rewritten color files. Thanks!
Comment #24
thijsvdanker commentedThe previous patch stripped of the space between the colon and the color, which is expected in the test.
This patch should make the test pass again.
I'll start updating the issue summary.
Comment #25
thijsvdanker commentedThis patch can be used to modify Bartik to have some css that would fail before the patch.
Can be used to manually test the patch.
Comment #25.0
thijsvdanker commentedthijsvdanker: Changed the issue summary up to comment #11
Comment #26
thijsvdanker commentedUpdated the issue summary.
Comment #28
thijsvdanker commentedThe patch in #25 is just to be used for manual testing.
The real patch in #24 passes the test.
Comment #29
markhalliwellI manually tested this. Everything looks good, but noticed that the gradients didn't get changed. I'm still convinced we should just try a different approach (like the one I suggested in #19) instead of trying to work inside of "chunks". Perhaps we should
preg_match_all/preg_replacethe color shifted things like links/text that match certain criteria first? Idk, just seems that we're trying to fix a broken system.Comment #30
markhalliwellI'm going to try and step through this to see how this is actually re-writing things.
Comment #31
markhalliwellHere is an 8.x version using preg_replace_callback and closures (which is far more powerful and easier to understand). This still does "chunks" but it is geared more around each selector group (between {}). @thijsvdanker, if you want we could still use the simpler regex for 7.x (if you can figure out the gradients).
Also attached is the before/after bartik CSS stylesheets.
Comment #31.0
markhalliwellUpdated issue summary to reflect state and manual testing.
Comment #33
jhedstromComment #34
kerby70 commentedReroll attached.
Per #2361823: Remove usage of drupal_strtolower() changed drupal_strtolower to Unicode::strtolower
Comment #35
mgiffordRe-uploading for the bots.
Comment #47
quietone commentedColor has been removed from core, #3270899: Remove Color module from core.