Skip to content

Commit 7e3b85d

Browse files
committed
Preserve sourceURL comment in parser
In addition to the sourceMappingURL comment, there is a second special comment, "sourceURL", that can be used to set the "display name" of a style sheet for developer tools. This name is also used as the base URL for the source-map URL resolution algorithm. sourceURL is described here: https://blog.getfirebug.com/2009/08/11/give-your-eval-a-name-with-sourceurl/ The relevant Firefox bug is here: https://bugzilla.mozilla.org/show_bug.cgi?id=880831
1 parent d17fd10 commit 7e3b85d

File tree

5 files changed

+58
-5
lines changed

5 files changed

+58
-5
lines changed

Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "cssparser"
3-
version = "0.21.0"
3+
version = "0.21.1"
44
authors = [ "Simon Sapin <simon.sapin@exyr.org>" ]
55

66
description = "Rust implementation of CSS Syntax Level 3"

src/parser.rs

+9
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,15 @@ impl<'i: 't, 't> Parser<'i, 't> {
291291
self.input.tokenizer.current_source_map_url()
292292
}
293293

294+
/// The source URL, if known.
295+
///
296+
/// The source URL is extracted from a specially formatted
297+
/// comment. The last such comment is used, so this value may
298+
/// change as parsing proceeds.
299+
pub fn current_source_url(&self) -> Option<&str> {
300+
self.input.tokenizer.current_source_url()
301+
}
302+
294303
/// Return the current internal state of the parser (including position within the input).
295304
///
296305
/// This state can later be restored with the `Parser::reset` method.

src/size_of_tests.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ size_of_test!(token, Token, 32);
3636
size_of_test!(std_cow_str, Cow<'static, str>, 32);
3737
size_of_test!(cow_rc_str, CowRcStr, 16);
3838

39-
size_of_test!(tokenizer, ::tokenizer::Tokenizer, 56);
40-
size_of_test!(parser_input, ::parser::ParserInput, 128);
39+
size_of_test!(tokenizer, ::tokenizer::Tokenizer, 72);
40+
size_of_test!(parser_input, ::parser::ParserInput, 144);
4141
size_of_test!(parser, ::parser::Parser, 16);
4242
size_of_test!(source_position, ::SourcePosition, 8);
4343
size_of_test!(parser_state, ::ParserState, 24);

src/tests.rs

+26-1
Original file line numberDiff line numberDiff line change
@@ -1030,7 +1030,7 @@ fn parse_entirely_reports_first_error() {
10301030
}
10311031

10321032
#[test]
1033-
fn parse_comments() {
1033+
fn parse_sourcemapping_comments() {
10341034
let tests = vec![
10351035
("/*# sourceMappingURL=here*/", Some("here")),
10361036
("/*# sourceMappingURL=here */", Some("here")),
@@ -1054,6 +1054,31 @@ fn parse_comments() {
10541054
}
10551055
}
10561056

1057+
#[test]
1058+
fn parse_sourceurl_comments() {
1059+
let tests = vec![
1060+
("/*# sourceURL=here*/", Some("here")),
1061+
("/*# sourceURL=here */", Some("here")),
1062+
("/*@ sourceURL=here*/", Some("here")),
1063+
("/*@ sourceURL=there*/ /*# sourceURL=here*/", Some("here")),
1064+
("/*# sourceURL=here there */", Some("here")),
1065+
("/*# sourceURL= here */", Some("")),
1066+
("/*# sourceURL=*/", Some("")),
1067+
("/*# sourceMappingUR=here */", None),
1068+
("/*! sourceURL=here */", None),
1069+
("/*# sourceURL = here */", None),
1070+
("/* # sourceURL=here */", None)
1071+
];
1072+
1073+
for test in tests {
1074+
let mut input = ParserInput::new(test.0);
1075+
let mut parser = Parser::new(&mut input);
1076+
while let Ok(_) = parser.next_including_whitespace() {
1077+
}
1078+
assert_eq!(parser.current_source_url(), test.1);
1079+
}
1080+
}
1081+
10571082
#[test]
10581083
fn roundtrip_percentage_token() {
10591084
fn test_roundtrip(value: &str) {

src/tokenizer.rs

+20-1
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,7 @@ pub struct Tokenizer<'a> {
213213
current_line_number: u32,
214214
var_functions: SeenStatus,
215215
source_map_url: Option<&'a str>,
216+
source_url: Option<&'a str>,
216217
}
217218

218219
#[derive(Copy, Clone, PartialEq, Eq)]
@@ -238,6 +239,7 @@ impl<'a> Tokenizer<'a> {
238239
current_line_number: first_line_number,
239240
var_functions: SeenStatus::DontCare,
240241
source_map_url: None,
242+
source_url: None,
241243
}
242244
}
243245

@@ -285,6 +287,11 @@ impl<'a> Tokenizer<'a> {
285287
self.source_map_url
286288
}
287289

290+
#[inline]
291+
pub fn current_source_url(&self) -> Option<&'a str> {
292+
self.source_url
293+
}
294+
288295
#[inline]
289296
pub fn state(&self) -> ParserState {
290297
ParserState {
@@ -692,7 +699,8 @@ fn consume_whitespace<'a>(tokenizer: &mut Tokenizer<'a>, newline: bool) -> Token
692699
}
693700

694701

695-
// Check for a sourceMappingURL comment and update the tokenizer appropriately.
702+
// Check for sourceMappingURL or sourceURL comments and update the
703+
// tokenizer appropriately.
696704
fn check_for_source_map<'a>(tokenizer: &mut Tokenizer<'a>, contents: &'a str) {
697705
let directive = "# sourceMappingURL=";
698706
let directive_old = "@ sourceMappingURL=";
@@ -704,6 +712,17 @@ fn check_for_source_map<'a>(tokenizer: &mut Tokenizer<'a>, contents: &'a str) {
704712
c == ' ' || c == '\t' || c == '\x0C' || c == '\r' || c == '\n'
705713
}).next()
706714
}
715+
716+
let directive = "# sourceURL=";
717+
let directive_old = "@ sourceURL=";
718+
719+
// If there is a source map directive, extract the URL.
720+
if contents.starts_with(directive) || contents.starts_with(directive_old) {
721+
let contents = &contents[directive.len()..];
722+
tokenizer.source_url = contents.split(|c| {
723+
c == ' ' || c == '\t' || c == '\x0C' || c == '\r' || c == '\n'
724+
}).next()
725+
}
707726
}
708727

709728
fn consume_comment<'a>(tokenizer: &mut Tokenizer<'a>) -> &'a str {

0 commit comments

Comments
 (0)