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
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
// This file is part of css. It is subject to the license terms in the COPYRIGHT file found in the top-level directory of this distribution and at https://raw.githubusercontent.com/lemonrock/css/master/COPYRIGHT. No part of predicator, including this file, may be copied, modified, propagated, or distributed except according to the terms contained in the COPYRIGHT file.
// Copyright © 2017 The developers of css. See the COPYRIGHT file in the top-level directory of this distribution and at https://raw.githubusercontent.com/lemonrock/css/master/COPYRIGHT.


#[derive(Debug, Clone)]
pub struct Stylesheet
{
	pub rules: CssRules,
	pub source_map_url: Option<String>,
	pub source_url: Option<String>,
}

impl HasCssRules for Stylesheet
{
	#[inline(always)]
	fn css_rules(&self) -> &CssRules
	{
		&self.rules
	}
	
	#[inline(always)]
	fn css_rules_mut(&mut self) -> &mut CssRules
	{
		&mut self.rules
	}
	
	#[inline(always)]
	fn css_rules_slice(&self) -> &[CssRule]
	{
		&self.rules.0[..]
	}
	
	#[inline(always)]
	fn css_rules_vec(&self) -> &Vec<CssRule>
	{
		&self.rules.0
	}
	
	#[inline(always)]
	fn css_rules_vec_mut(&mut self) -> &mut Vec<CssRule>
	{
		&mut self.rules.0
	}
}

impl Stylesheet
{
	// An solution is to use the HTTP header SourceMap: <url>
	pub fn to_css<W: fmt::Write>(&self, destination: &mut W, include_source_urls: bool) -> fmt::Result
	{
		if include_source_urls
		{
			// An older convention was to use '@' instead of '#'
			
			if let Some(ref source_map_url) = self.source_map_url
			{
				write!(destination, "//# sourceMappingURL=<{}>\n", source_map_url)?;
			}
			
			if let Some(ref source_url) = self.source_url
			{
				write!(destination, "//# sourceURL=<{}>\n", source_url)?;
			}
		}
		
		self.rules.to_css(destination)?;
		
		Ok(())
	}
	
	pub fn parse<'i>(css: &'i str) -> Result<Self, PreciseParseError<CustomParseError<'i>>>
	{
		const LineNumberingIsZeroBased: u32 = 0;
		
		let mut parserInput = ParserInput::new_with_line_number_offset(css, LineNumberingIsZeroBased);
		let mut input = Parser::new(&mut parserInput);
		
		let mut rules = Vec::new();
		
		let topLevelRuleParser = TopLevelRuleParser
		{
			context: ParserContext
			{
				rule_type: None,
				parsing_mode: ParsingMode::Default,
			},
			state: State::Start,
			namespaces: Namespaces::empty(),
		};
		
		{
			let mut iter = RuleListParser::new_for_stylesheet(&mut input, topLevelRuleParser);
			
			while let Some(result) = iter.next()
			{
				match result
				{
					Ok(rule) => rules.push(rule),
					Err(preciseParseError) => return Err(preciseParseError),
				}
			}
		}
		
		Ok
		(
			Self
			{
				rules: CssRules(rules),
				source_map_url: input.current_source_map_url().map(String::from),
				source_url: input.current_source_url().map(String::from),
			}
		)
	}
	
}