-
-
Notifications
You must be signed in to change notification settings - Fork 33
WIP: Added additional arg for turning styles into properties #139
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 6 commits
209036e
8a2a072
cb4dd0b
8f75d56
7a9c350
8d61dc4
0959ecc
1b9bc34
3365a79
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -74,6 +74,8 @@ pub struct InlineOptions<'a> { | |
// Python wrapper for `CSSInliner` and `&str` in Rust & simple functions on the Python side | ||
/// Additional CSS to inline. | ||
pub extra_css: Option<Cow<'a, str>>, | ||
/// Whether to break down styles into property tags | ||
pub styles_as_attributes: bool, | ||
} | ||
|
||
impl<'a> InlineOptions<'a> { | ||
|
@@ -87,6 +89,7 @@ impl<'a> InlineOptions<'a> { | |
base_url: None, | ||
load_remote_stylesheets: true, | ||
extra_css: None, | ||
styles_as_attributes: false, | ||
} | ||
} | ||
|
||
|
@@ -125,6 +128,13 @@ impl<'a> InlineOptions<'a> { | |
self | ||
} | ||
|
||
/// Insert styles as attributes | ||
#[must_use] | ||
pub fn styles_as_attributes(mut self, styles_as_attributes: bool) -> Self { | ||
self.styles_as_attributes = styles_as_attributes; | ||
self | ||
} | ||
|
||
/// Create a new `CSSInliner` instance from this options. | ||
#[must_use] | ||
pub const fn build(self) -> CSSInliner<'a> { | ||
|
@@ -141,6 +151,7 @@ impl Default for InlineOptions<'_> { | |
base_url: None, | ||
load_remote_stylesheets: true, | ||
extra_css: None, | ||
styles_as_attributes: false, | ||
} | ||
} | ||
} | ||
|
@@ -284,7 +295,7 @@ impl<'a> CSSInliner<'a> { | |
} | ||
} | ||
if let Some(extra_css) = &self.options.extra_css { | ||
process_css(&document, extra_css, &mut styles); | ||
process_css(&document, extra_css.as_ref(), &mut styles); | ||
} | ||
for (node_id, styles) in styles { | ||
// SAFETY: All nodes are alive as long as `document` is in scope. | ||
|
@@ -299,7 +310,9 @@ impl<'a> CSSInliner<'a> { | |
.attributes | ||
.try_borrow_mut() | ||
{ | ||
if let Some(existing_style) = attributes.get_mut("style") { | ||
if self.options.styles_as_attributes { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Here we'd have a similar situation to the branchs below:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Okay so within the conditional branch I created, we will have 2 conditional branches? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yep There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Okay so I think I got the first bullet point completed, I'm not quite sure if I understand the second one yet, but it's also a bit late for me haha. Will take a look tomorrow. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Awesome! I think we can use For the second point, the workflow would look like the other branch with At the moment, Something like this fn insert_as_attributes(
existing_style: &str,
new_styles: &AHashMap<String, (Specificity, String)>,
attributes: &mut Attributes
) -> Result<()> {
let mut input = cssparser::ParserInput::new(existing_style);
let mut parser = cssparser::Parser::new(&mut input);
let declarations = cssparser::DeclarationListParser::new(&mut parser, parser::CSSDeclarationListParser);
let mut buffer: SmallVec<[String; 8]> = smallvec![];
for declaration in declarations {
let (name, value) = declaration?;
attributes.insert(name, value);
buffer.push(name.to_string());
}
for (property, (_, value)) in new_styles {
if !buffer.contains(property) {
attributes.insert(property, value)
}
}
Ok(())
} And the last branch would look like this: insert_at_attributes(&existing_style.value, &styles, &mut attributes) I didn't test these code samples, but they should be alright :) The main idea is that existing "style" attribute styles are inserted as separate attributes immediately as they have the maximum priority, then the other ones are inserted only if they aren't clashing with already inserted ones. Then, there is a small corner case with quoting the value (see the if name.starts_with("font-family") && memchr::memchr(b'"', value.as_bytes()).is_some() {
attributes.insert(name, &value.replace('"', "\'"))
} else {
attributes.insert(name, value)
}; which could be also a small macro (the naming probably isn't much important - maybe Then, I think a few tests would be nice to have :) And a changelog entry |
||
// TODO | ||
} else if let Some(existing_style) = attributes.get_mut("style") { | ||
*existing_style = merge_styles(existing_style, &styles)?; | ||
} else { | ||
let mut final_styles = String::with_capacity(128); | ||
|
Uh oh!
There was an error while loading. Please reload this page.