Quote:
Originally Posted by mattmc
Do you have this precisely documented in any way? Do I really need to do this:
Code:
// Before
p.blah, p.foo, p.bar { ... }
// After
p.blah { ... }
p.foo { ... }
p.bar { ... }
|
I'd expect comma-separated rules to be fine. The rules that haven't worked correctly for me are multi-selector rules like:
Code:
p.blah span.foo { ... }
because kindlegen treats that as though you had specified:
Code:
p.blah span.foo, span.foo { ... }
if memory serves, but I'm not 100% certain—it might have interpreted it as:
Code:
p.blah, span.foo { ... }
Either way, all the
span tags with the
foo class matched, including
span tags that shouldn't have matched because they weren't in the specified enclosing element.
Quote:
Originally Posted by mattmc
And this:
Code:
// Before
<p class="blah foo">Words</p>
p.blah.foo { ... }
// After
<p class="blah-foo">Words</p>
p.blah-foo { ... }
|
I have had problems with styles not getting merged correctly, though it is possible that those problems were false positives caused by the gross misinterpretation of multi-element selectors as previously mentioned.
Whether combined rules were actually necessary or not... would require lots of software archaeology to determine definitively.
Quote:
Originally Posted by mattmc
And this:
Code:
// Before
<p><span>Words</span></p>
p span { ... }
// After
<p><span class="p-span">Words</span></p>
span.p-span { ... }
|
Yes, that's very similar to the rules I've had trouble with.
Quote:
Originally Posted by mattmc
What about this, is this necessary?
Code:
// Before
<p class="blah foo">Words</p>
p.blah { color:red }
p.foo {size:1.2em }
// After
<p class="blah-foo">Words</p>
p.blah-foo { color:red;size:1.2em }
|
Unclear, for the same reason that the second one was unclear.
Quote:
Originally Posted by mattmc
Although you did point out that my iBooks problem with the popovers was probably a specificity issue, I'm still wondering if it would be worth using Juice to do this to my Kindle file. (It'd obviously affect KF8 as well as KF7 since you can't split source files.)
|
Blowing things into inline styles is kind of messy, so if you can avoid it, that's probably better.
Quote:
Originally Posted by mattmc
I could probably get this going using NodeJS in a few hours, make the script available, maybe even set up an NPM package. Any thoughts?
|
If you want to take a crack at implementing the full set of sanity checks and fixup tweaks, JavaScript would be a really good way to do it. My first thought as far as implementation would be something like this:
- Iterate all the elements and css rules, and create an associative array with every single CSS class name used in either one. You'll need this for uniqueness checks later.
- Iterate all the elements looking for elements with multiple classes. Change the spaces to hyphens or underscores. Add a random number if needed to make the resulting class name unique. Create an associative array mapping each of the original classes to an array, and in that array, put the names of any combined classes based on the original class. That way, you can quickly obtain a list of all the new combined classes that are derived from each of the original classes.
- Iterate all the CSS rules. For each rule, if any part of the rule matches one of the original classes, add a new copy of that rule with the combined class substituted in place of the original class, but do not remove the original rule, because it might also affect other non-combining elements.
- Iterate all the CSS styles a second time. This time, for each rule with a complex selector (multi-element or multi-class or both), take the selector, remove all the characters that would be invalid in a class name, add a random number if needed to make the class name unique, and create a copy of that rule under the new name. Delete the original rule. Then use getElementsBySelector to obtain a list of elements that match the original selector. For each element, add the newly generated class name to its list of classes.
- Repeat steps 2–4 in a loop until nothing changes. (Step 4 can cause you to need to repeat step 2.)
- Optional: For each CSS style, perform a getElementsBySelector, and if it returns an empty list of elements, delete the unused style.
Be careful when handling the
@ styles, e.g.
@media,
@font-face, etc. You can probably just ignore
@font-face rules entirely, and emit them in the final output.
You'll want to process the rules within an
@media query just like you would any other rule, being sure to add any replacement rules inside the same
@media query that the original came from. I wouldn't try to process the
@media rules separately, because my gut says that could cause a nasty mess.
I'm suddenly tempted to try this.