1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
//! **This is a very experimental and unstable library! There WILL be breaking changes.**

#![doc(html_root_url = "https://docs.rs/topiary/0.0.1")]
#![forbid(unsafe_code)]
#![warn(clippy::pedantic)]

use std::iter::FromIterator;

#[cfg(doctest)]
pub mod readme {
	doc_comment::doctest!("../README.md");
}

//TODO: Support ::before and the like.
#[must_use]
pub fn scope_css(input: &str, selector: &str) -> String {
	let mut processed = 0usize;
	let mut whitespace_start = 0usize;
	let mut at_found = false;
	let mut result = String::with_capacity(2 * input.len());

	let mut i = 0;
	for c in input.chars() {
		let c_len = String::from_iter(&[c]).len();
		match c {
			'@' => at_found = true,
			w if w.is_whitespace() => (),
			'{' | ',' => {
				if !at_found {
					//TODO: This still messes up if there's multibyte characters anywhere.
					result = result + &input[processed..whitespace_start] + selector;
					processed = whitespace_start;
				}
				whitespace_start = i + c_len;
				at_found = false;
			}
			'}' => {
				whitespace_start = i + c_len;
				at_found = false;
			}
			_ => whitespace_start = i + c_len,
		}
		i += c_len;
	}

	result += &input[processed..];
	result = result.replace(":scope", &format!(":not({0})>{0}", selector));
	result.shrink_to_fit();
	result
}