[geary] Scope style rules in emails
- From: Robert Schroll <rschroll src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [geary] Scope style rules in emails
- Date: Wed, 10 Sep 2014 02:05:20 +0000 (UTC)
commit 6454860e9e6b91d7c3e77f9b3d0b8de2e1274c15
Author: Robert Schroll <rschroll gmail com>
Date: Mon Sep 1 22:03:36 2014 -0400
Scope style rules in emails
Some rules, including @media rules, are dropped completely. Others,
like @font-face rules, are passed through unaltered. There's a
potential that these could interfere with rules we might specify in the
future.
Based on work by Simon Lipp.
https://bugzilla.gnome.org/show_bug.cgi?id=712904
.../conversation-viewer/conversation-viewer.vala | 56 ++++++++++++++++++++
1 files changed, 56 insertions(+), 0 deletions(-)
---
diff --git a/src/client/conversation-viewer/conversation-viewer.vala
b/src/client/conversation-viewer/conversation-viewer.vala
index 61a2104..312ed4b 100644
--- a/src/client/conversation-viewer/conversation-viewer.vala
+++ b/src/client/conversation-viewer/conversation-viewer.vala
@@ -697,6 +697,20 @@ public class ConversationViewer : Gtk.Box {
} catch (Error html_error) {
warning("Error setting HTML for message: %s", html_error.message);
}
+
+ // Scope <style> tags
+ try {
+ WebKit.DOM.StyleSheetList style_sheets = web_view.get_dom_document().style_sheets;
+ string div_id = div_message.get_attribute("id");
+ for (int i = 0; i < style_sheets.length; i++) {
+ WebKit.DOM.StyleSheet style_sheet = style_sheets.item(i);
+ WebKit.DOM.Element style_element = (WebKit.DOM.Element) style_sheet.owner_node;
+ if (closest_ancestor(style_element, ".email") == div_message)
+ style_element.set_text_content(scope_style_sheet(style_sheet, div_id));
+ }
+ } catch (Error error) {
+ warning("Error scoping style nodes: %s", error.message);
+ }
// Look for any attached emails
Gee.List<Geary.RFC822.Message> sub_messages = message.get_sub_messages();
@@ -810,6 +824,48 @@ public class ConversationViewer : Gtk.Box {
loader.set_size(adj_width, adj_height);
}
+ /*
+ * Go through a style sheet and modify the selectors of style rules so that
+ * they only apply to elements in the email identified by div_id. Certain
+ * other rules (font faces, for example) are passed through unaltered, while
+ * the rest (like @media rules) are removed, since WebKitGTK doesn't implement
+ * the API we'd need to parse them. WebKitGTK is also missing the API to
+ * alter the style sheet in place, so we return a string that will replace the
+ * contents of the style sheet in question.
+ */
+ private string scope_style_sheet(WebKit.DOM.StyleSheet style_sheet, string div_id) {
+ string scope = @"div[id='$div_id'] > .email_container > .body ";
+ StringBuilder new_style = new StringBuilder();
+ WebKit.DOM.CSSRuleList rules = ((WebKit.DOM.CSSStyleSheet) style_sheet).rules;
+ try {
+ // Remove "html", "body", "html body", and "html > body" from the start of selectors
+ GLib.Regex body_html = new Regex("^(\\s*html(\\s*>)?)?(\\s*body)?");
+ for (int i = 0; i < rules.length; i++) {
+ WebKit.DOM.CSSRule rule = rules.item(i);
+ switch (rule.type) {
+ // See https://developer.mozilla.org/en-US/docs/Web/API/CSSRule
+ case 1: // Style rule
+ new_style.append(body_html.replace_literal(rule.css_text, -1, 0, scope) + "\n");
+ break;
+
+ case 5: // Font face rule
+ case 7: // Keyframes rule
+ case 8: // Keyframe rule
+ case 10: // Namespace rule
+ case 11: // Counter style rule
+ case 14: // Font feature values rule
+ new_style.append(rule.css_text + "\n");
+ break;
+
+ // All other rules are omitted.
+ }
+ }
+ } catch (Error error) {
+ warning("Regex error in CSS scoping: %s", error.message);
+ }
+ return new_style.str;
+ }
+
private void unhide_last_email() {
WebKit.DOM.HTMLElement last_email = (WebKit.DOM.HTMLElement)
web_view.container.get_last_child().previous_sibling;
if (last_email != null) {
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]