mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
Thread ParseError return values through CSS parsing.
This commit is contained in:
parent
58e39bfffa
commit
27ae1ef2e7
121 changed files with 2133 additions and 1505 deletions
35
Cargo.lock
generated
35
Cargo.lock
generated
|
@ -314,7 +314,7 @@ version = "0.0.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"azure 0.16.0 (git+https://github.com/servo/rust-azure)",
|
"azure 0.16.0 (git+https://github.com/servo/rust-azure)",
|
||||||
"canvas_traits 0.0.1",
|
"canvas_traits 0.0.1",
|
||||||
"cssparser 0.13.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cssparser 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"euclid 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"euclid 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"gleam 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"gleam 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"ipc-channel 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"ipc-channel 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -329,7 +329,7 @@ dependencies = [
|
||||||
name = "canvas_traits"
|
name = "canvas_traits"
|
||||||
version = "0.0.1"
|
version = "0.0.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cssparser 0.13.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cssparser 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"euclid 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"euclid 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"heapsize 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"heapsize 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"heapsize_derive 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"heapsize_derive 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -567,14 +567,14 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cssparser"
|
name = "cssparser"
|
||||||
version = "0.13.7"
|
version = "0.14.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cssparser-macros 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cssparser-macros 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"heapsize 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"heapsize 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
"phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"procedural-masquerade 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"procedural-masquerade 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
"quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
"syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -586,7 +586,7 @@ version = "0.3.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
"phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"procedural-masquerade 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"procedural-masquerade 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
"quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
"syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
@ -1005,7 +1005,7 @@ name = "geckoservo"
|
||||||
version = "0.0.1"
|
version = "0.0.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"cssparser 0.13.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cssparser 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -1072,7 +1072,7 @@ dependencies = [
|
||||||
name = "gfx_tests"
|
name = "gfx_tests"
|
||||||
version = "0.0.1"
|
version = "0.0.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cssparser 0.13.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cssparser 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"gfx 0.0.1",
|
"gfx 0.0.1",
|
||||||
"ipc-channel 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"ipc-channel 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"style 0.0.1",
|
"style 0.0.1",
|
||||||
|
@ -2158,7 +2158,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "procedural-masquerade"
|
name = "procedural-masquerade"
|
||||||
version = "0.1.1"
|
version = "0.1.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -2371,7 +2371,7 @@ dependencies = [
|
||||||
"caseless 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"caseless 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"cmake 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cmake 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"cookie 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cookie 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"cssparser 0.13.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cssparser 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"deny_public_fields 0.0.1",
|
"deny_public_fields 0.0.1",
|
||||||
"devtools_traits 0.0.1",
|
"devtools_traits 0.0.1",
|
||||||
"dom_struct 0.0.1",
|
"dom_struct 0.0.1",
|
||||||
|
@ -2444,7 +2444,7 @@ dependencies = [
|
||||||
"app_units 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"app_units 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"canvas_traits 0.0.1",
|
"canvas_traits 0.0.1",
|
||||||
"cssparser 0.13.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cssparser 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"euclid 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"euclid 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"gfx_traits 0.0.1",
|
"gfx_traits 0.0.1",
|
||||||
"heapsize 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"heapsize 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -2516,7 +2516,7 @@ name = "selectors"
|
||||||
version = "0.19.0"
|
version = "0.19.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"cssparser 0.13.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cssparser 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -2898,7 +2898,7 @@ dependencies = [
|
||||||
"bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"cssparser 0.13.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cssparser 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"encoding 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
|
"encoding 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"euclid 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"euclid 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -2952,7 +2952,7 @@ version = "0.0.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"app_units 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"app_units 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"cssparser 0.13.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cssparser 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"euclid 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"euclid 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"html5ever 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"html5ever 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"parking_lot 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"parking_lot 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -2972,10 +2972,11 @@ name = "style_traits"
|
||||||
version = "0.0.1"
|
version = "0.0.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"app_units 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"app_units 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"cssparser 0.13.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cssparser 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"euclid 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"euclid 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"heapsize 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"heapsize 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"heapsize_derive 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"heapsize_derive 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"selectors 0.19.0",
|
||||||
"serde 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_derive 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_derive 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
@ -2985,7 +2986,7 @@ name = "stylo_tests"
|
||||||
version = "0.0.1"
|
version = "0.0.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"cssparser 0.13.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cssparser 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"euclid 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"euclid 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"geckoservo 0.0.1",
|
"geckoservo 0.0.1",
|
||||||
|
@ -3565,7 +3566,7 @@ dependencies = [
|
||||||
"checksum core-foundation-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "41115a6aa5d3e1e5ef98148373f25971d1fad53818553f216495f9e67e90a624"
|
"checksum core-foundation-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "41115a6aa5d3e1e5ef98148373f25971d1fad53818553f216495f9e67e90a624"
|
||||||
"checksum core-graphics 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ead017dcf77f503dc991f6b52de6084eeea60a94b0a652baa9bf88654a28e83f"
|
"checksum core-graphics 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ead017dcf77f503dc991f6b52de6084eeea60a94b0a652baa9bf88654a28e83f"
|
||||||
"checksum core-text 4.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0e9719616a10f717628e074744f8c55df7b450f7a34d29c196d14f4498aad05d"
|
"checksum core-text 4.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0e9719616a10f717628e074744f8c55df7b450f7a34d29c196d14f4498aad05d"
|
||||||
"checksum cssparser 0.13.7 (registry+https://github.com/rust-lang/crates.io-index)" = "ef6124306e5ebc5ab11891d063aeafdd0cdc308079b708c8b566125f3680292b"
|
"checksum cssparser 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4a5ca71edbab09f8dc1e3d1c132717562c3b01c8598ab669183c5195bb1761"
|
||||||
"checksum cssparser-macros 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "079adec4af52bb5275eadd004292028c79eb3c5f5b4ee8086a36d4197032f6df"
|
"checksum cssparser-macros 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "079adec4af52bb5275eadd004292028c79eb3c5f5b4ee8086a36d4197032f6df"
|
||||||
"checksum dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97590ba53bcb8ac28279161ca943a924d1fd4a8fb3fa63302591647c4fc5b850"
|
"checksum dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97590ba53bcb8ac28279161ca943a924d1fd4a8fb3fa63302591647c4fc5b850"
|
||||||
"checksum dbus 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4aee01fb76ada3e5e7ca642ea6664ebf7308a810739ca2aca44909a1191ac254"
|
"checksum dbus 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4aee01fb76ada3e5e7ca642ea6664ebf7308a810739ca2aca44909a1191ac254"
|
||||||
|
@ -3696,7 +3697,7 @@ dependencies = [
|
||||||
"checksum plane-split 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "556929ef77bf07a9f8584d21382bcebcd6e6f5845d311824d369e1df7cf56d54"
|
"checksum plane-split 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "556929ef77bf07a9f8584d21382bcebcd6e6f5845d311824d369e1df7cf56d54"
|
||||||
"checksum png 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3cb773e9a557edb568ce9935cf783e3cdcabe06a9449d41b3e5506d88e582c82"
|
"checksum png 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3cb773e9a557edb568ce9935cf783e3cdcabe06a9449d41b3e5506d88e582c82"
|
||||||
"checksum precomputed-hash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf1fc3616b3ef726a847f2cd2388c646ef6a1f1ba4835c2629004da48184150"
|
"checksum precomputed-hash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf1fc3616b3ef726a847f2cd2388c646ef6a1f1ba4835c2629004da48184150"
|
||||||
"checksum procedural-masquerade 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9f566249236c6ca4340f7ca78968271f0ed2b0f234007a61b66f9ecd0af09260"
|
"checksum procedural-masquerade 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c93cdc1fb30af9ddf3debc4afbdb0f35126cbd99daa229dd76cdd5349b41d989"
|
||||||
"checksum pulldown-cmark 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1058d7bb927ca067656537eec4e02c2b4b70eaaa129664c5b90c111e20326f41"
|
"checksum pulldown-cmark 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1058d7bb927ca067656537eec4e02c2b4b70eaaa129664c5b90c111e20326f41"
|
||||||
"checksum quasi 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18c45c4854d6d1cf5d531db97c75880feb91c958b0720f4ec1057135fec358b3"
|
"checksum quasi 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18c45c4854d6d1cf5d531db97c75880feb91c958b0720f4ec1057135fec358b3"
|
||||||
"checksum quasi_codegen 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "51b9e25fa23c044c1803f43ca59c98dac608976dd04ce799411edd58ece776d4"
|
"checksum quasi_codegen 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "51b9e25fa23c044c1803f43ca59c98dac608976dd04ce799411edd58ece776d4"
|
||||||
|
|
|
@ -12,7 +12,7 @@ path = "lib.rs"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
azure = {git = "https://github.com/servo/rust-azure"}
|
azure = {git = "https://github.com/servo/rust-azure"}
|
||||||
canvas_traits = {path = "../canvas_traits"}
|
canvas_traits = {path = "../canvas_traits"}
|
||||||
cssparser = "0.13.7"
|
cssparser = "0.14.0"
|
||||||
euclid = "0.13"
|
euclid = "0.13"
|
||||||
gleam = "0.4"
|
gleam = "0.4"
|
||||||
ipc-channel = "0.7"
|
ipc-channel = "0.7"
|
||||||
|
|
|
@ -10,7 +10,7 @@ name = "canvas_traits"
|
||||||
path = "lib.rs"
|
path = "lib.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
cssparser = "0.13.7"
|
cssparser = "0.14.0"
|
||||||
euclid = "0.13"
|
euclid = "0.13"
|
||||||
heapsize = "0.4"
|
heapsize = "0.4"
|
||||||
heapsize_derive = "0.1"
|
heapsize_derive = "0.1"
|
||||||
|
|
|
@ -35,7 +35,7 @@ byteorder = "1.0"
|
||||||
canvas_traits = {path = "../canvas_traits"}
|
canvas_traits = {path = "../canvas_traits"}
|
||||||
caseless = "0.1.0"
|
caseless = "0.1.0"
|
||||||
cookie = "0.6"
|
cookie = "0.6"
|
||||||
cssparser = "0.13.7"
|
cssparser = "0.14.0"
|
||||||
deny_public_fields = {path = "../deny_public_fields"}
|
deny_public_fields = {path = "../deny_public_fields"}
|
||||||
devtools_traits = {path = "../devtools_traits"}
|
devtools_traits = {path = "../devtools_traits"}
|
||||||
dom_struct = {path = "../dom_struct"}
|
dom_struct = {path = "../dom_struct"}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use canvas_traits::{CanvasGradientStop, FillOrStrokeStyle, LinearGradientStyle, RadialGradientStyle};
|
use canvas_traits::{CanvasGradientStop, FillOrStrokeStyle, LinearGradientStyle, RadialGradientStyle};
|
||||||
use cssparser::{Parser, RGBA};
|
use cssparser::{Parser, ParserInput, RGBA};
|
||||||
use cssparser::Color as CSSColor;
|
use cssparser::Color as CSSColor;
|
||||||
use dom::bindings::cell::DOMRefCell;
|
use dom::bindings::cell::DOMRefCell;
|
||||||
use dom::bindings::codegen::Bindings::CanvasGradientBinding;
|
use dom::bindings::codegen::Bindings::CanvasGradientBinding;
|
||||||
|
@ -53,7 +53,8 @@ impl CanvasGradientMethods for CanvasGradient {
|
||||||
return Err(Error::IndexSize);
|
return Err(Error::IndexSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut parser = Parser::new(&color);
|
let mut input = ParserInput::new(&color);
|
||||||
|
let mut parser = Parser::new(&mut input);
|
||||||
let color = CSSColor::parse(&mut parser);
|
let color = CSSColor::parse(&mut parser);
|
||||||
let color = if parser.is_exhausted() {
|
let color = if parser.is_exhausted() {
|
||||||
match color {
|
match color {
|
||||||
|
|
|
@ -6,7 +6,7 @@ use canvas_traits::{Canvas2dMsg, CanvasCommonMsg, CanvasMsg};
|
||||||
use canvas_traits::{CompositionOrBlending, FillOrStrokeStyle, FillRule};
|
use canvas_traits::{CompositionOrBlending, FillOrStrokeStyle, FillRule};
|
||||||
use canvas_traits::{LineCapStyle, LineJoinStyle, LinearGradientStyle};
|
use canvas_traits::{LineCapStyle, LineJoinStyle, LinearGradientStyle};
|
||||||
use canvas_traits::{RadialGradientStyle, RepetitionStyle, byte_swap_and_premultiply};
|
use canvas_traits::{RadialGradientStyle, RepetitionStyle, byte_swap_and_premultiply};
|
||||||
use cssparser::{Parser, RGBA};
|
use cssparser::{Parser, ParserInput, RGBA};
|
||||||
use cssparser::Color as CSSColor;
|
use cssparser::Color as CSSColor;
|
||||||
use dom::bindings::cell::DOMRefCell;
|
use dom::bindings::cell::DOMRefCell;
|
||||||
use dom::bindings::codegen::Bindings::CSSStyleDeclarationBinding::CSSStyleDeclarationMethods;
|
use dom::bindings::codegen::Bindings::CSSStyleDeclarationBinding::CSSStyleDeclarationMethods;
|
||||||
|
@ -463,7 +463,8 @@ impl CanvasRenderingContext2D {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_color(&self, string: &str) -> Result<RGBA, ()> {
|
fn parse_color(&self, string: &str) -> Result<RGBA, ()> {
|
||||||
let mut parser = Parser::new(&string);
|
let mut input = ParserInput::new(string);
|
||||||
|
let mut parser = Parser::new(&mut input);
|
||||||
let color = CSSColor::parse(&mut parser);
|
let color = CSSColor::parse(&mut parser);
|
||||||
if parser.is_exhausted() {
|
if parser.is_exhausted() {
|
||||||
match color {
|
match color {
|
||||||
|
@ -1314,7 +1315,8 @@ impl Drop for CanvasRenderingContext2D {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_color(string: &str) -> Result<RGBA, ()> {
|
pub fn parse_color(string: &str) -> Result<RGBA, ()> {
|
||||||
let mut parser = Parser::new(&string);
|
let mut input = ParserInput::new(string);
|
||||||
|
let mut parser = Parser::new(&mut input);
|
||||||
match CSSColor::parse(&mut parser) {
|
match CSSColor::parse(&mut parser) {
|
||||||
Ok(CSSColor::RGBA(rgba)) => {
|
Ok(CSSColor::RGBA(rgba)) => {
|
||||||
if parser.is_exhausted() {
|
if parser.is_exhausted() {
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use cssparser::{Parser, serialize_identifier};
|
use cssparser::{Parser, ParserInput, serialize_identifier};
|
||||||
use dom::bindings::codegen::Bindings::WindowBinding::WindowBinding::WindowMethods;
|
use dom::bindings::codegen::Bindings::WindowBinding::WindowBinding::WindowMethods;
|
||||||
use dom::bindings::error::Fallible;
|
use dom::bindings::error::Fallible;
|
||||||
use dom::bindings::reflector::Reflector;
|
use dom::bindings::reflector::Reflector;
|
||||||
|
@ -39,7 +39,8 @@ impl CSS {
|
||||||
|
|
||||||
/// https://drafts.csswg.org/css-conditional/#dom-css-supports
|
/// https://drafts.csswg.org/css-conditional/#dom-css-supports
|
||||||
pub fn Supports_(win: &Window, condition: DOMString) -> bool {
|
pub fn Supports_(win: &Window, condition: DOMString) -> bool {
|
||||||
let mut input = Parser::new(&condition);
|
let mut input = ParserInput::new(&condition);
|
||||||
|
let mut input = Parser::new(&mut input);
|
||||||
let cond = parse_condition_or_declaration(&mut input);
|
let cond = parse_condition_or_declaration(&mut input);
|
||||||
if let Ok(cond) = cond {
|
if let Ok(cond) = cond {
|
||||||
let url = win.Document().url();
|
let url = win.Document().url();
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use cssparser::Parser;
|
use cssparser::{Parser, ParserInput};
|
||||||
use dom::bindings::codegen::Bindings::CSSKeyframesRuleBinding;
|
use dom::bindings::codegen::Bindings::CSSKeyframesRuleBinding;
|
||||||
use dom::bindings::codegen::Bindings::CSSKeyframesRuleBinding::CSSKeyframesRuleMethods;
|
use dom::bindings::codegen::Bindings::CSSKeyframesRuleBinding::CSSKeyframesRuleMethods;
|
||||||
use dom::bindings::error::ErrorResult;
|
use dom::bindings::error::ErrorResult;
|
||||||
|
@ -58,7 +58,8 @@ impl CSSKeyframesRule {
|
||||||
|
|
||||||
/// Given a keyframe selector, finds the index of the first corresponding rule if any
|
/// Given a keyframe selector, finds the index of the first corresponding rule if any
|
||||||
fn find_rule(&self, selector: &str) -> Option<usize> {
|
fn find_rule(&self, selector: &str) -> Option<usize> {
|
||||||
let mut input = Parser::new(selector);
|
let mut input = ParserInput::new(selector);
|
||||||
|
let mut input = Parser::new(&mut input);
|
||||||
if let Ok(sel) = KeyframeSelector::parse(&mut input) {
|
if let Ok(sel) = KeyframeSelector::parse(&mut input) {
|
||||||
let guard = self.cssrule.shared_lock().read();
|
let guard = self.cssrule.shared_lock().read();
|
||||||
// This finds the *last* element matching a selector
|
// This finds the *last* element matching a selector
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use cssparser::Parser;
|
use cssparser::{Parser, ParserInput};
|
||||||
use dom::bindings::codegen::Bindings::CSSMediaRuleBinding;
|
use dom::bindings::codegen::Bindings::CSSMediaRuleBinding;
|
||||||
use dom::bindings::codegen::Bindings::CSSMediaRuleBinding::CSSMediaRuleMethods;
|
use dom::bindings::codegen::Bindings::CSSMediaRuleBinding::CSSMediaRuleMethods;
|
||||||
use dom::bindings::codegen::Bindings::WindowBinding::WindowBinding::WindowMethods;
|
use dom::bindings::codegen::Bindings::WindowBinding::WindowBinding::WindowMethods;
|
||||||
|
@ -69,7 +69,8 @@ impl CSSMediaRule {
|
||||||
|
|
||||||
/// https://drafts.csswg.org/css-conditional-3/#the-cssmediarule-interface
|
/// https://drafts.csswg.org/css-conditional-3/#the-cssmediarule-interface
|
||||||
pub fn set_condition_text(&self, text: DOMString) {
|
pub fn set_condition_text(&self, text: DOMString) {
|
||||||
let mut input = Parser::new(&text);
|
let mut input = ParserInput::new(&text);
|
||||||
|
let mut input = Parser::new(&mut input);
|
||||||
let global = self.global();
|
let global = self.global();
|
||||||
let win = global.as_window();
|
let win = global.as_window();
|
||||||
let url = win.get_url();
|
let url = win.get_url();
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use cssparser::Parser;
|
use cssparser::{Parser, ParserInput};
|
||||||
use dom::bindings::codegen::Bindings::CSSSupportsRuleBinding;
|
use dom::bindings::codegen::Bindings::CSSSupportsRuleBinding;
|
||||||
use dom::bindings::codegen::Bindings::WindowBinding::WindowBinding::WindowMethods;
|
use dom::bindings::codegen::Bindings::WindowBinding::WindowBinding::WindowMethods;
|
||||||
use dom::bindings::js::Root;
|
use dom::bindings::js::Root;
|
||||||
|
@ -55,7 +55,8 @@ impl CSSSupportsRule {
|
||||||
|
|
||||||
/// https://drafts.csswg.org/css-conditional-3/#the-csssupportsrule-interface
|
/// https://drafts.csswg.org/css-conditional-3/#the-csssupportsrule-interface
|
||||||
pub fn set_condition_text(&self, text: DOMString) {
|
pub fn set_condition_text(&self, text: DOMString) {
|
||||||
let mut input = Parser::new(&text);
|
let mut input = ParserInput::new(&text);
|
||||||
|
let mut input = Parser::new(&mut input);
|
||||||
let cond = SupportsCondition::parse(&mut input);
|
let cond = SupportsCondition::parse(&mut input);
|
||||||
if let Ok(cond) = cond {
|
if let Ok(cond) = cond {
|
||||||
let global = self.global();
|
let global = self.global();
|
||||||
|
|
|
@ -2061,7 +2061,7 @@ impl ElementMethods for Element {
|
||||||
// https://dom.spec.whatwg.org/#dom-element-matches
|
// https://dom.spec.whatwg.org/#dom-element-matches
|
||||||
fn Matches(&self, selectors: DOMString) -> Fallible<bool> {
|
fn Matches(&self, selectors: DOMString) -> Fallible<bool> {
|
||||||
match SelectorParser::parse_author_origin_no_namespace(&selectors) {
|
match SelectorParser::parse_author_origin_no_namespace(&selectors) {
|
||||||
Err(()) => Err(Error::Syntax),
|
Err(_) => Err(Error::Syntax),
|
||||||
Ok(selectors) => {
|
Ok(selectors) => {
|
||||||
let mut ctx = MatchingContext::new(MatchingMode::Normal, None);
|
let mut ctx = MatchingContext::new(MatchingMode::Normal, None);
|
||||||
Ok(matches_selector_list(&selectors, &Root::from_ref(self), &mut ctx))
|
Ok(matches_selector_list(&selectors, &Root::from_ref(self), &mut ctx))
|
||||||
|
@ -2077,7 +2077,7 @@ impl ElementMethods for Element {
|
||||||
// https://dom.spec.whatwg.org/#dom-element-closest
|
// https://dom.spec.whatwg.org/#dom-element-closest
|
||||||
fn Closest(&self, selectors: DOMString) -> Fallible<Option<Root<Element>>> {
|
fn Closest(&self, selectors: DOMString) -> Fallible<Option<Root<Element>>> {
|
||||||
match SelectorParser::parse_author_origin_no_namespace(&selectors) {
|
match SelectorParser::parse_author_origin_no_namespace(&selectors) {
|
||||||
Err(()) => Err(Error::Syntax),
|
Err(_) => Err(Error::Syntax),
|
||||||
Ok(selectors) => {
|
Ok(selectors) => {
|
||||||
let root = self.upcast::<Node>();
|
let root = self.upcast::<Node>();
|
||||||
for element in root.inclusive_ancestors() {
|
for element in root.inclusive_ancestors() {
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use cssparser::Parser as CssParser;
|
use cssparser::{Parser as CssParser, ParserInput};
|
||||||
use dom::attr::Attr;
|
use dom::attr::Attr;
|
||||||
use dom::bindings::cell::DOMRefCell;
|
use dom::bindings::cell::DOMRefCell;
|
||||||
use dom::bindings::codegen::Bindings::DOMTokenListBinding::DOMTokenListBinding::DOMTokenListMethods;
|
use dom::bindings::codegen::Bindings::DOMTokenListBinding::DOMTokenListBinding::DOMTokenListMethods;
|
||||||
|
@ -278,7 +278,8 @@ impl HTMLLinkElement {
|
||||||
None => "",
|
None => "",
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut css_parser = CssParser::new(&mq_str);
|
let mut input = ParserInput::new(&mq_str);
|
||||||
|
let mut css_parser = CssParser::new(&mut input);
|
||||||
let win = document.window();
|
let win = document.window();
|
||||||
let doc_url = document.url();
|
let doc_url = document.url();
|
||||||
let context = CssParserContext::new_for_cssom(&doc_url, win.css_error_reporter(), Some(CssRuleType::Media),
|
let context = CssParserContext::new_for_cssom(&doc_url, win.css_error_reporter(), Some(CssRuleType::Media),
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use cssparser::Parser as CssParser;
|
use cssparser::{Parser as CssParser, ParserInput};
|
||||||
use dom::bindings::cell::DOMRefCell;
|
use dom::bindings::cell::DOMRefCell;
|
||||||
use dom::bindings::codegen::Bindings::HTMLStyleElementBinding;
|
use dom::bindings::codegen::Bindings::HTMLStyleElementBinding;
|
||||||
use dom::bindings::codegen::Bindings::HTMLStyleElementBinding::HTMLStyleElementMethods;
|
use dom::bindings::codegen::Bindings::HTMLStyleElementBinding::HTMLStyleElementMethods;
|
||||||
|
@ -91,8 +91,9 @@ impl HTMLStyleElement {
|
||||||
PARSING_MODE_DEFAULT,
|
PARSING_MODE_DEFAULT,
|
||||||
doc.quirks_mode());
|
doc.quirks_mode());
|
||||||
let shared_lock = node.owner_doc().style_shared_lock().clone();
|
let shared_lock = node.owner_doc().style_shared_lock().clone();
|
||||||
|
let mut input = ParserInput::new(&mq_str);
|
||||||
let mq = Arc::new(shared_lock.wrap(
|
let mq = Arc::new(shared_lock.wrap(
|
||||||
parse_media_query_list(&context, &mut CssParser::new(&mq_str))));
|
parse_media_query_list(&context, &mut CssParser::new(&mut input))));
|
||||||
let loader = StylesheetLoader::for_element(self.upcast());
|
let loader = StylesheetLoader::for_element(self.upcast());
|
||||||
let sheet = Stylesheet::from_str(&data, win.get_url(), Origin::Author, mq,
|
let sheet = Stylesheet::from_str(&data, win.get_url(), Origin::Author, mq,
|
||||||
shared_lock, Some(&loader),
|
shared_lock, Some(&loader),
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use cssparser::Parser;
|
use cssparser::{Parser, ParserInput};
|
||||||
use dom::bindings::codegen::Bindings::MediaListBinding;
|
use dom::bindings::codegen::Bindings::MediaListBinding;
|
||||||
use dom::bindings::codegen::Bindings::MediaListBinding::MediaListMethods;
|
use dom::bindings::codegen::Bindings::MediaListBinding::MediaListMethods;
|
||||||
use dom::bindings::codegen::Bindings::WindowBinding::WindowBinding::WindowMethods;
|
use dom::bindings::codegen::Bindings::WindowBinding::WindowBinding::WindowMethods;
|
||||||
|
@ -71,7 +71,8 @@ impl MediaListMethods for MediaList {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Step 3
|
// Step 3
|
||||||
let mut parser = Parser::new(&value);
|
let mut input = ParserInput::new(&value);
|
||||||
|
let mut parser = Parser::new(&mut input);
|
||||||
let global = self.global();
|
let global = self.global();
|
||||||
let win = global.as_window();
|
let win = global.as_window();
|
||||||
let url = win.get_url();
|
let url = win.get_url();
|
||||||
|
@ -107,7 +108,8 @@ impl MediaListMethods for MediaList {
|
||||||
// https://drafts.csswg.org/cssom/#dom-medialist-appendmedium
|
// https://drafts.csswg.org/cssom/#dom-medialist-appendmedium
|
||||||
fn AppendMedium(&self, medium: DOMString) {
|
fn AppendMedium(&self, medium: DOMString) {
|
||||||
// Step 1
|
// Step 1
|
||||||
let mut parser = Parser::new(&medium);
|
let mut input = ParserInput::new(&medium);
|
||||||
|
let mut parser = Parser::new(&mut input);
|
||||||
let global = self.global();
|
let global = self.global();
|
||||||
let win = global.as_window();
|
let win = global.as_window();
|
||||||
let url = win.get_url();
|
let url = win.get_url();
|
||||||
|
@ -135,7 +137,8 @@ impl MediaListMethods for MediaList {
|
||||||
// https://drafts.csswg.org/cssom/#dom-medialist-deletemedium
|
// https://drafts.csswg.org/cssom/#dom-medialist-deletemedium
|
||||||
fn DeleteMedium(&self, medium: DOMString) {
|
fn DeleteMedium(&self, medium: DOMString) {
|
||||||
// Step 1
|
// Step 1
|
||||||
let mut parser = Parser::new(&medium);
|
let mut input = ParserInput::new(&medium);
|
||||||
|
let mut parser = Parser::new(&mut input);
|
||||||
let global = self.global();
|
let global = self.global();
|
||||||
let win = global.as_window();
|
let win = global.as_window();
|
||||||
let url = win.get_url();
|
let url = win.get_url();
|
||||||
|
|
|
@ -717,7 +717,7 @@ impl Node {
|
||||||
// Step 1.
|
// Step 1.
|
||||||
match SelectorParser::parse_author_origin_no_namespace(&selectors) {
|
match SelectorParser::parse_author_origin_no_namespace(&selectors) {
|
||||||
// Step 2.
|
// Step 2.
|
||||||
Err(()) => Err(Error::Syntax),
|
Err(_) => Err(Error::Syntax),
|
||||||
// Step 3.
|
// Step 3.
|
||||||
Ok(selectors) => {
|
Ok(selectors) => {
|
||||||
let mut ctx = MatchingContext::new(MatchingMode::Normal, None);
|
let mut ctx = MatchingContext::new(MatchingMode::Normal, None);
|
||||||
|
@ -737,7 +737,7 @@ impl Node {
|
||||||
// Step 1.
|
// Step 1.
|
||||||
match SelectorParser::parse_author_origin_no_namespace(&selectors) {
|
match SelectorParser::parse_author_origin_no_namespace(&selectors) {
|
||||||
// Step 2.
|
// Step 2.
|
||||||
Err(()) => Err(Error::Syntax),
|
Err(_) => Err(Error::Syntax),
|
||||||
// Step 3.
|
// Step 3.
|
||||||
Ok(selectors) => {
|
Ok(selectors) => {
|
||||||
let mut descendants = self.traverse_preorder();
|
let mut descendants = self.traverse_preorder();
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
use base64;
|
use base64;
|
||||||
use bluetooth_traits::BluetoothRequest;
|
use bluetooth_traits::BluetoothRequest;
|
||||||
use cssparser::Parser;
|
use cssparser::{Parser, ParserInput};
|
||||||
use devtools_traits::{ScriptToDevtoolsControlMsg, TimelineMarker, TimelineMarkerType};
|
use devtools_traits::{ScriptToDevtoolsControlMsg, TimelineMarker, TimelineMarkerType};
|
||||||
use dom::bindings::cell::DOMRefCell;
|
use dom::bindings::cell::DOMRefCell;
|
||||||
use dom::bindings::codegen::Bindings::DocumentBinding::{DocumentMethods, DocumentReadyState};
|
use dom::bindings::codegen::Bindings::DocumentBinding::{DocumentMethods, DocumentReadyState};
|
||||||
|
@ -1003,7 +1003,8 @@ impl WindowMethods for Window {
|
||||||
|
|
||||||
// https://drafts.csswg.org/cssom-view/#dom-window-matchmedia
|
// https://drafts.csswg.org/cssom-view/#dom-window-matchmedia
|
||||||
fn MatchMedia(&self, query: DOMString) -> Root<MediaQueryList> {
|
fn MatchMedia(&self, query: DOMString) -> Root<MediaQueryList> {
|
||||||
let mut parser = Parser::new(&query);
|
let mut input = ParserInput::new(&query);
|
||||||
|
let mut parser = Parser::new(&mut input);
|
||||||
let url = self.get_url();
|
let url = self.get_url();
|
||||||
let quirks_mode = self.Document().quirks_mode();
|
let quirks_mode = self.Document().quirks_mode();
|
||||||
let context = CssParserContext::new_for_cssom(&url, self.css_error_reporter(), Some(CssRuleType::Media),
|
let context = CssParserContext::new_for_cssom(&url, self.css_error_reporter(), Some(CssRuleType::Media),
|
||||||
|
|
|
@ -13,7 +13,7 @@ path = "lib.rs"
|
||||||
app_units = "0.4.1"
|
app_units = "0.4.1"
|
||||||
atomic_refcell = "0.1"
|
atomic_refcell = "0.1"
|
||||||
canvas_traits = {path = "../canvas_traits"}
|
canvas_traits = {path = "../canvas_traits"}
|
||||||
cssparser = "0.13.7"
|
cssparser = "0.14.0"
|
||||||
euclid = "0.13"
|
euclid = "0.13"
|
||||||
gfx_traits = {path = "../gfx_traits"}
|
gfx_traits = {path = "../gfx_traits"}
|
||||||
heapsize = "0.4"
|
heapsize = "0.4"
|
||||||
|
|
|
@ -9,7 +9,7 @@ use msg::constellation_msg::PipelineId;
|
||||||
use script_traits::ConstellationControlMsg;
|
use script_traits::ConstellationControlMsg;
|
||||||
use servo_url::ServoUrl;
|
use servo_url::ServoUrl;
|
||||||
use std::sync::{Mutex, Arc};
|
use std::sync::{Mutex, Arc};
|
||||||
use style::error_reporting::{ParseErrorReporter, ParseError};
|
use style::error_reporting::{ParseErrorReporter, ContextualParseError};
|
||||||
|
|
||||||
#[derive(HeapSizeOf, Clone)]
|
#[derive(HeapSizeOf, Clone)]
|
||||||
pub struct CSSErrorReporter {
|
pub struct CSSErrorReporter {
|
||||||
|
@ -25,7 +25,7 @@ impl ParseErrorReporter for CSSErrorReporter {
|
||||||
fn report_error<'a>(&self,
|
fn report_error<'a>(&self,
|
||||||
input: &mut Parser,
|
input: &mut Parser,
|
||||||
position: SourcePosition,
|
position: SourcePosition,
|
||||||
error: ParseError<'a>,
|
error: ContextualParseError<'a>,
|
||||||
url: &ServoUrl,
|
url: &ServoUrl,
|
||||||
line_number_offset: u64) {
|
line_number_offset: u64) {
|
||||||
let location = input.source_location(position);
|
let location = input.source_location(position);
|
||||||
|
|
|
@ -24,7 +24,7 @@ gecko_like_types = []
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bitflags = "0.7"
|
bitflags = "0.7"
|
||||||
matches = "0.1"
|
matches = "0.1"
|
||||||
cssparser = "0.13.7"
|
cssparser = "0.14.0"
|
||||||
log = "0.3"
|
log = "0.3"
|
||||||
fnv = "1.0"
|
fnv = "1.0"
|
||||||
phf = "0.7.18"
|
phf = "0.7.18"
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
use attr::{AttrSelectorWithNamespace, ParsedAttrSelectorOperation, AttrSelectorOperator};
|
use attr::{AttrSelectorWithNamespace, ParsedAttrSelectorOperation, AttrSelectorOperator};
|
||||||
use attr::{ParsedCaseSensitivity, SELECTOR_WHITESPACE, NamespaceConstraint};
|
use attr::{ParsedCaseSensitivity, SELECTOR_WHITESPACE, NamespaceConstraint};
|
||||||
|
use cssparser::{ParseError, BasicParseError};
|
||||||
use cssparser::{Token, Parser as CssParser, parse_nth, ToCss, serialize_identifier, CssStringWriter};
|
use cssparser::{Token, Parser as CssParser, parse_nth, ToCss, serialize_identifier, CssStringWriter};
|
||||||
use precomputed_hash::PrecomputedHash;
|
use precomputed_hash::PrecomputedHash;
|
||||||
use servo_arc::{Arc, HeaderWithLength, ThinArc};
|
use servo_arc::{Arc, HeaderWithLength, ThinArc};
|
||||||
|
@ -43,6 +44,30 @@ fn to_ascii_lowercase(s: &str) -> Cow<str> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
|
pub enum SelectorParseError<'i, T> {
|
||||||
|
PseudoElementInComplexSelector,
|
||||||
|
NoQualifiedNameInAttributeSelector,
|
||||||
|
TooManyCompoundSelectorComponentsInNegation,
|
||||||
|
NegationSelectorComponentNotNamespace,
|
||||||
|
NegationSelectorComponentNotLocalName,
|
||||||
|
EmptySelector,
|
||||||
|
NonSimpleSelectorInNegation,
|
||||||
|
UnexpectedTokenInAttributeSelector,
|
||||||
|
PseudoElementExpectedColon,
|
||||||
|
PseudoElementExpectedIdent,
|
||||||
|
UnsupportedPseudoClass,
|
||||||
|
UnexpectedIdent(Cow<'i, str>),
|
||||||
|
ExpectedNamespace,
|
||||||
|
Custom(T),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, T> Into<ParseError<'a, SelectorParseError<'a, T>>> for SelectorParseError<'a, T> {
|
||||||
|
fn into(self) -> ParseError<'a, SelectorParseError<'a, T>> {
|
||||||
|
ParseError::Custom(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
macro_rules! with_all_bounds {
|
macro_rules! with_all_bounds {
|
||||||
(
|
(
|
||||||
[ $( $InSelector: tt )* ]
|
[ $( $InSelector: tt )* ]
|
||||||
|
@ -97,26 +122,30 @@ with_bounds! {
|
||||||
[From<String> + for<'a> From<&'a str>]
|
[From<String> + for<'a> From<&'a str>]
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Parser {
|
pub trait Parser<'i> {
|
||||||
type Impl: SelectorImpl;
|
type Impl: SelectorImpl;
|
||||||
|
type Error: 'i;
|
||||||
|
|
||||||
/// This function can return an "Err" pseudo-element in order to support CSS2.1
|
/// This function can return an "Err" pseudo-element in order to support CSS2.1
|
||||||
/// pseudo-elements.
|
/// pseudo-elements.
|
||||||
fn parse_non_ts_pseudo_class(&self, _name: Cow<str>)
|
fn parse_non_ts_pseudo_class(&self, name: Cow<'i, str>)
|
||||||
-> Result<<Self::Impl as SelectorImpl>::NonTSPseudoClass, ()> {
|
-> Result<<Self::Impl as SelectorImpl>::NonTSPseudoClass,
|
||||||
Err(())
|
ParseError<'i, SelectorParseError<'i, Self::Error>>> {
|
||||||
|
Err(ParseError::Custom(SelectorParseError::UnexpectedIdent(name)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_non_ts_functional_pseudo_class
|
fn parse_non_ts_functional_pseudo_class<'t>
|
||||||
(&self, _name: Cow<str>, _arguments: &mut CssParser)
|
(&self, name: Cow<'i, str>, _arguments: &mut CssParser<'i, 't>)
|
||||||
-> Result<<Self::Impl as SelectorImpl>::NonTSPseudoClass, ()>
|
-> Result<<Self::Impl as SelectorImpl>::NonTSPseudoClass,
|
||||||
|
ParseError<'i, SelectorParseError<'i, Self::Error>>>
|
||||||
{
|
{
|
||||||
Err(())
|
Err(ParseError::Custom(SelectorParseError::UnexpectedIdent(name)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_pseudo_element(&self, _name: Cow<str>)
|
fn parse_pseudo_element(&self, name: Cow<'i, str>)
|
||||||
-> Result<<Self::Impl as SelectorImpl>::PseudoElement, ()> {
|
-> Result<<Self::Impl as SelectorImpl>::PseudoElement,
|
||||||
Err(())
|
ParseError<'i, SelectorParseError<'i, Self::Error>>> {
|
||||||
|
Err(ParseError::Custom(SelectorParseError::UnexpectedIdent(name)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_namespace(&self) -> Option<<Self::Impl as SelectorImpl>::NamespaceUrl> {
|
fn default_namespace(&self) -> Option<<Self::Impl as SelectorImpl>::NamespaceUrl> {
|
||||||
|
@ -157,8 +186,9 @@ impl<Impl: SelectorImpl> SelectorList<Impl> {
|
||||||
/// https://drafts.csswg.org/selectors/#grouping
|
/// https://drafts.csswg.org/selectors/#grouping
|
||||||
///
|
///
|
||||||
/// Return the Selectors or Err if there is an invalid selector.
|
/// Return the Selectors or Err if there is an invalid selector.
|
||||||
pub fn parse<P>(parser: &P, input: &mut CssParser) -> Result<Self, ()>
|
pub fn parse<'i, 't, P, E>(parser: &P, input: &mut CssParser<'i, 't>)
|
||||||
where P: Parser<Impl=Impl> {
|
-> Result<Self, ParseError<'i, SelectorParseError<'i, E>>>
|
||||||
|
where P: Parser<'i, Impl=Impl, Error=E> {
|
||||||
input.parse_comma_separated(|input| parse_selector(parser, input).map(SelectorAndHashes::new))
|
input.parse_comma_separated(|input| parse_selector(parser, input).map(SelectorAndHashes::new))
|
||||||
.map(SelectorList)
|
.map(SelectorList)
|
||||||
}
|
}
|
||||||
|
@ -960,11 +990,11 @@ type ParseVec<Impl> = SmallVec<[Component<Impl>; 32]>;
|
||||||
/// selector : simple_selector_sequence [ combinator simple_selector_sequence ]* ;
|
/// selector : simple_selector_sequence [ combinator simple_selector_sequence ]* ;
|
||||||
///
|
///
|
||||||
/// `Err` means invalid selector.
|
/// `Err` means invalid selector.
|
||||||
fn parse_selector<P, Impl>(
|
fn parse_selector<'i, 't, P, E, Impl>(
|
||||||
parser: &P,
|
parser: &P,
|
||||||
input: &mut CssParser)
|
input: &mut CssParser<'i, 't>)
|
||||||
-> Result<Selector<Impl>, ()>
|
-> Result<Selector<Impl>, ParseError<'i, SelectorParseError<'i, E>>>
|
||||||
where P: Parser<Impl=Impl>, Impl: SelectorImpl
|
where P: Parser<'i, Impl=Impl, Error=E>, Impl: SelectorImpl
|
||||||
{
|
{
|
||||||
let mut sequence = ParseVec::new();
|
let mut sequence = ParseVec::new();
|
||||||
let mut parsed_pseudo_element;
|
let mut parsed_pseudo_element;
|
||||||
|
@ -983,7 +1013,7 @@ fn parse_selector<P, Impl>(
|
||||||
loop {
|
loop {
|
||||||
let position = input.position();
|
let position = input.position();
|
||||||
match input.next_including_whitespace() {
|
match input.next_including_whitespace() {
|
||||||
Err(()) => break 'outer_loop,
|
Err(_e) => break 'outer_loop,
|
||||||
Ok(Token::WhiteSpace(_)) => any_whitespace = true,
|
Ok(Token::WhiteSpace(_)) => any_whitespace = true,
|
||||||
Ok(Token::Delim('>')) => {
|
Ok(Token::Delim('>')) => {
|
||||||
combinator = Combinator::Child;
|
combinator = Combinator::Child;
|
||||||
|
@ -1026,12 +1056,13 @@ fn parse_selector<P, Impl>(
|
||||||
|
|
||||||
impl<Impl: SelectorImpl> Selector<Impl> {
|
impl<Impl: SelectorImpl> Selector<Impl> {
|
||||||
/// Parse a selector, without any pseudo-element.
|
/// Parse a selector, without any pseudo-element.
|
||||||
pub fn parse<P>(parser: &P, input: &mut CssParser) -> Result<Self, ()>
|
pub fn parse<'i, 't, P, E>(parser: &P, input: &mut CssParser<'i, 't>)
|
||||||
where P: Parser<Impl=Impl>
|
-> Result<Self, ParseError<'i, SelectorParseError<'i, E>>>
|
||||||
|
where P: Parser<'i, Impl=Impl, Error=E>
|
||||||
{
|
{
|
||||||
let selector = parse_selector(parser, input)?;
|
let selector = parse_selector(parser, input)?;
|
||||||
if selector.has_pseudo_element() {
|
if selector.has_pseudo_element() {
|
||||||
return Err(())
|
return Err(ParseError::Custom(SelectorParseError::PseudoElementInComplexSelector))
|
||||||
}
|
}
|
||||||
Ok(selector)
|
Ok(selector)
|
||||||
}
|
}
|
||||||
|
@ -1040,9 +1071,10 @@ impl<Impl: SelectorImpl> Selector<Impl> {
|
||||||
/// * `Err(())`: Invalid selector, abort
|
/// * `Err(())`: Invalid selector, abort
|
||||||
/// * `Ok(None)`: Not a type selector, could be something else. `input` was not consumed.
|
/// * `Ok(None)`: Not a type selector, could be something else. `input` was not consumed.
|
||||||
/// * `Ok(Some(vec))`: Length 0 (`*|*`), 1 (`*|E` or `ns|*`) or 2 (`|E` or `ns|E`)
|
/// * `Ok(Some(vec))`: Length 0 (`*|*`), 1 (`*|E` or `ns|*`) or 2 (`|E` or `ns|E`)
|
||||||
fn parse_type_selector<P, Impl>(parser: &P, input: &mut CssParser, sequence: &mut ParseVec<Impl>)
|
fn parse_type_selector<'i, 't, P, E, Impl>(parser: &P, input: &mut CssParser<'i, 't>,
|
||||||
-> Result<bool, ()>
|
sequence: &mut ParseVec<Impl>)
|
||||||
where P: Parser<Impl=Impl>, Impl: SelectorImpl
|
-> Result<bool, ParseError<'i, SelectorParseError<'i, E>>>
|
||||||
|
where P: Parser<'i, Impl=Impl, Error=E>, Impl: SelectorImpl
|
||||||
{
|
{
|
||||||
match parse_qualified_name(parser, input, /* in_attr_selector = */ false)? {
|
match parse_qualified_name(parser, input, /* in_attr_selector = */ false)? {
|
||||||
None => Ok(false),
|
None => Ok(false),
|
||||||
|
@ -1100,11 +1132,12 @@ enum QNamePrefix<Impl: SelectorImpl> {
|
||||||
/// * `Err(())`: Invalid selector, abort
|
/// * `Err(())`: Invalid selector, abort
|
||||||
/// * `Ok(None)`: Not a simple selector, could be something else. `input` was not consumed.
|
/// * `Ok(None)`: Not a simple selector, could be something else. `input` was not consumed.
|
||||||
/// * `Ok(Some((namespace, local_name)))`: `None` for the local name means a `*` universal selector
|
/// * `Ok(Some((namespace, local_name)))`: `None` for the local name means a `*` universal selector
|
||||||
fn parse_qualified_name<'i, 't, P, Impl>
|
fn parse_qualified_name<'i, 't, P, E, Impl>
|
||||||
(parser: &P, input: &mut CssParser<'i, 't>,
|
(parser: &P, input: &mut CssParser<'i, 't>,
|
||||||
in_attr_selector: bool)
|
in_attr_selector: bool)
|
||||||
-> Result<Option<(QNamePrefix<Impl>, Option<Cow<'i, str>>)>, ()>
|
-> Result<Option<(QNamePrefix<Impl>, Option<Cow<'i, str>>)>,
|
||||||
where P: Parser<Impl=Impl>, Impl: SelectorImpl
|
ParseError<'i, SelectorParseError<'i, E>>>
|
||||||
|
where P: Parser<'i, Impl=Impl, Error=E>, Impl: SelectorImpl
|
||||||
{
|
{
|
||||||
let default_namespace = |local_name| {
|
let default_namespace = |local_name| {
|
||||||
let namespace = match parser.default_namespace() {
|
let namespace = match parser.default_namespace() {
|
||||||
|
@ -1122,7 +1155,8 @@ fn parse_qualified_name<'i, 't, P, Impl>
|
||||||
Ok(Token::Ident(local_name)) => {
|
Ok(Token::Ident(local_name)) => {
|
||||||
Ok(Some((namespace, Some(local_name))))
|
Ok(Some((namespace, Some(local_name))))
|
||||||
},
|
},
|
||||||
_ => Err(()),
|
Ok(t) => Err(ParseError::Basic(BasicParseError::UnexpectedToken(t))),
|
||||||
|
Err(e) => Err(ParseError::Basic(e)),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1134,7 +1168,7 @@ fn parse_qualified_name<'i, 't, P, Impl>
|
||||||
Ok(Token::Delim('|')) => {
|
Ok(Token::Delim('|')) => {
|
||||||
let prefix = from_cow_str(value);
|
let prefix = from_cow_str(value);
|
||||||
let result = parser.namespace_for_prefix(&prefix);
|
let result = parser.namespace_for_prefix(&prefix);
|
||||||
let url = result.ok_or(())?;
|
let url = result.ok_or(ParseError::Custom(SelectorParseError::ExpectedNamespace))?;
|
||||||
explicit_namespace(input, QNamePrefix::ExplicitNamespace(prefix, url))
|
explicit_namespace(input, QNamePrefix::ExplicitNamespace(prefix, url))
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
|
@ -1153,10 +1187,13 @@ fn parse_qualified_name<'i, 't, P, Impl>
|
||||||
Ok(Token::Delim('|')) => {
|
Ok(Token::Delim('|')) => {
|
||||||
explicit_namespace(input, QNamePrefix::ExplicitAnyNamespace)
|
explicit_namespace(input, QNamePrefix::ExplicitAnyNamespace)
|
||||||
}
|
}
|
||||||
_ => {
|
result => {
|
||||||
input.reset(position);
|
input.reset(position);
|
||||||
if in_attr_selector {
|
if in_attr_selector {
|
||||||
Err(())
|
match result {
|
||||||
|
Ok(t) => Err(ParseError::Basic(BasicParseError::UnexpectedToken(t))),
|
||||||
|
Err(e) => Err(ParseError::Basic(e)),
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
default_namespace(None)
|
default_namespace(None)
|
||||||
}
|
}
|
||||||
|
@ -1174,14 +1211,15 @@ fn parse_qualified_name<'i, 't, P, Impl>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn parse_attribute_selector<P, Impl>(parser: &P, input: &mut CssParser)
|
fn parse_attribute_selector<'i, 't, P, E, Impl>(parser: &P, input: &mut CssParser<'i, 't>)
|
||||||
-> Result<Component<Impl>, ()>
|
-> Result<Component<Impl>,
|
||||||
where P: Parser<Impl=Impl>, Impl: SelectorImpl
|
ParseError<'i, SelectorParseError<'i, E>>>
|
||||||
|
where P: Parser<'i, Impl=Impl, Error=E>, Impl: SelectorImpl
|
||||||
{
|
{
|
||||||
let namespace;
|
let namespace;
|
||||||
let local_name;
|
let local_name;
|
||||||
match parse_qualified_name(parser, input, /* in_attr_selector = */ true)? {
|
match parse_qualified_name(parser, input, /* in_attr_selector = */ true)? {
|
||||||
None => return Err(()),
|
None => return Err(ParseError::Custom(SelectorParseError::NoQualifiedNameInAttributeSelector)),
|
||||||
Some((_, None)) => unreachable!(),
|
Some((_, None)) => unreachable!(),
|
||||||
Some((ns, Some(ln))) => {
|
Some((ns, Some(ln))) => {
|
||||||
local_name = ln;
|
local_name = ln;
|
||||||
|
@ -1209,7 +1247,7 @@ fn parse_attribute_selector<P, Impl>(parser: &P, input: &mut CssParser)
|
||||||
let never_matches;
|
let never_matches;
|
||||||
match input.next() {
|
match input.next() {
|
||||||
// [foo]
|
// [foo]
|
||||||
Err(()) => {
|
Err(_) => {
|
||||||
let local_name_lower = from_cow_str(to_ascii_lowercase(&local_name));
|
let local_name_lower = from_cow_str(to_ascii_lowercase(&local_name));
|
||||||
let local_name = from_cow_str(local_name);
|
let local_name = from_cow_str(local_name);
|
||||||
if let Some(namespace) = namespace {
|
if let Some(namespace) = namespace {
|
||||||
|
@ -1264,7 +1302,7 @@ fn parse_attribute_selector<P, Impl>(parser: &P, input: &mut CssParser)
|
||||||
never_matches = value.is_empty();
|
never_matches = value.is_empty();
|
||||||
operator = AttrSelectorOperator::Suffix;
|
operator = AttrSelectorOperator::Suffix;
|
||||||
}
|
}
|
||||||
_ => return Err(())
|
_ => return Err(SelectorParseError::UnexpectedTokenInAttributeSelector.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut case_sensitivity = parse_attribute_flags(input)?;
|
let mut case_sensitivity = parse_attribute_flags(input)?;
|
||||||
|
@ -1310,23 +1348,26 @@ fn parse_attribute_selector<P, Impl>(parser: &P, input: &mut CssParser)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn parse_attribute_flags(input: &mut CssParser) -> Result<ParsedCaseSensitivity, ()> {
|
fn parse_attribute_flags<'i, 't, E>(input: &mut CssParser<'i, 't>)
|
||||||
|
-> Result<ParsedCaseSensitivity,
|
||||||
|
ParseError<'i, SelectorParseError<'i, E>>> {
|
||||||
match input.next() {
|
match input.next() {
|
||||||
Err(()) => Ok(ParsedCaseSensitivity::CaseSensitive),
|
Err(_) => Ok(ParsedCaseSensitivity::CaseSensitive),
|
||||||
Ok(Token::Ident(ref value)) if value.eq_ignore_ascii_case("i") => {
|
Ok(Token::Ident(ref value)) if value.eq_ignore_ascii_case("i") => {
|
||||||
Ok(ParsedCaseSensitivity::AsciiCaseInsensitive)
|
Ok(ParsedCaseSensitivity::AsciiCaseInsensitive)
|
||||||
}
|
}
|
||||||
_ => Err(())
|
Ok(t) => Err(ParseError::Basic(BasicParseError::UnexpectedToken(t)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Level 3: Parse **one** simple_selector. (Though we might insert a second
|
/// Level 3: Parse **one** simple_selector. (Though we might insert a second
|
||||||
/// implied "<defaultns>|*" type selector.)
|
/// implied "<defaultns>|*" type selector.)
|
||||||
fn parse_negation<P, Impl>(parser: &P,
|
fn parse_negation<'i, 't, P, E, Impl>(parser: &P,
|
||||||
input: &mut CssParser)
|
input: &mut CssParser<'i, 't>)
|
||||||
-> Result<Component<Impl>, ()>
|
-> Result<Component<Impl>,
|
||||||
where P: Parser<Impl=Impl>, Impl: SelectorImpl
|
ParseError<'i, SelectorParseError<'i, E>>>
|
||||||
|
where P: Parser<'i, Impl=Impl, Error=E>, Impl: SelectorImpl
|
||||||
{
|
{
|
||||||
let mut v = ParseVec::new();
|
let mut v = ParseVec::new();
|
||||||
parse_compound_selector(parser, input, &mut v, /* inside_negation = */ true)?;
|
parse_compound_selector(parser, input, &mut v, /* inside_negation = */ true)?;
|
||||||
|
@ -1334,7 +1375,7 @@ fn parse_negation<P, Impl>(parser: &P,
|
||||||
if single_simple_selector(&v) {
|
if single_simple_selector(&v) {
|
||||||
Ok(Component::Negation(v.into_vec().into_boxed_slice()))
|
Ok(Component::Negation(v.into_vec().into_boxed_slice()))
|
||||||
} else {
|
} else {
|
||||||
Err(())
|
Err(ParseError::Custom(SelectorParseError::NonSimpleSelectorInNegation))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1365,13 +1406,13 @@ fn single_simple_selector<Impl: SelectorImpl>(v: &[Component<Impl>]) -> bool {
|
||||||
/// `Err(())` means invalid selector.
|
/// `Err(())` means invalid selector.
|
||||||
///
|
///
|
||||||
/// The boolean represent whether a pseudo-element has been parsed.
|
/// The boolean represent whether a pseudo-element has been parsed.
|
||||||
fn parse_compound_selector<P, Impl>(
|
fn parse_compound_selector<'i, 't, P, E, Impl>(
|
||||||
parser: &P,
|
parser: &P,
|
||||||
input: &mut CssParser,
|
input: &mut CssParser<'i, 't>,
|
||||||
mut sequence: &mut ParseVec<Impl>,
|
mut sequence: &mut ParseVec<Impl>,
|
||||||
inside_negation: bool)
|
inside_negation: bool)
|
||||||
-> Result<bool, ()>
|
-> Result<bool, ParseError<'i, SelectorParseError<'i, E>>>
|
||||||
where P: Parser<Impl=Impl>, Impl: SelectorImpl
|
where P: Parser<'i, Impl=Impl, Error=E>, Impl: SelectorImpl
|
||||||
{
|
{
|
||||||
// Consume any leading whitespace.
|
// Consume any leading whitespace.
|
||||||
loop {
|
loop {
|
||||||
|
@ -1412,21 +1453,21 @@ fn parse_compound_selector<P, Impl>(
|
||||||
loop {
|
loop {
|
||||||
match input.next_including_whitespace() {
|
match input.next_including_whitespace() {
|
||||||
Ok(Token::Colon) => {},
|
Ok(Token::Colon) => {},
|
||||||
Ok(Token::WhiteSpace(_)) | Err(()) => break,
|
Ok(Token::WhiteSpace(_)) | Err(_) => break,
|
||||||
_ => return Err(()),
|
_ => return Err(SelectorParseError::PseudoElementExpectedColon.into()),
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(emilio): Functional pseudo-classes too?
|
// TODO(emilio): Functional pseudo-classes too?
|
||||||
// We don't need it for now.
|
// We don't need it for now.
|
||||||
let name = match input.next_including_whitespace() {
|
let name = match input.next_including_whitespace() {
|
||||||
Ok(Token::Ident(name)) => name,
|
Ok(Token::Ident(name)) => name,
|
||||||
_ => return Err(()),
|
_ => return Err(SelectorParseError::PseudoElementExpectedIdent.into()),
|
||||||
};
|
};
|
||||||
|
|
||||||
let pseudo_class =
|
let pseudo_class =
|
||||||
P::parse_non_ts_pseudo_class(parser, name)?;
|
P::parse_non_ts_pseudo_class(parser, name)?;
|
||||||
if !p.supports_pseudo_class(&pseudo_class) {
|
if !p.supports_pseudo_class(&pseudo_class) {
|
||||||
return Err(());
|
return Err(SelectorParseError::UnsupportedPseudoClass.into());
|
||||||
}
|
}
|
||||||
state_selectors.push(Component::NonTSPseudoClass(pseudo_class));
|
state_selectors.push(Component::NonTSPseudoClass(pseudo_class));
|
||||||
}
|
}
|
||||||
|
@ -1448,18 +1489,19 @@ fn parse_compound_selector<P, Impl>(
|
||||||
}
|
}
|
||||||
if empty {
|
if empty {
|
||||||
// An empty selector is invalid.
|
// An empty selector is invalid.
|
||||||
Err(())
|
Err(ParseError::Custom(SelectorParseError::EmptySelector))
|
||||||
} else {
|
} else {
|
||||||
Ok(pseudo)
|
Ok(pseudo)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_functional_pseudo_class<P, Impl>(parser: &P,
|
fn parse_functional_pseudo_class<'i, 't, P, E, Impl>(parser: &P,
|
||||||
input: &mut CssParser,
|
input: &mut CssParser<'i, 't>,
|
||||||
name: Cow<str>,
|
name: Cow<'i, str>,
|
||||||
inside_negation: bool)
|
inside_negation: bool)
|
||||||
-> Result<Component<Impl>, ()>
|
-> Result<Component<Impl>,
|
||||||
where P: Parser<Impl=Impl>, Impl: SelectorImpl
|
ParseError<'i, SelectorParseError<'i, E>>>
|
||||||
|
where P: Parser<'i, Impl=Impl, Error=E>, Impl: SelectorImpl
|
||||||
{
|
{
|
||||||
match_ignore_ascii_case! { &name,
|
match_ignore_ascii_case! { &name,
|
||||||
"nth-child" => return parse_nth_pseudo_class(input, Component::NthChild),
|
"nth-child" => return parse_nth_pseudo_class(input, Component::NthChild),
|
||||||
|
@ -1468,7 +1510,7 @@ fn parse_functional_pseudo_class<P, Impl>(parser: &P,
|
||||||
"nth-last-of-type" => return parse_nth_pseudo_class(input, Component::NthLastOfType),
|
"nth-last-of-type" => return parse_nth_pseudo_class(input, Component::NthLastOfType),
|
||||||
"not" => {
|
"not" => {
|
||||||
if inside_negation {
|
if inside_negation {
|
||||||
return Err(())
|
return Err(ParseError::Custom(SelectorParseError::UnexpectedIdent("not".into())));
|
||||||
}
|
}
|
||||||
return parse_negation(parser, input)
|
return parse_negation(parser, input)
|
||||||
},
|
},
|
||||||
|
@ -1479,8 +1521,9 @@ fn parse_functional_pseudo_class<P, Impl>(parser: &P,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn parse_nth_pseudo_class<Impl, F>(input: &mut CssParser, selector: F)
|
fn parse_nth_pseudo_class<'i, 't, Impl, F, E>(input: &mut CssParser<'i, 't>, selector: F)
|
||||||
-> Result<Component<Impl>, ()>
|
-> Result<Component<Impl>,
|
||||||
|
ParseError<'i, SelectorParseError<'i, E>>>
|
||||||
where Impl: SelectorImpl, F: FnOnce(i32, i32) -> Component<Impl> {
|
where Impl: SelectorImpl, F: FnOnce(i32, i32) -> Component<Impl> {
|
||||||
let (a, b) = parse_nth(input)?;
|
let (a, b) = parse_nth(input)?;
|
||||||
Ok(selector(a, b))
|
Ok(selector(a, b))
|
||||||
|
@ -1492,11 +1535,12 @@ where Impl: SelectorImpl, F: FnOnce(i32, i32) -> Component<Impl> {
|
||||||
/// * `Err(())`: Invalid selector, abort
|
/// * `Err(())`: Invalid selector, abort
|
||||||
/// * `Ok(None)`: Not a simple selector, could be something else. `input` was not consumed.
|
/// * `Ok(None)`: Not a simple selector, could be something else. `input` was not consumed.
|
||||||
/// * `Ok(Some(_))`: Parsed a simple selector or pseudo-element
|
/// * `Ok(Some(_))`: Parsed a simple selector or pseudo-element
|
||||||
fn parse_one_simple_selector<P, Impl>(parser: &P,
|
fn parse_one_simple_selector<'i, 't, P, E, Impl>(parser: &P,
|
||||||
input: &mut CssParser,
|
input: &mut CssParser<'i, 't>,
|
||||||
inside_negation: bool)
|
inside_negation: bool)
|
||||||
-> Result<Option<SimpleSelectorParseResult<Impl>>, ()>
|
-> Result<Option<SimpleSelectorParseResult<Impl>>,
|
||||||
where P: Parser<Impl=Impl>, Impl: SelectorImpl
|
ParseError<'i, SelectorParseError<'i, E>>>
|
||||||
|
where P: Parser<'i, Impl=Impl, Error=E>, Impl: SelectorImpl
|
||||||
{
|
{
|
||||||
let start_position = input.position();
|
let start_position = input.position();
|
||||||
match input.next_including_whitespace() {
|
match input.next_including_whitespace() {
|
||||||
|
@ -1510,7 +1554,8 @@ fn parse_one_simple_selector<P, Impl>(parser: &P,
|
||||||
let class = Component::Class(from_cow_str(class));
|
let class = Component::Class(from_cow_str(class));
|
||||||
Ok(Some(SimpleSelectorParseResult::SimpleSelector(class)))
|
Ok(Some(SimpleSelectorParseResult::SimpleSelector(class)))
|
||||||
}
|
}
|
||||||
_ => Err(()),
|
Ok(t) => Err(ParseError::Basic(BasicParseError::UnexpectedToken(t))),
|
||||||
|
Err(e) => Err(ParseError::Basic(e)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(Token::SquareBracketBlock) => {
|
Ok(Token::SquareBracketBlock) => {
|
||||||
|
@ -1545,10 +1590,12 @@ fn parse_one_simple_selector<P, Impl>(parser: &P,
|
||||||
let pseudo = P::parse_pseudo_element(parser, name)?;
|
let pseudo = P::parse_pseudo_element(parser, name)?;
|
||||||
Ok(Some(SimpleSelectorParseResult::PseudoElement(pseudo)))
|
Ok(Some(SimpleSelectorParseResult::PseudoElement(pseudo)))
|
||||||
}
|
}
|
||||||
_ => Err(())
|
Ok(t) => Err(ParseError::Basic(BasicParseError::UnexpectedToken(t))),
|
||||||
|
Err(e) => Err(ParseError::Basic(e)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => Err(())
|
Ok(t) => Err(ParseError::Basic(BasicParseError::UnexpectedToken(t))),
|
||||||
|
Err(e) => Err(ParseError::Basic(e)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
|
@ -1558,8 +1605,10 @@ fn parse_one_simple_selector<P, Impl>(parser: &P,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_simple_pseudo_class<P, Impl>(parser: &P, name: Cow<str>) -> Result<Component<Impl>, ()>
|
fn parse_simple_pseudo_class<'i, P, E, Impl>(parser: &P, name: Cow<'i, str>)
|
||||||
where P: Parser<Impl=Impl>, Impl: SelectorImpl
|
-> Result<Component<Impl>,
|
||||||
|
ParseError<'i, SelectorParseError<'i, E>>>
|
||||||
|
where P: Parser<'i, Impl=Impl, Error=E>, Impl: SelectorImpl
|
||||||
{
|
{
|
||||||
(match_ignore_ascii_case! { &name,
|
(match_ignore_ascii_case! { &name,
|
||||||
"first-child" => Ok(Component::FirstChild),
|
"first-child" => Ok(Component::FirstChild),
|
||||||
|
@ -1580,7 +1629,7 @@ fn parse_simple_pseudo_class<P, Impl>(parser: &P, name: Cow<str>) -> Result<Comp
|
||||||
// NB: pub module in order to access the DummyParser
|
// NB: pub module in order to access the DummyParser
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub mod tests {
|
pub mod tests {
|
||||||
use cssparser::{Parser as CssParser, ToCss, serialize_identifier};
|
use cssparser::{Parser as CssParser, ToCss, serialize_identifier, ParserInput};
|
||||||
use parser;
|
use parser;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
@ -1691,32 +1740,37 @@ pub mod tests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parser for DummyParser {
|
impl<'i> Parser<'i> for DummyParser {
|
||||||
type Impl = DummySelectorImpl;
|
type Impl = DummySelectorImpl;
|
||||||
|
type Error = ();
|
||||||
|
|
||||||
fn parse_non_ts_pseudo_class(&self, name: Cow<str>)
|
fn parse_non_ts_pseudo_class(&self, name: Cow<'i, str>)
|
||||||
-> Result<PseudoClass, ()> {
|
-> Result<PseudoClass,
|
||||||
|
ParseError<'i, SelectorParseError<'i, ()>>> {
|
||||||
match_ignore_ascii_case! { &name,
|
match_ignore_ascii_case! { &name,
|
||||||
"hover" => Ok(PseudoClass::Hover),
|
"hover" => Ok(PseudoClass::Hover),
|
||||||
"active" => Ok(PseudoClass::Active),
|
"active" => Ok(PseudoClass::Active),
|
||||||
_ => Err(())
|
_ => Err(SelectorParseError::Custom(()).into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_non_ts_functional_pseudo_class(&self, name: Cow<str>,
|
fn parse_non_ts_functional_pseudo_class<'t>(&self, name: Cow<'i, str>,
|
||||||
parser: &mut CssParser)
|
parser: &mut CssParser<'i, 't>)
|
||||||
-> Result<PseudoClass, ()> {
|
-> Result<PseudoClass,
|
||||||
|
ParseError<'i, SelectorParseError<'i, ()>>> {
|
||||||
match_ignore_ascii_case! { &name,
|
match_ignore_ascii_case! { &name,
|
||||||
"lang" => Ok(PseudoClass::Lang(try!(parser.expect_ident_or_string()).into_owned())),
|
"lang" => Ok(PseudoClass::Lang(try!(parser.expect_ident_or_string()).into_owned())),
|
||||||
_ => Err(())
|
_ => Err(SelectorParseError::Custom(()).into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_pseudo_element(&self, name: Cow<str>) -> Result<PseudoElement, ()> {
|
fn parse_pseudo_element(&self, name: Cow<'i, str>)
|
||||||
|
-> Result<PseudoElement,
|
||||||
|
ParseError<'i, SelectorParseError<'i, ()>>> {
|
||||||
match_ignore_ascii_case! { &name,
|
match_ignore_ascii_case! { &name,
|
||||||
"before" => Ok(PseudoElement::Before),
|
"before" => Ok(PseudoElement::Before),
|
||||||
"after" => Ok(PseudoElement::After),
|
"after" => Ok(PseudoElement::After),
|
||||||
_ => Err(())
|
_ => Err(SelectorParseError::Custom(()).into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1729,13 +1783,16 @@ pub mod tests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse(input: &str) -> Result<SelectorList<DummySelectorImpl>, ()> {
|
fn parse<'i>(input: &'i str) -> Result<SelectorList<DummySelectorImpl>,
|
||||||
|
ParseError<'i, SelectorParseError<'i, ()>>> {
|
||||||
parse_ns(input, &DummyParser::default())
|
parse_ns(input, &DummyParser::default())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_ns(input: &str, parser: &DummyParser)
|
fn parse_ns<'i>(input: &'i str, parser: &DummyParser)
|
||||||
-> Result<SelectorList<DummySelectorImpl>, ()> {
|
-> Result<SelectorList<DummySelectorImpl>,
|
||||||
let result = SelectorList::parse(parser, &mut CssParser::new(input));
|
ParseError<'i, SelectorParseError<'i, ()>>> {
|
||||||
|
let mut parser_input = ParserInput::new(input);
|
||||||
|
let result = SelectorList::parse(parser, &mut CssParser::new(&mut parser_input));
|
||||||
if let Ok(ref selectors) = result {
|
if let Ok(ref selectors) = result {
|
||||||
assert_eq!(selectors.0.len(), 1);
|
assert_eq!(selectors.0.len(), 1);
|
||||||
assert_eq!(selectors.0[0].selector.to_css_string(), input);
|
assert_eq!(selectors.0[0].selector.to_css_string(), input);
|
||||||
|
@ -1749,7 +1806,8 @@ pub mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_empty() {
|
fn test_empty() {
|
||||||
let list = SelectorList::parse(&DummyParser::default(), &mut CssParser::new(":empty"));
|
let mut input = ParserInput::new(":empty");
|
||||||
|
let list = SelectorList::parse(&DummyParser::default(), &mut CssParser::new(&mut input));
|
||||||
assert!(list.is_ok());
|
assert!(list.is_ok());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1758,9 +1816,9 @@ pub mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_parsing() {
|
fn test_parsing() {
|
||||||
assert_eq!(parse(""), Err(())) ;
|
assert!(parse("").is_err()) ;
|
||||||
assert_eq!(parse(":lang(4)"), Err(())) ;
|
assert!(parse(":lang(4)").is_err()) ;
|
||||||
assert_eq!(parse(":lang(en US)"), Err(())) ;
|
assert!(parse(":lang(en US)").is_err()) ;
|
||||||
assert_eq!(parse("EeÉ"), Ok(SelectorList::from_vec(vec!(
|
assert_eq!(parse("EeÉ"), Ok(SelectorList::from_vec(vec!(
|
||||||
Selector::from_vec(vec!(
|
Selector::from_vec(vec!(
|
||||||
Component::LocalName(LocalName {
|
Component::LocalName(LocalName {
|
||||||
|
@ -1846,7 +1904,7 @@ pub mod tests {
|
||||||
}
|
}
|
||||||
), specificity(0, 1, 0))
|
), specificity(0, 1, 0))
|
||||||
))));
|
))));
|
||||||
assert_eq!(parse_ns("svg|circle", &parser), Err(()));
|
assert!(parse_ns("svg|circle", &parser).is_err());
|
||||||
parser.ns_prefixes.insert(DummyAtom("svg".into()), DummyAtom(SVG.into()));
|
parser.ns_prefixes.insert(DummyAtom("svg".into()), DummyAtom(SVG.into()));
|
||||||
assert_eq!(parse_ns("svg|circle", &parser), Ok(SelectorList::from_vec(vec!(
|
assert_eq!(parse_ns("svg|circle", &parser), Ok(SelectorList::from_vec(vec!(
|
||||||
Selector::from_vec(vec!(
|
Selector::from_vec(vec!(
|
||||||
|
@ -1960,14 +2018,14 @@ pub mod tests {
|
||||||
Component::NonTSPseudoClass(PseudoClass::Hover),
|
Component::NonTSPseudoClass(PseudoClass::Hover),
|
||||||
), specificity(0, 2, 1) | HAS_PSEUDO_BIT)
|
), specificity(0, 2, 1) | HAS_PSEUDO_BIT)
|
||||||
))));
|
))));
|
||||||
assert_eq!(parse("::before:hover:active"), Err(()));
|
assert!(parse("::before:hover:active").is_err());
|
||||||
assert_eq!(parse("::before:hover .foo"), Err(()));
|
assert!(parse("::before:hover .foo").is_err());
|
||||||
assert_eq!(parse("::before .foo"), Err(()));
|
assert!(parse("::before .foo").is_err());
|
||||||
assert_eq!(parse("::before ~ bar"), Err(()));
|
assert!(parse("::before ~ bar").is_err());
|
||||||
assert_eq!(parse("::before:active"), Err(()));
|
assert!(parse("::before:active").is_err());
|
||||||
|
|
||||||
// https://github.com/servo/servo/issues/15335
|
// https://github.com/servo/servo/issues/15335
|
||||||
assert_eq!(parse(":: before"), Err(()));
|
assert!(parse(":: before").is_err());
|
||||||
assert_eq!(parse("div ::after"), Ok(SelectorList::from_vec(vec!(
|
assert_eq!(parse("div ::after"), Ok(SelectorList::from_vec(vec!(
|
||||||
Selector::from_vec(vec!(
|
Selector::from_vec(vec!(
|
||||||
Component::LocalName(LocalName {
|
Component::LocalName(LocalName {
|
||||||
|
@ -1986,8 +2044,8 @@ pub mod tests {
|
||||||
), (1 << 20) + (1 << 10) + (0 << 0))
|
), (1 << 20) + (1 << 10) + (0 << 0))
|
||||||
))));
|
))));
|
||||||
parser.default_ns = None;
|
parser.default_ns = None;
|
||||||
assert_eq!(parse(":not(#provel.old)"), Err(()));
|
assert!(parse(":not(#provel.old)").is_err());
|
||||||
assert_eq!(parse(":not(#provel > old)"), Err(()));
|
assert!(parse(":not(#provel > old)").is_err());
|
||||||
assert!(parse("table[rules]:not([rules = \"none\"]):not([rules = \"\"])").is_ok());
|
assert!(parse("table[rules]:not([rules = \"none\"]):not([rules = \"\"])").is_ok());
|
||||||
assert_eq!(parse(":not(#provel)"), Ok(SelectorList::from_vec(vec!(
|
assert_eq!(parse(":not(#provel)"), Ok(SelectorList::from_vec(vec!(
|
||||||
Selector::from_vec(vec!(Component::Negation(vec!(
|
Selector::from_vec(vec!(Component::Negation(vec!(
|
||||||
|
|
|
@ -38,7 +38,7 @@ bitflags = "0.7"
|
||||||
bit-vec = "0.4.3"
|
bit-vec = "0.4.3"
|
||||||
byteorder = "1.0"
|
byteorder = "1.0"
|
||||||
cfg-if = "0.1.0"
|
cfg-if = "0.1.0"
|
||||||
cssparser = "0.13.7"
|
cssparser = "0.14.0"
|
||||||
encoding = {version = "0.2", optional = true}
|
encoding = {version = "0.2", optional = true}
|
||||||
euclid = "0.13"
|
euclid = "0.13"
|
||||||
fnv = "1.0"
|
fnv = "1.0"
|
||||||
|
|
|
@ -8,21 +8,22 @@
|
||||||
|
|
||||||
use Atom;
|
use Atom;
|
||||||
use cssparser::{AtRuleParser, DeclarationListParser, DeclarationParser};
|
use cssparser::{AtRuleParser, DeclarationListParser, DeclarationParser};
|
||||||
use cssparser::{Parser, Token, serialize_identifier};
|
use cssparser::{Parser, Token, serialize_identifier, BasicParseError};
|
||||||
use error_reporting::ParseError;
|
use error_reporting::ContextualParseError;
|
||||||
#[cfg(feature = "gecko")] use gecko::rules::CounterStyleDescriptors;
|
#[cfg(feature = "gecko")] use gecko::rules::CounterStyleDescriptors;
|
||||||
#[cfg(feature = "gecko")] use gecko_bindings::structs::nsCSSCounterDesc;
|
#[cfg(feature = "gecko")] use gecko_bindings::structs::nsCSSCounterDesc;
|
||||||
use parser::{ParserContext, log_css_error, Parse};
|
use parser::{ParserContext, log_css_error, Parse};
|
||||||
|
use selectors::parser::SelectorParseError;
|
||||||
use shared_lock::{SharedRwLockReadGuard, ToCssWithGuard};
|
use shared_lock::{SharedRwLockReadGuard, ToCssWithGuard};
|
||||||
use std::ascii::AsciiExt;
|
use std::ascii::AsciiExt;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
use style_traits::{ToCss, OneOrMoreCommaSeparated};
|
use style_traits::{ToCss, OneOrMoreCommaSeparated, ParseError, StyleParseError};
|
||||||
use values::CustomIdent;
|
use values::CustomIdent;
|
||||||
|
|
||||||
/// Parse the prelude of an @counter-style rule
|
/// Parse the prelude of an @counter-style rule
|
||||||
pub fn parse_counter_style_name(input: &mut Parser) -> Result<CustomIdent, ()> {
|
pub fn parse_counter_style_name<'i, 't>(input: &mut Parser<'i, 't>) -> Result<CustomIdent, ParseError<'i>> {
|
||||||
macro_rules! predefined {
|
macro_rules! predefined {
|
||||||
($($name: expr,)+) => {
|
($($name: expr,)+) => {
|
||||||
{
|
{
|
||||||
|
@ -49,8 +50,8 @@ pub fn parse_counter_style_name(input: &mut Parser) -> Result<CustomIdent, ()> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse the body (inside `{}`) of an @counter-style rule
|
/// Parse the body (inside `{}`) of an @counter-style rule
|
||||||
pub fn parse_counter_style_body(name: CustomIdent, context: &ParserContext, input: &mut Parser)
|
pub fn parse_counter_style_body<'i, 't>(name: CustomIdent, context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
-> Result<CounterStyleRuleData, ()> {
|
-> Result<CounterStyleRuleData, ParseError<'i>> {
|
||||||
let start = input.position();
|
let start = input.position();
|
||||||
let mut rule = CounterStyleRuleData::empty(name);
|
let mut rule = CounterStyleRuleData::empty(name);
|
||||||
{
|
{
|
||||||
|
@ -60,9 +61,10 @@ pub fn parse_counter_style_body(name: CustomIdent, context: &ParserContext, inpu
|
||||||
};
|
};
|
||||||
let mut iter = DeclarationListParser::new(input, parser);
|
let mut iter = DeclarationListParser::new(input, parser);
|
||||||
while let Some(declaration) = iter.next() {
|
while let Some(declaration) = iter.next() {
|
||||||
if let Err(range) = declaration {
|
if let Err(err) = declaration {
|
||||||
let pos = range.start;
|
let pos = err.span.start;
|
||||||
let error = ParseError::UnsupportedViewportDescriptorDeclaration(iter.input.slice(range));
|
let error = ContextualParseError::UnsupportedCounterStyleDescriptorDeclaration(
|
||||||
|
iter.input.slice(err.span), err.error);
|
||||||
log_css_error(iter.input, pos, error, context);
|
log_css_error(iter.input, pos, error, context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -75,28 +77,28 @@ pub fn parse_counter_style_body(name: CustomIdent, context: &ParserContext, inpu
|
||||||
ref system @ System::Numeric
|
ref system @ System::Numeric
|
||||||
if rule.symbols.is_none() => {
|
if rule.symbols.is_none() => {
|
||||||
let system = system.to_css_string();
|
let system = system.to_css_string();
|
||||||
Some(ParseError::InvalidCounterStyleWithoutSymbols(system))
|
Some(ContextualParseError::InvalidCounterStyleWithoutSymbols(system))
|
||||||
}
|
}
|
||||||
ref system @ System::Alphabetic |
|
ref system @ System::Alphabetic |
|
||||||
ref system @ System::Numeric
|
ref system @ System::Numeric
|
||||||
if rule.symbols().unwrap().0.len() < 2 => {
|
if rule.symbols().unwrap().0.len() < 2 => {
|
||||||
let system = system.to_css_string();
|
let system = system.to_css_string();
|
||||||
Some(ParseError::InvalidCounterStyleNotEnoughSymbols(system))
|
Some(ContextualParseError::InvalidCounterStyleNotEnoughSymbols(system))
|
||||||
}
|
}
|
||||||
System::Additive if rule.additive_symbols.is_none() => {
|
System::Additive if rule.additive_symbols.is_none() => {
|
||||||
Some(ParseError::InvalidCounterStyleWithoutAdditiveSymbols)
|
Some(ContextualParseError::InvalidCounterStyleWithoutAdditiveSymbols)
|
||||||
}
|
}
|
||||||
System::Extends(_) if rule.symbols.is_some() => {
|
System::Extends(_) if rule.symbols.is_some() => {
|
||||||
Some(ParseError::InvalidCounterStyleExtendsWithSymbols)
|
Some(ContextualParseError::InvalidCounterStyleExtendsWithSymbols)
|
||||||
}
|
}
|
||||||
System::Extends(_) if rule.additive_symbols.is_some() => {
|
System::Extends(_) if rule.additive_symbols.is_some() => {
|
||||||
Some(ParseError::InvalidCounterStyleExtendsWithAdditiveSymbols)
|
Some(ContextualParseError::InvalidCounterStyleExtendsWithAdditiveSymbols)
|
||||||
}
|
}
|
||||||
_ => None
|
_ => None
|
||||||
};
|
};
|
||||||
if let Some(error) = error {
|
if let Some(error) = error {
|
||||||
log_css_error(input, start, error, context);
|
log_css_error(input, start, error, context);
|
||||||
Err(())
|
Err(StyleParseError::UnspecifiedError.into())
|
||||||
} else {
|
} else {
|
||||||
Ok(rule)
|
Ok(rule)
|
||||||
}
|
}
|
||||||
|
@ -108,9 +110,10 @@ struct CounterStyleRuleParser<'a, 'b: 'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Default methods reject all at rules.
|
/// Default methods reject all at rules.
|
||||||
impl<'a, 'b> AtRuleParser for CounterStyleRuleParser<'a, 'b> {
|
impl<'a, 'b, 'i> AtRuleParser<'i> for CounterStyleRuleParser<'a, 'b> {
|
||||||
type Prelude = ();
|
type Prelude = ();
|
||||||
type AtRule = ();
|
type AtRule = ();
|
||||||
|
type Error = SelectorParseError<'i, StyleParseError<'i>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! accessor {
|
macro_rules! accessor {
|
||||||
|
@ -177,11 +180,13 @@ macro_rules! counter_style_descriptors {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b> DeclarationParser for CounterStyleRuleParser<'a, 'b> {
|
impl<'a, 'b, 'i> DeclarationParser<'i> for CounterStyleRuleParser<'a, 'b> {
|
||||||
type Declaration = ();
|
type Declaration = ();
|
||||||
|
type Error = SelectorParseError<'i, StyleParseError<'i>>;
|
||||||
|
|
||||||
fn parse_value(&mut self, name: &str, input: &mut Parser) -> Result<(), ()> {
|
fn parse_value<'t>(&mut self, name: Cow<'i, str>, input: &mut Parser<'i, 't>)
|
||||||
match_ignore_ascii_case! { name,
|
-> Result<(), ParseError<'i>> {
|
||||||
|
match_ignore_ascii_case! { &*name,
|
||||||
$(
|
$(
|
||||||
$name => {
|
$name => {
|
||||||
// DeclarationParser also calls parse_entirely
|
// DeclarationParser also calls parse_entirely
|
||||||
|
@ -192,7 +197,7 @@ macro_rules! counter_style_descriptors {
|
||||||
self.rule.$ident = Some(value)
|
self.rule.$ident = Some(value)
|
||||||
}
|
}
|
||||||
)*
|
)*
|
||||||
_ => return Err(())
|
_ => return Err(SelectorParseError::UnexpectedIdent(name.clone()).into())
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -289,8 +294,9 @@ pub enum System {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for System {
|
impl Parse for System {
|
||||||
fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
match_ignore_ascii_case! { &input.expect_ident()?,
|
let ident = input.expect_ident()?;
|
||||||
|
(match_ignore_ascii_case! { &ident,
|
||||||
"cyclic" => Ok(System::Cyclic),
|
"cyclic" => Ok(System::Cyclic),
|
||||||
"numeric" => Ok(System::Numeric),
|
"numeric" => Ok(System::Numeric),
|
||||||
"alphabetic" => Ok(System::Alphabetic),
|
"alphabetic" => Ok(System::Alphabetic),
|
||||||
|
@ -305,7 +311,7 @@ impl Parse for System {
|
||||||
Ok(System::Extends(other))
|
Ok(System::Extends(other))
|
||||||
}
|
}
|
||||||
_ => Err(())
|
_ => Err(())
|
||||||
}
|
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -345,11 +351,12 @@ pub enum Symbol {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for Symbol {
|
impl Parse for Symbol {
|
||||||
fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
match input.next() {
|
match input.next() {
|
||||||
Ok(Token::QuotedString(s)) => Ok(Symbol::String(s.into_owned())),
|
Ok(Token::QuotedString(s)) => Ok(Symbol::String(s.into_owned())),
|
||||||
Ok(Token::Ident(s)) => Ok(Symbol::Ident(s.into_owned())),
|
Ok(Token::Ident(s)) => Ok(Symbol::Ident(s.into_owned())),
|
||||||
_ => Err(())
|
Ok(t) => Err(BasicParseError::UnexpectedToken(t).into()),
|
||||||
|
Err(e) => Err(e.into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -379,7 +386,7 @@ impl Symbol {
|
||||||
pub struct Negative(pub Symbol, pub Option<Symbol>);
|
pub struct Negative(pub Symbol, pub Option<Symbol>);
|
||||||
|
|
||||||
impl Parse for Negative {
|
impl Parse for Negative {
|
||||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
Ok(Negative(
|
Ok(Negative(
|
||||||
Symbol::parse(context, input)?,
|
Symbol::parse(context, input)?,
|
||||||
input.try(|input| Symbol::parse(context, input)).ok(),
|
input.try(|input| Symbol::parse(context, input)).ok(),
|
||||||
|
@ -405,7 +412,7 @@ impl ToCss for Negative {
|
||||||
pub struct Ranges(pub Vec<Range<Option<i32>>>);
|
pub struct Ranges(pub Vec<Range<Option<i32>>>);
|
||||||
|
|
||||||
impl Parse for Ranges {
|
impl Parse for Ranges {
|
||||||
fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
if input.try(|input| input.expect_ident_matching("auto")).is_ok() {
|
if input.try(|input| input.expect_ident_matching("auto")).is_ok() {
|
||||||
Ok(Ranges(Vec::new()))
|
Ok(Ranges(Vec::new()))
|
||||||
} else {
|
} else {
|
||||||
|
@ -414,7 +421,7 @@ impl Parse for Ranges {
|
||||||
let opt_end = parse_bound(input)?;
|
let opt_end = parse_bound(input)?;
|
||||||
if let (Some(start), Some(end)) = (opt_start, opt_end) {
|
if let (Some(start), Some(end)) = (opt_start, opt_end) {
|
||||||
if start > end {
|
if start > end {
|
||||||
return Err(())
|
return Err(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(opt_start..opt_end)
|
Ok(opt_start..opt_end)
|
||||||
|
@ -423,11 +430,12 @@ impl Parse for Ranges {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_bound(input: &mut Parser) -> Result<Option<i32>, ()> {
|
fn parse_bound<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Option<i32>, ParseError<'i>> {
|
||||||
match input.next() {
|
match input.next() {
|
||||||
Ok(Token::Number(ref v)) if v.int_value.is_some() => Ok(Some(v.int_value.unwrap())),
|
Ok(Token::Number(ref v)) if v.int_value.is_some() => Ok(Some(v.int_value.unwrap())),
|
||||||
Ok(Token::Ident(ref ident)) if ident.eq_ignore_ascii_case("infinite") => Ok(None),
|
Ok(Token::Ident(ref ident)) if ident.eq_ignore_ascii_case("infinite") => Ok(None),
|
||||||
_ => Err(())
|
Ok(t) => Err(BasicParseError::UnexpectedToken(t).into()),
|
||||||
|
Err(e) => Err(e.into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -467,13 +475,13 @@ fn bound_to_css<W>(range: Option<i32>, dest: &mut W) -> fmt::Result where W: fmt
|
||||||
pub struct Pad(pub u32, pub Symbol);
|
pub struct Pad(pub u32, pub Symbol);
|
||||||
|
|
||||||
impl Parse for Pad {
|
impl Parse for Pad {
|
||||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
let pad_with = input.try(|input| Symbol::parse(context, input));
|
let pad_with = input.try(|input| Symbol::parse(context, input));
|
||||||
let min_length = input.expect_integer()?;
|
let min_length = input.expect_integer()?;
|
||||||
if min_length < 0 {
|
if min_length < 0 {
|
||||||
return Err(())
|
return Err(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
let pad_with = pad_with.or_else(|()| Symbol::parse(context, input))?;
|
let pad_with = pad_with.or_else(|_| Symbol::parse(context, input))?;
|
||||||
Ok(Pad(min_length as u32, pad_with))
|
Ok(Pad(min_length as u32, pad_with))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -490,7 +498,7 @@ impl ToCss for Pad {
|
||||||
pub struct Fallback(pub CustomIdent);
|
pub struct Fallback(pub CustomIdent);
|
||||||
|
|
||||||
impl Parse for Fallback {
|
impl Parse for Fallback {
|
||||||
fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
parse_counter_style_name(input).map(Fallback)
|
parse_counter_style_name(input).map(Fallback)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -506,14 +514,14 @@ impl ToCss for Fallback {
|
||||||
pub struct Symbols(pub Vec<Symbol>);
|
pub struct Symbols(pub Vec<Symbol>);
|
||||||
|
|
||||||
impl Parse for Symbols {
|
impl Parse for Symbols {
|
||||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
let mut symbols = Vec::new();
|
let mut symbols = Vec::new();
|
||||||
loop {
|
loop {
|
||||||
if let Ok(s) = input.try(|input| Symbol::parse(context, input)) {
|
if let Ok(s) = input.try(|input| Symbol::parse(context, input)) {
|
||||||
symbols.push(s)
|
symbols.push(s)
|
||||||
} else {
|
} else {
|
||||||
if symbols.is_empty() {
|
if symbols.is_empty() {
|
||||||
return Err(())
|
return Err(StyleParseError::UnspecifiedError.into())
|
||||||
} else {
|
} else {
|
||||||
return Ok(Symbols(symbols))
|
return Ok(Symbols(symbols))
|
||||||
}
|
}
|
||||||
|
@ -540,11 +548,11 @@ impl ToCss for Symbols {
|
||||||
pub struct AdditiveSymbols(pub Vec<AdditiveTuple>);
|
pub struct AdditiveSymbols(pub Vec<AdditiveTuple>);
|
||||||
|
|
||||||
impl Parse for AdditiveSymbols {
|
impl Parse for AdditiveSymbols {
|
||||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
let tuples = Vec::<AdditiveTuple>::parse(context, input)?;
|
let tuples = Vec::<AdditiveTuple>::parse(context, input)?;
|
||||||
// FIXME maybe? https://github.com/w3c/csswg-drafts/issues/1220
|
// FIXME maybe? https://github.com/w3c/csswg-drafts/issues/1220
|
||||||
if tuples.windows(2).any(|window| window[0].weight <= window[1].weight) {
|
if tuples.windows(2).any(|window| window[0].weight <= window[1].weight) {
|
||||||
return Err(())
|
return Err(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
Ok(AdditiveSymbols(tuples))
|
Ok(AdditiveSymbols(tuples))
|
||||||
}
|
}
|
||||||
|
@ -568,13 +576,13 @@ pub struct AdditiveTuple {
|
||||||
impl OneOrMoreCommaSeparated for AdditiveTuple {}
|
impl OneOrMoreCommaSeparated for AdditiveTuple {}
|
||||||
|
|
||||||
impl Parse for AdditiveTuple {
|
impl Parse for AdditiveTuple {
|
||||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
let symbol = input.try(|input| Symbol::parse(context, input));
|
let symbol = input.try(|input| Symbol::parse(context, input));
|
||||||
let weight = input.expect_integer()?;
|
let weight = input.expect_integer()?;
|
||||||
if weight < 0 {
|
if weight < 0 {
|
||||||
return Err(())
|
return Err(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
let symbol = symbol.or_else(|()| Symbol::parse(context, input))?;
|
let symbol = symbol.or_else(|_| Symbol::parse(context, input))?;
|
||||||
Ok(AdditiveTuple {
|
Ok(AdditiveTuple {
|
||||||
weight: weight as u32,
|
weight: weight as u32,
|
||||||
symbol: symbol,
|
symbol: symbol,
|
||||||
|
@ -607,10 +615,11 @@ pub enum SpeakAs {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for SpeakAs {
|
impl Parse for SpeakAs {
|
||||||
fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
let mut is_spell_out = false;
|
let mut is_spell_out = false;
|
||||||
let result = input.try(|input| {
|
let result: Result<_, ParseError> = input.try(|input| {
|
||||||
match_ignore_ascii_case! { &input.expect_ident()?,
|
let ident = input.expect_ident()?;
|
||||||
|
(match_ignore_ascii_case! { &ident,
|
||||||
"auto" => Ok(SpeakAs::Auto),
|
"auto" => Ok(SpeakAs::Auto),
|
||||||
"bullets" => Ok(SpeakAs::Bullets),
|
"bullets" => Ok(SpeakAs::Bullets),
|
||||||
"numbers" => Ok(SpeakAs::Numbers),
|
"numbers" => Ok(SpeakAs::Numbers),
|
||||||
|
@ -620,14 +629,14 @@ impl Parse for SpeakAs {
|
||||||
Err(())
|
Err(())
|
||||||
}
|
}
|
||||||
_ => Err(())
|
_ => Err(())
|
||||||
}
|
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
|
||||||
});
|
});
|
||||||
if is_spell_out {
|
if is_spell_out {
|
||||||
// spell-out is not supported, but don’t parse it as a <counter-style-name>.
|
// spell-out is not supported, but don’t parse it as a <counter-style-name>.
|
||||||
// See bug 1024178.
|
// See bug 1024178.
|
||||||
return Err(())
|
return Err(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
result.or_else(|()| {
|
result.or_else(|_| {
|
||||||
Ok(SpeakAs::Other(parse_counter_style_name(input)?))
|
Ok(SpeakAs::Other(parse_counter_style_name(input)?))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,14 +7,15 @@
|
||||||
//! [custom]: https://drafts.csswg.org/css-variables/
|
//! [custom]: https://drafts.csswg.org/css-variables/
|
||||||
|
|
||||||
use Atom;
|
use Atom;
|
||||||
use cssparser::{Delimiter, Parser, SourcePosition, Token, TokenSerializationType};
|
use cssparser::{Delimiter, Parser, ParserInput, SourcePosition, Token, TokenSerializationType};
|
||||||
use parser::ParserContext;
|
use parser::ParserContext;
|
||||||
use properties::{CSSWideKeyword, DeclaredValue};
|
use properties::{CSSWideKeyword, DeclaredValue};
|
||||||
|
use selectors::parser::SelectorParseError;
|
||||||
use std::ascii::AsciiExt;
|
use std::ascii::AsciiExt;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use style_traits::{HasViewportPercentage, ToCss};
|
use style_traits::{HasViewportPercentage, ToCss, StyleParseError, ParseError};
|
||||||
use stylearc::Arc;
|
use stylearc::Arc;
|
||||||
|
|
||||||
/// A custom property name is just an `Atom`.
|
/// A custom property name is just an `Atom`.
|
||||||
|
@ -131,7 +132,8 @@ impl ComputedValue {
|
||||||
|
|
||||||
impl SpecifiedValue {
|
impl SpecifiedValue {
|
||||||
/// Parse a custom property SpecifiedValue.
|
/// Parse a custom property SpecifiedValue.
|
||||||
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Box<Self>, ()> {
|
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<Box<Self>, ParseError<'i>> {
|
||||||
let mut references = Some(HashSet::new());
|
let mut references = Some(HashSet::new());
|
||||||
let (first, css, last) = try!(parse_self_contained_declaration_value(input, &mut references));
|
let (first, css, last) = try!(parse_self_contained_declaration_value(input, &mut references));
|
||||||
Ok(Box::new(SpecifiedValue {
|
Ok(Box::new(SpecifiedValue {
|
||||||
|
@ -146,7 +148,7 @@ impl SpecifiedValue {
|
||||||
/// Parse the value of a non-custom property that contains `var()` references.
|
/// Parse the value of a non-custom property that contains `var()` references.
|
||||||
pub fn parse_non_custom_with_var<'i, 't>
|
pub fn parse_non_custom_with_var<'i, 't>
|
||||||
(input: &mut Parser<'i, 't>)
|
(input: &mut Parser<'i, 't>)
|
||||||
-> Result<(TokenSerializationType, Cow<'i, str>), ()> {
|
-> Result<(TokenSerializationType, Cow<'i, str>), ParseError<'i>> {
|
||||||
let (first_token_type, css, _) = try!(parse_self_contained_declaration_value(input, &mut None));
|
let (first_token_type, css, _) = try!(parse_self_contained_declaration_value(input, &mut None));
|
||||||
Ok((first_token_type, css))
|
Ok((first_token_type, css))
|
||||||
}
|
}
|
||||||
|
@ -158,7 +160,7 @@ fn parse_self_contained_declaration_value<'i, 't>
|
||||||
TokenSerializationType,
|
TokenSerializationType,
|
||||||
Cow<'i, str>,
|
Cow<'i, str>,
|
||||||
TokenSerializationType
|
TokenSerializationType
|
||||||
), ()> {
|
), ParseError<'i>> {
|
||||||
let start_position = input.position();
|
let start_position = input.position();
|
||||||
let mut missing_closing_characters = String::new();
|
let mut missing_closing_characters = String::new();
|
||||||
let (first, last) = try!(
|
let (first, last) = try!(
|
||||||
|
@ -179,7 +181,7 @@ fn parse_declaration_value<'i, 't>
|
||||||
(input: &mut Parser<'i, 't>,
|
(input: &mut Parser<'i, 't>,
|
||||||
references: &mut Option<HashSet<Name>>,
|
references: &mut Option<HashSet<Name>>,
|
||||||
missing_closing_characters: &mut String)
|
missing_closing_characters: &mut String)
|
||||||
-> Result<(TokenSerializationType, TokenSerializationType), ()> {
|
-> Result<(TokenSerializationType, TokenSerializationType), ParseError<'i>> {
|
||||||
input.parse_until_before(Delimiter::Bang | Delimiter::Semicolon, |input| {
|
input.parse_until_before(Delimiter::Bang | Delimiter::Semicolon, |input| {
|
||||||
// Need at least one token
|
// Need at least one token
|
||||||
let start_position = input.position();
|
let start_position = input.position();
|
||||||
|
@ -192,14 +194,16 @@ fn parse_declaration_value<'i, 't>
|
||||||
|
|
||||||
/// Like parse_declaration_value, but accept `!` and `;` since they are only
|
/// Like parse_declaration_value, but accept `!` and `;` since they are only
|
||||||
/// invalid at the top level
|
/// invalid at the top level
|
||||||
fn parse_declaration_value_block(input: &mut Parser,
|
fn parse_declaration_value_block<'i, 't>
|
||||||
|
(input: &mut Parser<'i, 't>,
|
||||||
references: &mut Option<HashSet<Name>>,
|
references: &mut Option<HashSet<Name>>,
|
||||||
missing_closing_characters: &mut String)
|
missing_closing_characters: &mut String)
|
||||||
-> Result<(TokenSerializationType, TokenSerializationType), ()> {
|
-> Result<(TokenSerializationType, TokenSerializationType),
|
||||||
|
ParseError<'i>> {
|
||||||
let mut token_start = input.position();
|
let mut token_start = input.position();
|
||||||
let mut token = match input.next_including_whitespace_and_comments() {
|
let mut token = match input.next_including_whitespace_and_comments() {
|
||||||
Ok(token) => token,
|
Ok(token) => token,
|
||||||
Err(()) => return Ok((TokenSerializationType::nothing(), TokenSerializationType::nothing()))
|
Err(_) => return Ok((TokenSerializationType::nothing(), TokenSerializationType::nothing()))
|
||||||
};
|
};
|
||||||
let first_token_type = token.serialization_type();
|
let first_token_type = token.serialization_type();
|
||||||
loop {
|
loop {
|
||||||
|
@ -226,13 +230,16 @@ fn parse_declaration_value_block(input: &mut Parser,
|
||||||
}
|
}
|
||||||
token.serialization_type()
|
token.serialization_type()
|
||||||
}
|
}
|
||||||
Token::BadUrl |
|
Token::BadUrl =>
|
||||||
Token::BadString |
|
return Err(StyleParseError::BadUrlInDeclarationValueBlock.into()),
|
||||||
Token::CloseParenthesis |
|
Token::BadString =>
|
||||||
Token::CloseSquareBracket |
|
return Err(StyleParseError::BadStringInDeclarationValueBlock.into()),
|
||||||
Token::CloseCurlyBracket => {
|
Token::CloseParenthesis =>
|
||||||
return Err(())
|
return Err(StyleParseError::UnbalancedCloseParenthesisInDeclarationValueBlock.into()),
|
||||||
}
|
Token::CloseSquareBracket =>
|
||||||
|
return Err(StyleParseError::UnbalancedCloseSquareBracketInDeclarationValueBlock.into()),
|
||||||
|
Token::CloseCurlyBracket =>
|
||||||
|
return Err(StyleParseError::UnbalancedCloseCurlyBracketInDeclarationValueBlock.into()),
|
||||||
Token::Function(ref name) => {
|
Token::Function(ref name) => {
|
||||||
if name.eq_ignore_ascii_case("var") {
|
if name.eq_ignore_ascii_case("var") {
|
||||||
let position = input.position();
|
let position = input.position();
|
||||||
|
@ -303,9 +310,12 @@ fn parse_declaration_value_block(input: &mut Parser,
|
||||||
// If the var function is valid, return Ok((custom_property_name, fallback))
|
// If the var function is valid, return Ok((custom_property_name, fallback))
|
||||||
fn parse_var_function<'i, 't>(input: &mut Parser<'i, 't>,
|
fn parse_var_function<'i, 't>(input: &mut Parser<'i, 't>,
|
||||||
references: &mut Option<HashSet<Name>>)
|
references: &mut Option<HashSet<Name>>)
|
||||||
-> Result<(), ()> {
|
-> Result<(), ParseError<'i>> {
|
||||||
let name = try!(input.expect_ident());
|
let name = try!(input.expect_ident());
|
||||||
let name = try!(parse_name(&name));
|
let name: Result<_, ParseError> =
|
||||||
|
parse_name(&name)
|
||||||
|
.map_err(|()| SelectorParseError::UnexpectedIdent(name.clone()).into());
|
||||||
|
let name = try!(name);
|
||||||
if input.try(|input| input.expect_comma()).is_ok() {
|
if input.try(|input| input.expect_comma()).is_ok() {
|
||||||
// Exclude `!` and `;` at the top level
|
// Exclude `!` and `;` at the top level
|
||||||
// https://drafts.csswg.org/css-syntax/#typedef-declaration-value
|
// https://drafts.csswg.org/css-syntax/#typedef-declaration-value
|
||||||
|
@ -474,7 +484,8 @@ fn substitute_one(name: &Name,
|
||||||
}
|
}
|
||||||
let computed_value = if specified_value.references.map(|set| set.is_empty()) == Some(false) {
|
let computed_value = if specified_value.references.map(|set| set.is_empty()) == Some(false) {
|
||||||
let mut partial_computed_value = ComputedValue::empty();
|
let mut partial_computed_value = ComputedValue::empty();
|
||||||
let mut input = Parser::new(&specified_value.css);
|
let mut input = ParserInput::new(&specified_value.css);
|
||||||
|
let mut input = Parser::new(&mut input);
|
||||||
let mut position = (input.position(), specified_value.first_token_type);
|
let mut position = (input.position(), specified_value.first_token_type);
|
||||||
let result = substitute_block(
|
let result = substitute_block(
|
||||||
&mut input, &mut position, &mut partial_computed_value,
|
&mut input, &mut position, &mut partial_computed_value,
|
||||||
|
@ -525,11 +536,11 @@ fn substitute_one(name: &Name,
|
||||||
///
|
///
|
||||||
/// Return `Err(())` if `input` is invalid at computed-value time.
|
/// Return `Err(())` if `input` is invalid at computed-value time.
|
||||||
/// or `Ok(last_token_type that was pushed to partial_computed_value)` otherwise.
|
/// or `Ok(last_token_type that was pushed to partial_computed_value)` otherwise.
|
||||||
fn substitute_block<F>(input: &mut Parser,
|
fn substitute_block<'i, 't, F>(input: &mut Parser<'i, 't>,
|
||||||
position: &mut (SourcePosition, TokenSerializationType),
|
position: &mut (SourcePosition, TokenSerializationType),
|
||||||
partial_computed_value: &mut ComputedValue,
|
partial_computed_value: &mut ComputedValue,
|
||||||
substitute_one: &mut F)
|
substitute_one: &mut F)
|
||||||
-> Result<TokenSerializationType, ()>
|
-> Result<TokenSerializationType, ParseError<'i>>
|
||||||
where F: FnMut(&Name, &mut ComputedValue) -> Result<TokenSerializationType, ()> {
|
where F: FnMut(&Name, &mut ComputedValue) -> Result<TokenSerializationType, ()> {
|
||||||
let mut last_token_type = TokenSerializationType::nothing();
|
let mut last_token_type = TokenSerializationType::nothing();
|
||||||
let mut set_position_at_next_iteration = false;
|
let mut set_position_at_next_iteration = false;
|
||||||
|
@ -539,7 +550,7 @@ fn substitute_block<F>(input: &mut Parser,
|
||||||
if set_position_at_next_iteration {
|
if set_position_at_next_iteration {
|
||||||
*position = (before_this_token, match next {
|
*position = (before_this_token, match next {
|
||||||
Ok(ref token) => token.serialization_type(),
|
Ok(ref token) => token.serialization_type(),
|
||||||
Err(()) => TokenSerializationType::nothing(),
|
Err(_) => TokenSerializationType::nothing(),
|
||||||
});
|
});
|
||||||
set_position_at_next_iteration = false;
|
set_position_at_next_iteration = false;
|
||||||
}
|
}
|
||||||
|
@ -605,11 +616,12 @@ fn substitute_block<F>(input: &mut Parser,
|
||||||
|
|
||||||
/// Replace `var()` functions for a non-custom property.
|
/// Replace `var()` functions for a non-custom property.
|
||||||
/// Return `Err(())` for invalid at computed time.
|
/// Return `Err(())` for invalid at computed time.
|
||||||
pub fn substitute(input: &str, first_token_type: TokenSerializationType,
|
pub fn substitute<'i>(input: &'i str, first_token_type: TokenSerializationType,
|
||||||
computed_values_map: &Option<Arc<HashMap<Name, ComputedValue>>>)
|
computed_values_map: &Option<Arc<HashMap<Name, ComputedValue>>>)
|
||||||
-> Result<String, ()> {
|
-> Result<String, ParseError<'i>> {
|
||||||
let mut substituted = ComputedValue::empty();
|
let mut substituted = ComputedValue::empty();
|
||||||
let mut input = Parser::new(input);
|
let mut input = ParserInput::new(input);
|
||||||
|
let mut input = Parser::new(&mut input);
|
||||||
let mut position = (input.position(), first_token_type);
|
let mut position = (input.position(), first_token_type);
|
||||||
let last_token_type = try!(substitute_block(
|
let last_token_type = try!(substitute_block(
|
||||||
&mut input, &mut position, &mut substituted, &mut |name, substituted| {
|
&mut input, &mut position, &mut substituted, &mut |name, substituted| {
|
||||||
|
|
|
@ -6,28 +6,30 @@
|
||||||
|
|
||||||
#![deny(missing_docs)]
|
#![deny(missing_docs)]
|
||||||
|
|
||||||
use cssparser::{Parser, SourcePosition};
|
use cssparser::{Parser, SourcePosition, BasicParseError, Token, NumericValue, PercentageValue};
|
||||||
|
use cssparser::ParseError as CssParseError;
|
||||||
use log;
|
use log;
|
||||||
|
use style_traits::ParseError;
|
||||||
use stylesheets::UrlExtraData;
|
use stylesheets::UrlExtraData;
|
||||||
|
|
||||||
/// Errors that can be encountered while parsing CSS.
|
/// Errors that can be encountered while parsing CSS.
|
||||||
pub enum ParseError<'a> {
|
pub enum ContextualParseError<'a> {
|
||||||
/// A property declaration was not recognized.
|
/// A property declaration was not recognized.
|
||||||
UnsupportedPropertyDeclaration(&'a str),
|
UnsupportedPropertyDeclaration(&'a str, ParseError<'a>),
|
||||||
/// A font face descriptor was not recognized.
|
/// A font face descriptor was not recognized.
|
||||||
UnsupportedFontFaceDescriptor(&'a str),
|
UnsupportedFontFaceDescriptor(&'a str, ParseError<'a>),
|
||||||
/// A keyframe rule was not valid.
|
/// A keyframe rule was not valid.
|
||||||
InvalidKeyframeRule(&'a str),
|
InvalidKeyframeRule(&'a str, ParseError<'a>),
|
||||||
/// A keyframe property declaration was not recognized.
|
/// A keyframe property declaration was not recognized.
|
||||||
UnsupportedKeyframePropertyDeclaration(&'a str),
|
UnsupportedKeyframePropertyDeclaration(&'a str, ParseError<'a>),
|
||||||
/// A rule was invalid for some reason.
|
/// A rule was invalid for some reason.
|
||||||
InvalidRule(&'a str),
|
InvalidRule(&'a str, ParseError<'a>),
|
||||||
/// A rule was not recognized.
|
/// A rule was not recognized.
|
||||||
UnsupportedRule(&'a str),
|
UnsupportedRule(&'a str, ParseError<'a>),
|
||||||
/// A viewport descriptor declaration was not recognized.
|
/// A viewport descriptor declaration was not recognized.
|
||||||
UnsupportedViewportDescriptorDeclaration(&'a str),
|
UnsupportedViewportDescriptorDeclaration(&'a str, ParseError<'a>),
|
||||||
/// A counter style descriptor declaration was not recognized.
|
/// A counter style descriptor declaration was not recognized.
|
||||||
UnsupportedCounterStyleDescriptorDeclaration(&'a str),
|
UnsupportedCounterStyleDescriptorDeclaration(&'a str, ParseError<'a>),
|
||||||
/// A counter style rule had no symbols.
|
/// A counter style rule had no symbols.
|
||||||
InvalidCounterStyleWithoutSymbols(String),
|
InvalidCounterStyleWithoutSymbols(String),
|
||||||
/// A counter style rule had less than two symbols.
|
/// A counter style rule had less than two symbols.
|
||||||
|
@ -40,35 +42,97 @@ pub enum ParseError<'a> {
|
||||||
InvalidCounterStyleExtendsWithAdditiveSymbols
|
InvalidCounterStyleExtendsWithAdditiveSymbols
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ParseError<'a> {
|
impl<'a> ContextualParseError<'a> {
|
||||||
/// Turn a parse error into a string representation.
|
/// Turn a parse error into a string representation.
|
||||||
pub fn to_string(&self) -> String {
|
pub fn to_string(&self) -> String {
|
||||||
|
fn token_to_str(t: &Token) -> String {
|
||||||
|
match *t {
|
||||||
|
Token::Ident(ref i) => format!("identifier {}", i),
|
||||||
|
Token::AtKeyword(ref kw) => format!("keyword @{}", kw),
|
||||||
|
Token::Hash(ref h) => format!("hash #{}", h),
|
||||||
|
Token::IDHash(ref h) => format!("id selector #{}", h),
|
||||||
|
Token::QuotedString(ref s) => format!("quoted string \"{}\"", s),
|
||||||
|
Token::UnquotedUrl(ref u) => format!("url {}", u),
|
||||||
|
Token::Delim(ref d) => format!("delimiter {}", d),
|
||||||
|
Token::Number(NumericValue { int_value: Some(i), .. }) => format!("number {}", i),
|
||||||
|
Token::Number(ref n) => format!("number {}", n.value),
|
||||||
|
Token::Percentage(PercentageValue { int_value: Some(i), .. }) => format!("percentage {}", i),
|
||||||
|
Token::Percentage(ref p) => format!("percentage {}", p.unit_value),
|
||||||
|
Token::Dimension(_, ref d) => format!("dimension {}", d),
|
||||||
|
Token::WhiteSpace(_) => format!("whitespace"),
|
||||||
|
Token::Comment(_) => format!("comment"),
|
||||||
|
Token::Colon => format!("colon (:)"),
|
||||||
|
Token::Semicolon => format!("semicolon (;)"),
|
||||||
|
Token::Comma => format!("comma (,)"),
|
||||||
|
Token::IncludeMatch => format!("include match (~=)"),
|
||||||
|
Token::DashMatch => format!("dash match (|=)"),
|
||||||
|
Token::PrefixMatch => format!("prefix match (^=)"),
|
||||||
|
Token::SuffixMatch => format!("suffix match ($=)"),
|
||||||
|
Token::SubstringMatch => format!("substring match (*=)"),
|
||||||
|
Token::Column => format!("column (||)"),
|
||||||
|
Token::CDO => format!("CDO (<!--)"),
|
||||||
|
Token::CDC => format!("CDC (-->)"),
|
||||||
|
Token::Function(ref f) => format!("function {}", f),
|
||||||
|
Token::ParenthesisBlock => format!("parenthesis ("),
|
||||||
|
Token::SquareBracketBlock => format!("square bracket ["),
|
||||||
|
Token::CurlyBracketBlock => format!("curly bracket {{"),
|
||||||
|
Token::BadUrl => format!("bad url parse error"),
|
||||||
|
Token::BadString => format!("bad string parse error"),
|
||||||
|
Token::CloseParenthesis => format!("unmatched close parenthesis"),
|
||||||
|
Token::CloseSquareBracket => format!("unmatched close square bracket"),
|
||||||
|
Token::CloseCurlyBracket => format!("unmatched close curly bracket"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_error_to_str(err: &ParseError) -> String {
|
||||||
|
match *err {
|
||||||
|
CssParseError::Basic(BasicParseError::UnexpectedToken(ref t)) =>
|
||||||
|
format!("found unexpected {}", token_to_str(t)),
|
||||||
|
CssParseError::Basic(BasicParseError::ExpectedToken(ref t)) =>
|
||||||
|
format!("expected {}", token_to_str(t)),
|
||||||
|
CssParseError::Basic(BasicParseError::EndOfInput) =>
|
||||||
|
format!("unexpected end of input"),
|
||||||
|
CssParseError::Basic(BasicParseError::AtRuleInvalid) =>
|
||||||
|
format!("@ rule invalid"),
|
||||||
|
CssParseError::Basic(BasicParseError::QualifiedRuleInvalid) =>
|
||||||
|
format!("qualified rule invalid"),
|
||||||
|
CssParseError::Custom(ref err) =>
|
||||||
|
format!("{:?}", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
match *self {
|
match *self {
|
||||||
ParseError::UnsupportedPropertyDeclaration(decl) =>
|
ContextualParseError::UnsupportedPropertyDeclaration(decl, ref err) =>
|
||||||
format!("Unsupported property declaration: '{}'", decl),
|
format!("Unsupported property declaration: '{}', {}", decl,
|
||||||
ParseError::UnsupportedFontFaceDescriptor(decl) =>
|
parse_error_to_str(err)),
|
||||||
format!("Unsupported @font-face descriptor declaration: '{}'", decl),
|
ContextualParseError::UnsupportedFontFaceDescriptor(decl, ref err) =>
|
||||||
ParseError::InvalidKeyframeRule(rule) =>
|
format!("Unsupported @font-face descriptor declaration: '{}', {}", decl,
|
||||||
format!("Invalid keyframe rule: '{}'", rule),
|
parse_error_to_str(err)),
|
||||||
ParseError::UnsupportedKeyframePropertyDeclaration(decl) =>
|
ContextualParseError::InvalidKeyframeRule(rule, ref err) =>
|
||||||
format!("Unsupported keyframe property declaration: '{}'", decl),
|
format!("Invalid keyframe rule: '{}', {}", rule,
|
||||||
ParseError::InvalidRule(rule) =>
|
parse_error_to_str(err)),
|
||||||
format!("Invalid rule: '{}'", rule),
|
ContextualParseError::UnsupportedKeyframePropertyDeclaration(decl, ref err) =>
|
||||||
ParseError::UnsupportedRule(rule) =>
|
format!("Unsupported keyframe property declaration: '{}', {}", decl,
|
||||||
format!("Unsupported rule: '{}'", rule),
|
parse_error_to_str(err)),
|
||||||
ParseError::UnsupportedViewportDescriptorDeclaration(decl) =>
|
ContextualParseError::InvalidRule(rule, ref err) =>
|
||||||
format!("Unsupported @viewport descriptor declaration: '{}'", decl),
|
format!("Invalid rule: '{}', {}", rule, parse_error_to_str(err)),
|
||||||
ParseError::UnsupportedCounterStyleDescriptorDeclaration(decl) =>
|
ContextualParseError::UnsupportedRule(rule, ref err) =>
|
||||||
format!("Unsupported @counter-style descriptor declaration: '{}'", decl),
|
format!("Unsupported rule: '{}', {}", rule, parse_error_to_str(err)),
|
||||||
ParseError::InvalidCounterStyleWithoutSymbols(ref system) =>
|
ContextualParseError::UnsupportedViewportDescriptorDeclaration(decl, ref err) =>
|
||||||
|
format!("Unsupported @viewport descriptor declaration: '{}', {}", decl,
|
||||||
|
parse_error_to_str(err)),
|
||||||
|
ContextualParseError::UnsupportedCounterStyleDescriptorDeclaration(decl, ref err) =>
|
||||||
|
format!("Unsupported @counter-style descriptor declaration: '{}', {}", decl,
|
||||||
|
parse_error_to_str(err)),
|
||||||
|
ContextualParseError::InvalidCounterStyleWithoutSymbols(ref system) =>
|
||||||
format!("Invalid @counter-style rule: 'system: {}' without 'symbols'", system),
|
format!("Invalid @counter-style rule: 'system: {}' without 'symbols'", system),
|
||||||
ParseError::InvalidCounterStyleNotEnoughSymbols(ref system) =>
|
ContextualParseError::InvalidCounterStyleNotEnoughSymbols(ref system) =>
|
||||||
format!("Invalid @counter-style rule: 'system: {}' less than two 'symbols'", system),
|
format!("Invalid @counter-style rule: 'system: {}' less than two 'symbols'", system),
|
||||||
ParseError::InvalidCounterStyleWithoutAdditiveSymbols =>
|
ContextualParseError::InvalidCounterStyleWithoutAdditiveSymbols =>
|
||||||
"Invalid @counter-style rule: 'system: additive' without 'additive-symbols'".into(),
|
"Invalid @counter-style rule: 'system: additive' without 'additive-symbols'".into(),
|
||||||
ParseError::InvalidCounterStyleExtendsWithSymbols =>
|
ContextualParseError::InvalidCounterStyleExtendsWithSymbols =>
|
||||||
"Invalid @counter-style rule: 'system: extends …' with 'symbols'".into(),
|
"Invalid @counter-style rule: 'system: extends …' with 'symbols'".into(),
|
||||||
ParseError::InvalidCounterStyleExtendsWithAdditiveSymbols =>
|
ContextualParseError::InvalidCounterStyleExtendsWithAdditiveSymbols =>
|
||||||
"Invalid @counter-style rule: 'system: extends …' with 'additive-symbols'".into(),
|
"Invalid @counter-style rule: 'system: extends …' with 'additive-symbols'".into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -83,7 +147,7 @@ pub trait ParseErrorReporter : Sync {
|
||||||
fn report_error<'a>(&self,
|
fn report_error<'a>(&self,
|
||||||
input: &mut Parser,
|
input: &mut Parser,
|
||||||
position: SourcePosition,
|
position: SourcePosition,
|
||||||
error: ParseError<'a>,
|
error: ContextualParseError<'a>,
|
||||||
url: &UrlExtraData,
|
url: &UrlExtraData,
|
||||||
line_number_offset: u64);
|
line_number_offset: u64);
|
||||||
}
|
}
|
||||||
|
@ -100,7 +164,7 @@ impl ParseErrorReporter for RustLogReporter {
|
||||||
fn report_error<'a>(&self,
|
fn report_error<'a>(&self,
|
||||||
input: &mut Parser,
|
input: &mut Parser,
|
||||||
position: SourcePosition,
|
position: SourcePosition,
|
||||||
error: ParseError<'a>,
|
error: ContextualParseError<'a>,
|
||||||
url: &UrlExtraData,
|
url: &UrlExtraData,
|
||||||
line_number_offset: u64) {
|
line_number_offset: u64) {
|
||||||
if log_enabled!(log::LogLevel::Info) {
|
if log_enabled!(log::LogLevel::Info) {
|
||||||
|
@ -118,21 +182,14 @@ impl ParseErrorReporter for NullReporter {
|
||||||
fn report_error<'a>(&self,
|
fn report_error<'a>(&self,
|
||||||
_: &mut Parser,
|
_: &mut Parser,
|
||||||
_: SourcePosition,
|
_: SourcePosition,
|
||||||
_: ParseError<'a>,
|
_: ContextualParseError<'a>,
|
||||||
_: &UrlExtraData,
|
_: &UrlExtraData,
|
||||||
_: u64) {
|
_: u64) {
|
||||||
// do nothing
|
// do nothing
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create an instance of the default error reporter for Servo.
|
/// Create an instance of the default error reporter.
|
||||||
#[cfg(feature = "servo")]
|
|
||||||
pub fn create_error_reporter() -> RustLogReporter {
|
|
||||||
RustLogReporter
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create an instance of the default error reporter for Stylo.
|
|
||||||
#[cfg(feature = "gecko")]
|
|
||||||
pub fn create_error_reporter() -> RustLogReporter {
|
pub fn create_error_reporter() -> RustLogReporter {
|
||||||
RustLogReporter
|
RustLogReporter
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,13 +13,15 @@ use computed_values::{font_feature_settings, font_stretch, font_style, font_weig
|
||||||
use computed_values::font_family::FamilyName;
|
use computed_values::font_family::FamilyName;
|
||||||
use cssparser::{AtRuleParser, DeclarationListParser, DeclarationParser, Parser};
|
use cssparser::{AtRuleParser, DeclarationListParser, DeclarationParser, Parser};
|
||||||
use cssparser::SourceLocation;
|
use cssparser::SourceLocation;
|
||||||
use error_reporting::ParseError;
|
use error_reporting::ContextualParseError;
|
||||||
#[cfg(feature = "gecko")] use gecko_bindings::structs::CSSFontFaceDescriptors;
|
#[cfg(feature = "gecko")] use gecko_bindings::structs::CSSFontFaceDescriptors;
|
||||||
#[cfg(feature = "gecko")] use cssparser::UnicodeRange;
|
#[cfg(feature = "gecko")] use cssparser::UnicodeRange;
|
||||||
use parser::{ParserContext, log_css_error, Parse};
|
use parser::{ParserContext, log_css_error, Parse};
|
||||||
|
use selectors::parser::SelectorParseError;
|
||||||
use shared_lock::{SharedRwLockReadGuard, ToCssWithGuard};
|
use shared_lock::{SharedRwLockReadGuard, ToCssWithGuard};
|
||||||
|
use std::borrow::Cow;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use style_traits::{ToCss, OneOrMoreCommaSeparated};
|
use style_traits::{ToCss, OneOrMoreCommaSeparated, ParseError, StyleParseError};
|
||||||
use values::specified::url::SpecifiedUrl;
|
use values::specified::url::SpecifiedUrl;
|
||||||
|
|
||||||
/// A source for a font-face rule.
|
/// A source for a font-face rule.
|
||||||
|
@ -98,9 +100,10 @@ pub fn parse_font_face_block(context: &ParserContext, input: &mut Parser, locati
|
||||||
};
|
};
|
||||||
let mut iter = DeclarationListParser::new(input, parser);
|
let mut iter = DeclarationListParser::new(input, parser);
|
||||||
while let Some(declaration) = iter.next() {
|
while let Some(declaration) = iter.next() {
|
||||||
if let Err(range) = declaration {
|
if let Err(err) = declaration {
|
||||||
let pos = range.start;
|
let pos = err.span.start;
|
||||||
let error = ParseError::UnsupportedFontFaceDescriptor(iter.input.slice(range));
|
let error = ContextualParseError::UnsupportedFontFaceDescriptor(
|
||||||
|
iter.input.slice(err.span), err.error);
|
||||||
log_css_error(iter.input, pos, error, context);
|
log_css_error(iter.input, pos, error, context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -154,13 +157,15 @@ struct FontFaceRuleParser<'a, 'b: 'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Default methods reject all at rules.
|
/// Default methods reject all at rules.
|
||||||
impl<'a, 'b> AtRuleParser for FontFaceRuleParser<'a, 'b> {
|
impl<'a, 'b, 'i> AtRuleParser<'i> for FontFaceRuleParser<'a, 'b> {
|
||||||
type Prelude = ();
|
type Prelude = ();
|
||||||
type AtRule = ();
|
type AtRule = ();
|
||||||
|
type Error = SelectorParseError<'i, StyleParseError<'i>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for Source {
|
impl Parse for Source {
|
||||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Source, ()> {
|
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<Source, ParseError<'i>> {
|
||||||
if input.try(|input| input.expect_function_matching("local")).is_ok() {
|
if input.try(|input| input.expect_function_matching("local")).is_ok() {
|
||||||
return input.parse_nested_block(|input| {
|
return input.parse_nested_block(|input| {
|
||||||
FamilyName::parse(context, input)
|
FamilyName::parse(context, input)
|
||||||
|
@ -247,11 +252,13 @@ macro_rules! font_face_descriptors_common {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b> DeclarationParser for FontFaceRuleParser<'a, 'b> {
|
impl<'a, 'b, 'i> DeclarationParser<'i> for FontFaceRuleParser<'a, 'b> {
|
||||||
type Declaration = ();
|
type Declaration = ();
|
||||||
|
type Error = SelectorParseError<'i, StyleParseError<'i>>;
|
||||||
|
|
||||||
fn parse_value(&mut self, name: &str, input: &mut Parser) -> Result<(), ()> {
|
fn parse_value<'t>(&mut self, name: Cow<'i, str>, input: &mut Parser<'i, 't>)
|
||||||
match_ignore_ascii_case! { name,
|
-> Result<(), ParseError<'i>> {
|
||||||
|
match_ignore_ascii_case! { &*name,
|
||||||
$(
|
$(
|
||||||
$name => {
|
$name => {
|
||||||
// DeclarationParser also calls parse_entirely
|
// DeclarationParser also calls parse_entirely
|
||||||
|
@ -262,7 +269,7 @@ macro_rules! font_face_descriptors_common {
|
||||||
self.rule.$ident = Some(value)
|
self.rule.$ident = Some(value)
|
||||||
}
|
}
|
||||||
)*
|
)*
|
||||||
_ => return Err(())
|
_ => return Err(SelectorParseError::UnexpectedIdent(name.clone()).into())
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
use context::QuirksMode;
|
use context::QuirksMode;
|
||||||
use cssparser::{CssStringWriter, Parser, RGBA, Token};
|
use cssparser::{CssStringWriter, Parser, RGBA, Token, BasicParseError};
|
||||||
use euclid::Size2D;
|
use euclid::Size2D;
|
||||||
use font_metrics::get_metrics_provider_for_product;
|
use font_metrics::get_metrics_provider_for_product;
|
||||||
use gecko::values::convert_nscolor_to_rgba;
|
use gecko::values::convert_nscolor_to_rgba;
|
||||||
|
@ -19,11 +19,12 @@ use media_queries::MediaType;
|
||||||
use parser::ParserContext;
|
use parser::ParserContext;
|
||||||
use properties::{ComputedValues, StyleBuilder};
|
use properties::{ComputedValues, StyleBuilder};
|
||||||
use properties::longhands::font_size;
|
use properties::longhands::font_size;
|
||||||
|
use selectors::parser::SelectorParseError;
|
||||||
use std::fmt::{self, Write};
|
use std::fmt::{self, Write};
|
||||||
use std::sync::atomic::{AtomicBool, AtomicIsize, Ordering};
|
use std::sync::atomic::{AtomicBool, AtomicIsize, Ordering};
|
||||||
use str::starts_with_ignore_ascii_case;
|
use str::starts_with_ignore_ascii_case;
|
||||||
use string_cache::Atom;
|
use string_cache::Atom;
|
||||||
use style_traits::ToCss;
|
use style_traits::{ToCss, ParseError, StyleParseError};
|
||||||
use style_traits::viewport::ViewportConstraints;
|
use style_traits::viewport::ViewportConstraints;
|
||||||
use stylearc::Arc;
|
use stylearc::Arc;
|
||||||
use values::{CSSFloat, specified};
|
use values::{CSSFloat, specified};
|
||||||
|
@ -228,24 +229,25 @@ impl Resolution {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse(input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
let (value, unit) = match try!(input.next()) {
|
let (value, unit) = match try!(input.next()) {
|
||||||
Token::Dimension(value, unit) => {
|
Token::Dimension(value, unit) => {
|
||||||
(value.value, unit)
|
(value, unit)
|
||||||
},
|
},
|
||||||
_ => return Err(()),
|
t => return Err(BasicParseError::UnexpectedToken(t).into()),
|
||||||
};
|
};
|
||||||
|
|
||||||
if value <= 0. {
|
let inner_value = value.value;
|
||||||
return Err(())
|
if inner_value <= 0. {
|
||||||
|
return Err(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(match_ignore_ascii_case! { &unit,
|
(match_ignore_ascii_case! { &unit,
|
||||||
"dpi" => Resolution::Dpi(value),
|
"dpi" => Ok(Resolution::Dpi(inner_value)),
|
||||||
"dppx" => Resolution::Dppx(value),
|
"dppx" => Ok(Resolution::Dppx(inner_value)),
|
||||||
"dpcm" => Resolution::Dpcm(value),
|
"dpcm" => Ok(Resolution::Dpcm(inner_value)),
|
||||||
_ => return Err(())
|
_ => Err(())
|
||||||
})
|
}).map_err(|()| StyleParseError::UnexpectedDimension(unit).into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -459,44 +461,51 @@ impl Expression {
|
||||||
/// ```
|
/// ```
|
||||||
/// (media-feature: media-value)
|
/// (media-feature: media-value)
|
||||||
/// ```
|
/// ```
|
||||||
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<Self, ParseError<'i>> {
|
||||||
try!(input.expect_parenthesis_block());
|
try!(input.expect_parenthesis_block());
|
||||||
input.parse_nested_block(|input| {
|
input.parse_nested_block(|input| {
|
||||||
let ident = try!(input.expect_ident());
|
let ident = try!(input.expect_ident());
|
||||||
|
|
||||||
let mut flags = 0;
|
let mut flags = 0;
|
||||||
let mut feature_name = &*ident;
|
let result = {
|
||||||
|
let mut feature_name = &*ident;
|
||||||
|
|
||||||
// TODO(emilio): this is under a pref in Gecko.
|
// TODO(emilio): this is under a pref in Gecko.
|
||||||
if starts_with_ignore_ascii_case(feature_name, "-webkit-") {
|
if starts_with_ignore_ascii_case(feature_name, "-webkit-") {
|
||||||
feature_name = &feature_name[8..];
|
feature_name = &feature_name[8..];
|
||||||
flags |= nsMediaFeature_RequirementFlags::eHasWebkitPrefix as u8;
|
flags |= nsMediaFeature_RequirementFlags::eHasWebkitPrefix as u8;
|
||||||
}
|
}
|
||||||
|
|
||||||
let range = if starts_with_ignore_ascii_case(feature_name, "min-") {
|
let range = if starts_with_ignore_ascii_case(feature_name, "min-") {
|
||||||
feature_name = &feature_name[4..];
|
feature_name = &feature_name[4..];
|
||||||
nsMediaExpression_Range::eMin
|
nsMediaExpression_Range::eMin
|
||||||
} else if starts_with_ignore_ascii_case(feature_name, "max-") {
|
} else if starts_with_ignore_ascii_case(feature_name, "max-") {
|
||||||
feature_name = &feature_name[4..];
|
feature_name = &feature_name[4..];
|
||||||
nsMediaExpression_Range::eMax
|
nsMediaExpression_Range::eMax
|
||||||
} else {
|
} else {
|
||||||
nsMediaExpression_Range::eEqual
|
nsMediaExpression_Range::eEqual
|
||||||
};
|
|
||||||
|
|
||||||
let atom = Atom::from(feature_name);
|
|
||||||
let feature =
|
|
||||||
match find_feature(|f| atom.as_ptr() == unsafe { *f.mName }) {
|
|
||||||
Some(f) => f,
|
|
||||||
None => return Err(()),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let atom = Atom::from(feature_name);
|
||||||
|
match find_feature(|f| atom.as_ptr() == unsafe { *f.mName }) {
|
||||||
|
Some(f) => Ok((f, range)),
|
||||||
|
None => Err(()),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let (feature, range) = match result {
|
||||||
|
Ok((feature, range)) => (feature, range),
|
||||||
|
Err(()) => return Err(SelectorParseError::UnexpectedIdent(ident).into()),
|
||||||
|
};
|
||||||
|
|
||||||
if (feature.mReqFlags & !flags) != 0 {
|
if (feature.mReqFlags & !flags) != 0 {
|
||||||
return Err(());
|
return Err(SelectorParseError::UnexpectedIdent(ident).into());
|
||||||
}
|
}
|
||||||
|
|
||||||
if range != nsMediaExpression_Range::eEqual &&
|
if range != nsMediaExpression_Range::eEqual &&
|
||||||
feature.mRangeType != nsMediaFeature_RangeType::eMinMaxAllowed {
|
feature.mRangeType != nsMediaFeature_RangeType::eMinMaxAllowed {
|
||||||
return Err(());
|
return Err(SelectorParseError::UnexpectedIdent(ident).into());
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there's no colon, this is a media query of the form
|
// If there's no colon, this is a media query of the form
|
||||||
|
@ -506,7 +515,7 @@ impl Expression {
|
||||||
// reject them here too.
|
// reject them here too.
|
||||||
if input.try(|i| i.expect_colon()).is_err() {
|
if input.try(|i| i.expect_colon()).is_err() {
|
||||||
if range != nsMediaExpression_Range::eEqual {
|
if range != nsMediaExpression_Range::eEqual {
|
||||||
return Err(())
|
return Err(StyleParseError::RangedExpressionWithNoValue.into())
|
||||||
}
|
}
|
||||||
return Ok(Expression::new(feature, None, range));
|
return Ok(Expression::new(feature, None, range));
|
||||||
}
|
}
|
||||||
|
@ -519,14 +528,14 @@ impl Expression {
|
||||||
nsMediaFeature_ValueType::eInteger => {
|
nsMediaFeature_ValueType::eInteger => {
|
||||||
let i = input.expect_integer()?;
|
let i = input.expect_integer()?;
|
||||||
if i < 0 {
|
if i < 0 {
|
||||||
return Err(())
|
return Err(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
MediaExpressionValue::Integer(i as u32)
|
MediaExpressionValue::Integer(i as u32)
|
||||||
}
|
}
|
||||||
nsMediaFeature_ValueType::eBoolInteger => {
|
nsMediaFeature_ValueType::eBoolInteger => {
|
||||||
let i = input.expect_integer()?;
|
let i = input.expect_integer()?;
|
||||||
if i < 0 || i > 1 {
|
if i < 0 || i > 1 {
|
||||||
return Err(())
|
return Err(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
MediaExpressionValue::BoolInteger(i == 1)
|
MediaExpressionValue::BoolInteger(i == 1)
|
||||||
}
|
}
|
||||||
|
@ -536,14 +545,14 @@ impl Expression {
|
||||||
nsMediaFeature_ValueType::eIntRatio => {
|
nsMediaFeature_ValueType::eIntRatio => {
|
||||||
let a = input.expect_integer()?;
|
let a = input.expect_integer()?;
|
||||||
if a <= 0 {
|
if a <= 0 {
|
||||||
return Err(())
|
return Err(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
input.expect_delim('/')?;
|
input.expect_delim('/')?;
|
||||||
|
|
||||||
let b = input.expect_integer()?;
|
let b = input.expect_integer()?;
|
||||||
if b <= 0 {
|
if b <= 0 {
|
||||||
return Err(())
|
return Err(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
MediaExpressionValue::IntRatio(a as u32, b as u32)
|
MediaExpressionValue::IntRatio(a as u32, b as u32)
|
||||||
}
|
}
|
||||||
|
@ -566,7 +575,7 @@ impl Expression {
|
||||||
Some((_kw, value)) => {
|
Some((_kw, value)) => {
|
||||||
value
|
value
|
||||||
}
|
}
|
||||||
None => return Err(()),
|
None => return Err(StyleParseError::UnspecifiedError.into()),
|
||||||
};
|
};
|
||||||
|
|
||||||
MediaExpressionValue::Enumerated(value)
|
MediaExpressionValue::Enumerated(value)
|
||||||
|
|
|
@ -8,11 +8,12 @@ use cssparser::{Parser, ToCss};
|
||||||
use element_state::ElementState;
|
use element_state::ElementState;
|
||||||
use gecko_bindings::structs::CSSPseudoClassType;
|
use gecko_bindings::structs::CSSPseudoClassType;
|
||||||
use selector_parser::{SelectorParser, PseudoElementCascadeType};
|
use selector_parser::{SelectorParser, PseudoElementCascadeType};
|
||||||
use selectors::parser::{Selector, SelectorMethods};
|
use selectors::parser::{Selector, SelectorMethods, SelectorParseError};
|
||||||
use selectors::visitor::SelectorVisitor;
|
use selectors::visitor::SelectorVisitor;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use string_cache::{Atom, Namespace, WeakAtom, WeakNamespace};
|
use string_cache::{Atom, Namespace, WeakAtom, WeakNamespace};
|
||||||
|
use style_traits::{ParseError, StyleParseError};
|
||||||
|
|
||||||
pub use gecko::pseudo_element::{PseudoElement, EAGER_PSEUDOS, EAGER_PSEUDO_COUNT};
|
pub use gecko::pseudo_element::{PseudoElement, EAGER_PSEUDOS, EAGER_PSEUDO_COUNT};
|
||||||
pub use gecko::snapshot::SnapshotMap;
|
pub use gecko::snapshot::SnapshotMap;
|
||||||
|
@ -238,17 +239,20 @@ impl ::selectors::SelectorImpl for SelectorImpl {
|
||||||
type NonTSPseudoClass = NonTSPseudoClass;
|
type NonTSPseudoClass = NonTSPseudoClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ::selectors::Parser for SelectorParser<'a> {
|
impl<'a, 'i> ::selectors::Parser<'i> for SelectorParser<'a> {
|
||||||
type Impl = SelectorImpl;
|
type Impl = SelectorImpl;
|
||||||
|
type Error = StyleParseError<'i>;
|
||||||
|
|
||||||
fn parse_non_ts_pseudo_class(&self, name: Cow<str>) -> Result<NonTSPseudoClass, ()> {
|
fn parse_non_ts_pseudo_class(&self, name: Cow<'i, str>)
|
||||||
|
-> Result<NonTSPseudoClass, ParseError<'i>> {
|
||||||
macro_rules! pseudo_class_parse {
|
macro_rules! pseudo_class_parse {
|
||||||
(bare: [$(($css:expr, $name:ident, $gecko_type:tt, $state:tt, $flags:tt),)*],
|
(bare: [$(($css:expr, $name:ident, $gecko_type:tt, $state:tt, $flags:tt),)*],
|
||||||
string: [$(($s_css:expr, $s_name:ident, $s_gecko_type:tt, $s_state:tt, $s_flags:tt),)*],
|
string: [$(($s_css:expr, $s_name:ident, $s_gecko_type:tt, $s_state:tt, $s_flags:tt),)*],
|
||||||
keyword: [$(($k_css:expr, $k_name:ident, $k_gecko_type:tt, $k_state:tt, $k_flags:tt),)*]) => {
|
keyword: [$(($k_css:expr, $k_name:ident, $k_gecko_type:tt, $k_state:tt, $k_flags:tt),)*]) => {
|
||||||
match_ignore_ascii_case! { &name,
|
match_ignore_ascii_case! { &name,
|
||||||
$($css => NonTSPseudoClass::$name,)*
|
$($css => NonTSPseudoClass::$name,)*
|
||||||
_ => return Err(())
|
_ => return Err(::selectors::parser::SelectorParseError::UnexpectedIdent(
|
||||||
|
name.clone()).into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -256,14 +260,14 @@ impl<'a> ::selectors::Parser for SelectorParser<'a> {
|
||||||
if !pseudo_class.is_internal() || self.in_user_agent_stylesheet() {
|
if !pseudo_class.is_internal() || self.in_user_agent_stylesheet() {
|
||||||
Ok(pseudo_class)
|
Ok(pseudo_class)
|
||||||
} else {
|
} else {
|
||||||
Err(())
|
Err(SelectorParseError::UnexpectedIdent(name).into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_non_ts_functional_pseudo_class(&self,
|
fn parse_non_ts_functional_pseudo_class<'t>(&self,
|
||||||
name: Cow<str>,
|
name: Cow<'i, str>,
|
||||||
parser: &mut Parser)
|
parser: &mut Parser<'i, 't>)
|
||||||
-> Result<NonTSPseudoClass, ()> {
|
-> Result<NonTSPseudoClass, ParseError<'i>> {
|
||||||
macro_rules! pseudo_class_string_parse {
|
macro_rules! pseudo_class_string_parse {
|
||||||
(bare: [$(($css:expr, $name:ident, $gecko_type:tt, $state:tt, $flags:tt),)*],
|
(bare: [$(($css:expr, $name:ident, $gecko_type:tt, $state:tt, $flags:tt),)*],
|
||||||
string: [$(($s_css:expr, $s_name:ident, $s_gecko_type:tt, $s_state:tt, $s_flags:tt),)*],
|
string: [$(($s_css:expr, $s_name:ident, $s_gecko_type:tt, $s_state:tt, $s_flags:tt),)*],
|
||||||
|
@ -289,11 +293,11 @@ impl<'a> ::selectors::Parser for SelectorParser<'a> {
|
||||||
})?;
|
})?;
|
||||||
// Selectors inside `:-moz-any` may not include combinators.
|
// Selectors inside `:-moz-any` may not include combinators.
|
||||||
if selectors.iter().flat_map(|x| x.iter_raw()).any(|s| s.is_combinator()) {
|
if selectors.iter().flat_map(|x| x.iter_raw()).any(|s| s.is_combinator()) {
|
||||||
return Err(())
|
return Err(SelectorParseError::UnexpectedIdent("-moz-any".into()).into())
|
||||||
}
|
}
|
||||||
NonTSPseudoClass::MozAny(selectors.into_boxed_slice())
|
NonTSPseudoClass::MozAny(selectors.into_boxed_slice())
|
||||||
}
|
}
|
||||||
_ => return Err(())
|
_ => return Err(SelectorParseError::UnexpectedIdent(name.clone()).into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -301,13 +305,13 @@ impl<'a> ::selectors::Parser for SelectorParser<'a> {
|
||||||
if !pseudo_class.is_internal() || self.in_user_agent_stylesheet() {
|
if !pseudo_class.is_internal() || self.in_user_agent_stylesheet() {
|
||||||
Ok(pseudo_class)
|
Ok(pseudo_class)
|
||||||
} else {
|
} else {
|
||||||
Err(())
|
Err(SelectorParseError::UnexpectedIdent(name).into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_pseudo_element(&self, name: Cow<str>) -> Result<PseudoElement, ()> {
|
fn parse_pseudo_element(&self, name: Cow<'i, str>) -> Result<PseudoElement, ParseError<'i>> {
|
||||||
PseudoElement::from_slice(&name, self.in_user_agent_stylesheet())
|
PseudoElement::from_slice(&name, self.in_user_agent_stylesheet())
|
||||||
.ok_or(())
|
.ok_or(SelectorParseError::UnexpectedIdent(name.clone()).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_namespace(&self) -> Option<Namespace> {
|
fn default_namespace(&self) -> Option<Namespace> {
|
||||||
|
|
|
@ -11,7 +11,7 @@ use gecko_bindings::sugar::refptr::RefPtr;
|
||||||
use parser::ParserContext;
|
use parser::ParserContext;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::fmt::{self, Write};
|
use std::fmt::{self, Write};
|
||||||
use style_traits::ToCss;
|
use style_traits::{ToCss, ParseError};
|
||||||
use stylearc::Arc;
|
use stylearc::Arc;
|
||||||
|
|
||||||
/// A specified url() value for gecko. Gecko does not eagerly resolve SpecifiedUrls.
|
/// A specified url() value for gecko. Gecko does not eagerly resolve SpecifiedUrls.
|
||||||
|
@ -38,7 +38,7 @@ impl SpecifiedUrl {
|
||||||
/// Returns `Err` in the case that extra_data is incomplete.
|
/// Returns `Err` in the case that extra_data is incomplete.
|
||||||
pub fn parse_from_string<'a>(url: Cow<'a, str>,
|
pub fn parse_from_string<'a>(url: Cow<'a, str>,
|
||||||
context: &ParserContext)
|
context: &ParserContext)
|
||||||
-> Result<Self, ()> {
|
-> Result<Self, ParseError<'a>> {
|
||||||
Ok(SpecifiedUrl {
|
Ok(SpecifiedUrl {
|
||||||
serialization: Arc::new(url.into_owned()),
|
serialization: Arc::new(url.into_owned()),
|
||||||
extra_data: context.url_data.clone(),
|
extra_data: context.url_data.clone(),
|
||||||
|
|
|
@ -18,11 +18,14 @@ macro_rules! define_numbered_css_keyword_enum {
|
||||||
|
|
||||||
impl $crate::parser::Parse for $name {
|
impl $crate::parser::Parse for $name {
|
||||||
#[allow(missing_docs)]
|
#[allow(missing_docs)]
|
||||||
fn parse(_context: &$crate::parser::ParserContext, input: &mut ::cssparser::Parser) -> Result<$name, ()> {
|
fn parse<'i, 't>(_context: &$crate::parser::ParserContext,
|
||||||
match_ignore_ascii_case! { &try!(input.expect_ident()),
|
input: &mut ::cssparser::Parser<'i, 't>)
|
||||||
|
-> Result<$name, ::style_traits::ParseError<'i>> {
|
||||||
|
let ident = try!(input.expect_ident());
|
||||||
|
(match_ignore_ascii_case! { &ident,
|
||||||
$( $css => Ok($name::$variant), )+
|
$( $css => Ok($name::$variant), )+
|
||||||
_ => Err(())
|
_ => Err(())
|
||||||
}
|
}).map_err(|()| ::selectors::parser::SelectorParseError::UnexpectedIdent(ident).into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,9 +52,9 @@ macro_rules! add_impls_for_keyword_enum {
|
||||||
($name:ident) => {
|
($name:ident) => {
|
||||||
impl $crate::parser::Parse for $name {
|
impl $crate::parser::Parse for $name {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn parse(_context: &$crate::parser::ParserContext,
|
fn parse<'i, 't>(_context: &$crate::parser::ParserContext,
|
||||||
input: &mut ::cssparser::Parser)
|
input: &mut ::cssparser::Parser<'i, 't>)
|
||||||
-> Result<Self, ()> {
|
-> Result<Self, ::style_traits::ParseError<'i>> {
|
||||||
$name::parse(input)
|
$name::parse(input)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -89,10 +92,10 @@ macro_rules! define_keyword_type {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl $crate::parser::Parse for $name {
|
impl $crate::parser::Parse for $name {
|
||||||
fn parse(_context: &$crate::parser::ParserContext,
|
fn parse<'i, 't>(_context: &$crate::parser::ParserContext,
|
||||||
input: &mut ::cssparser::Parser)
|
input: &mut ::cssparser::Parser<'i, 't>)
|
||||||
-> Result<$name, ()> {
|
-> Result<$name, ::style_traits::ParseError<'i>> {
|
||||||
input.expect_ident_matching($css).map(|_| $name)
|
input.expect_ident_matching($css).map(|_| $name).map_err(|e| e.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,12 +8,13 @@
|
||||||
|
|
||||||
use Atom;
|
use Atom;
|
||||||
use context::QuirksMode;
|
use context::QuirksMode;
|
||||||
use cssparser::{Delimiter, Parser, Token};
|
use cssparser::{Delimiter, Parser, Token, ParserInput};
|
||||||
use parser::ParserContext;
|
use parser::ParserContext;
|
||||||
|
use selectors::parser::SelectorParseError;
|
||||||
use serialize_comma_separated_list;
|
use serialize_comma_separated_list;
|
||||||
use std::ascii::AsciiExt;
|
use std::ascii::AsciiExt;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use style_traits::ToCss;
|
use style_traits::{ToCss, ParseError, StyleParseError};
|
||||||
|
|
||||||
#[cfg(feature = "servo")]
|
#[cfg(feature = "servo")]
|
||||||
pub use servo::media_queries::{Device, Expression};
|
pub use servo::media_queries::{Device, Expression};
|
||||||
|
@ -209,7 +210,8 @@ impl MediaQuery {
|
||||||
/// Parse a media query given css input.
|
/// Parse a media query given css input.
|
||||||
///
|
///
|
||||||
/// Returns an error if any of the expressions is unknown.
|
/// Returns an error if any of the expressions is unknown.
|
||||||
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<MediaQuery, ()> {
|
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<MediaQuery, ParseError<'i>> {
|
||||||
let mut expressions = vec![];
|
let mut expressions = vec![];
|
||||||
|
|
||||||
let qualifier = if input.try(|input| input.expect_ident_matching("only")).is_ok() {
|
let qualifier = if input.try(|input| input.expect_ident_matching("only")).is_ok() {
|
||||||
|
@ -221,11 +223,15 @@ impl MediaQuery {
|
||||||
};
|
};
|
||||||
|
|
||||||
let media_type = match input.try(|input| input.expect_ident()) {
|
let media_type = match input.try(|input| input.expect_ident()) {
|
||||||
Ok(ident) => try!(MediaQueryType::parse(&*ident)),
|
Ok(ident) => {
|
||||||
Err(()) => {
|
let result: Result<_, ParseError> = MediaQueryType::parse(&*ident)
|
||||||
|
.map_err(|()| SelectorParseError::UnexpectedIdent(ident).into());
|
||||||
|
try!(result)
|
||||||
|
}
|
||||||
|
Err(_) => {
|
||||||
// Media type is only optional if qualifier is not specified.
|
// Media type is only optional if qualifier is not specified.
|
||||||
if qualifier.is_some() {
|
if qualifier.is_some() {
|
||||||
return Err(())
|
return Err(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Without a media type, require at least one expression.
|
// Without a media type, require at least one expression.
|
||||||
|
@ -270,7 +276,7 @@ pub fn parse_media_query_list(context: &ParserContext, input: &mut Parser) -> Me
|
||||||
match input.next() {
|
match input.next() {
|
||||||
Ok(Token::Comma) => {},
|
Ok(Token::Comma) => {},
|
||||||
Ok(_) => unreachable!(),
|
Ok(_) => unreachable!(),
|
||||||
Err(()) => break,
|
Err(_) => break,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -311,7 +317,8 @@ impl MediaList {
|
||||||
///
|
///
|
||||||
/// Returns true if added, false if fail to parse the medium string.
|
/// Returns true if added, false if fail to parse the medium string.
|
||||||
pub fn append_medium(&mut self, context: &ParserContext, new_medium: &str) -> bool {
|
pub fn append_medium(&mut self, context: &ParserContext, new_medium: &str) -> bool {
|
||||||
let mut parser = Parser::new(new_medium);
|
let mut input = ParserInput::new(new_medium);
|
||||||
|
let mut parser = Parser::new(&mut input);
|
||||||
let new_query = match MediaQuery::parse(&context, &mut parser) {
|
let new_query = match MediaQuery::parse(&context, &mut parser) {
|
||||||
Ok(query) => query,
|
Ok(query) => query,
|
||||||
Err(_) => { return false; }
|
Err(_) => { return false; }
|
||||||
|
@ -329,7 +336,8 @@ impl MediaList {
|
||||||
///
|
///
|
||||||
/// Returns true if found and deleted, false otherwise.
|
/// Returns true if found and deleted, false otherwise.
|
||||||
pub fn delete_medium(&mut self, context: &ParserContext, old_medium: &str) -> bool {
|
pub fn delete_medium(&mut self, context: &ParserContext, old_medium: &str) -> bool {
|
||||||
let mut parser = Parser::new(old_medium);
|
let mut input = ParserInput::new(old_medium);
|
||||||
|
let mut parser = Parser::new(&mut input);
|
||||||
let old_query = match MediaQuery::parse(context, &mut parser) {
|
let old_query = match MediaQuery::parse(context, &mut parser) {
|
||||||
Ok(query) => query,
|
Ok(query) => query,
|
||||||
Err(_) => { return false; }
|
Err(_) => { return false; }
|
||||||
|
|
|
@ -6,8 +6,8 @@
|
||||||
|
|
||||||
use context::QuirksMode;
|
use context::QuirksMode;
|
||||||
use cssparser::{Parser, SourcePosition, UnicodeRange};
|
use cssparser::{Parser, SourcePosition, UnicodeRange};
|
||||||
use error_reporting::{ParseErrorReporter, ParseError};
|
use error_reporting::{ParseErrorReporter, ContextualParseError};
|
||||||
use style_traits::OneOrMoreCommaSeparated;
|
use style_traits::{OneOrMoreCommaSeparated, ParseError};
|
||||||
use stylesheets::{CssRuleType, Origin, UrlExtraData, Namespaces};
|
use stylesheets::{CssRuleType, Origin, UrlExtraData, Namespaces};
|
||||||
|
|
||||||
bitflags! {
|
bitflags! {
|
||||||
|
@ -166,7 +166,7 @@ impl<'a> ParserContext<'a> {
|
||||||
/// to log CSS parse errors to stderr.
|
/// to log CSS parse errors to stderr.
|
||||||
pub fn log_css_error<'a>(input: &mut Parser,
|
pub fn log_css_error<'a>(input: &mut Parser,
|
||||||
position: SourcePosition,
|
position: SourcePosition,
|
||||||
error: ParseError<'a>,
|
error: ContextualParseError<'a>,
|
||||||
parsercontext: &ParserContext) {
|
parsercontext: &ParserContext) {
|
||||||
let url_data = parsercontext.url_data;
|
let url_data = parsercontext.url_data;
|
||||||
let line_number_offset = parsercontext.line_number_offset;
|
let line_number_offset = parsercontext.line_number_offset;
|
||||||
|
@ -183,19 +183,21 @@ pub trait Parse : Sized {
|
||||||
/// Parse a value of this type.
|
/// Parse a value of this type.
|
||||||
///
|
///
|
||||||
/// Returns an error on failure.
|
/// Returns an error on failure.
|
||||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()>;
|
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<Self, ParseError<'i>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Parse for Vec<T> where T: Parse + OneOrMoreCommaSeparated {
|
impl<T> Parse for Vec<T> where T: Parse + OneOrMoreCommaSeparated {
|
||||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<Self, ParseError<'i>> {
|
||||||
input.parse_comma_separated(|input| T::parse(context, input))
|
input.parse_comma_separated(|input| T::parse(context, input))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a non-empty space-separated or comma-separated list of objects parsed by parse_one
|
/// Parse a non-empty space-separated or comma-separated list of objects parsed by parse_one
|
||||||
pub fn parse_space_or_comma_separated<F, T>(input: &mut Parser, mut parse_one: F)
|
pub fn parse_space_or_comma_separated<'i, 't, F, T>(input: &mut Parser<'i, 't>, mut parse_one: F)
|
||||||
-> Result<Vec<T>, ()>
|
-> Result<Vec<T>, ParseError<'i>>
|
||||||
where F: FnMut(&mut Parser) -> Result<T, ()> {
|
where F: for<'ii, 'tt> FnMut(&mut Parser<'ii, 'tt>) -> Result<T, ParseError<'ii>> {
|
||||||
let first = parse_one(input)?;
|
let first = parse_one(input)?;
|
||||||
let mut vec = vec![first];
|
let mut vec = vec![first];
|
||||||
loop {
|
loop {
|
||||||
|
@ -209,7 +211,8 @@ pub fn parse_space_or_comma_separated<F, T>(input: &mut Parser, mut parse_one: F
|
||||||
Ok(vec)
|
Ok(vec)
|
||||||
}
|
}
|
||||||
impl Parse for UnicodeRange {
|
impl Parse for UnicodeRange {
|
||||||
fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
UnicodeRange::parse(input)
|
-> Result<Self, ParseError<'i>> {
|
||||||
|
UnicodeRange::parse(input).map_err(|e| e.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,15 +7,16 @@
|
||||||
#![deny(missing_docs)]
|
#![deny(missing_docs)]
|
||||||
|
|
||||||
use context::QuirksMode;
|
use context::QuirksMode;
|
||||||
use cssparser::{DeclarationListParser, parse_important};
|
use cssparser::{DeclarationListParser, parse_important, ParserInput};
|
||||||
use cssparser::{Parser, AtRuleParser, DeclarationParser, Delimiter};
|
use cssparser::{Parser, AtRuleParser, DeclarationParser, Delimiter};
|
||||||
use error_reporting::{ParseErrorReporter, ParseError};
|
use error_reporting::{ParseErrorReporter, ContextualParseError};
|
||||||
use parser::{PARSING_MODE_DEFAULT, ParsingMode, ParserContext, log_css_error};
|
use parser::{PARSING_MODE_DEFAULT, ParsingMode, ParserContext, log_css_error};
|
||||||
use properties::animated_properties::AnimationValue;
|
use properties::animated_properties::AnimationValue;
|
||||||
|
use selectors::parser::SelectorParseError;
|
||||||
use shared_lock::Locked;
|
use shared_lock::Locked;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::slice::Iter;
|
use std::slice::Iter;
|
||||||
use style_traits::ToCss;
|
use style_traits::{ToCss, ParseError, StyleParseError};
|
||||||
use stylesheets::{CssRuleType, Origin, UrlExtraData};
|
use stylesheets::{CssRuleType, Origin, UrlExtraData};
|
||||||
use stylesheets::{MallocSizeOf, MallocSizeOfFn};
|
use stylesheets::{MallocSizeOf, MallocSizeOfFn};
|
||||||
use super::*;
|
use super::*;
|
||||||
|
@ -875,7 +876,8 @@ pub fn parse_style_attribute(input: &str,
|
||||||
Some(CssRuleType::Style),
|
Some(CssRuleType::Style),
|
||||||
PARSING_MODE_DEFAULT,
|
PARSING_MODE_DEFAULT,
|
||||||
quirks_mode);
|
quirks_mode);
|
||||||
parse_property_declaration_list(&context, &mut Parser::new(input))
|
let mut input = ParserInput::new(input);
|
||||||
|
parse_property_declaration_list(&context, &mut Parser::new(&mut input))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a given property declaration. Can result in multiple
|
/// Parse a given property declaration. Can result in multiple
|
||||||
|
@ -896,10 +898,11 @@ pub fn parse_one_declaration_into(declarations: &mut SourcePropertyDeclaration,
|
||||||
Some(CssRuleType::Style),
|
Some(CssRuleType::Style),
|
||||||
parsing_mode,
|
parsing_mode,
|
||||||
quirks_mode);
|
quirks_mode);
|
||||||
Parser::new(input).parse_entirely(|parser| {
|
let mut input = ParserInput::new(input);
|
||||||
|
Parser::new(&mut input).parse_entirely(|parser| {
|
||||||
PropertyDeclaration::parse_into(declarations, id, &context, parser)
|
PropertyDeclaration::parse_into(declarations, id, &context, parser)
|
||||||
.map_err(|_| ())
|
.map_err(|e| e.into())
|
||||||
})
|
}).map_err(|_| ())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A struct to parse property declarations.
|
/// A struct to parse property declarations.
|
||||||
|
@ -910,23 +913,26 @@ struct PropertyDeclarationParser<'a, 'b: 'a> {
|
||||||
|
|
||||||
|
|
||||||
/// Default methods reject all at rules.
|
/// Default methods reject all at rules.
|
||||||
impl<'a, 'b> AtRuleParser for PropertyDeclarationParser<'a, 'b> {
|
impl<'a, 'b, 'i> AtRuleParser<'i> for PropertyDeclarationParser<'a, 'b> {
|
||||||
type Prelude = ();
|
type Prelude = ();
|
||||||
type AtRule = Importance;
|
type AtRule = Importance;
|
||||||
|
type Error = SelectorParseError<'i, StyleParseError<'i>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b> DeclarationParser for PropertyDeclarationParser<'a, 'b> {
|
impl<'a, 'b, 'i> DeclarationParser<'i> for PropertyDeclarationParser<'a, 'b> {
|
||||||
type Declaration = Importance;
|
type Declaration = Importance;
|
||||||
|
type Error = SelectorParseError<'i, StyleParseError<'i>>;
|
||||||
|
|
||||||
fn parse_value(&mut self, name: &str, input: &mut Parser) -> Result<Importance, ()> {
|
fn parse_value<'t>(&mut self, name: Cow<'i, str>, input: &mut Parser<'i, 't>)
|
||||||
let id = try!(PropertyId::parse(name.into()));
|
-> Result<Importance, ParseError<'i>> {
|
||||||
|
let id = try!(PropertyId::parse(name));
|
||||||
input.parse_until_before(Delimiter::Bang, |input| {
|
input.parse_until_before(Delimiter::Bang, |input| {
|
||||||
PropertyDeclaration::parse_into(self.declarations, id, self.context, input)
|
PropertyDeclaration::parse_into(self.declarations, id, self.context, input)
|
||||||
.map_err(|_| ())
|
.map_err(|e| e.into())
|
||||||
})?;
|
})?;
|
||||||
let importance = match input.try(parse_important) {
|
let importance = match input.try(parse_important) {
|
||||||
Ok(()) => Importance::Important,
|
Ok(()) => Importance::Important,
|
||||||
Err(()) => Importance::Normal,
|
Err(_) => Importance::Normal,
|
||||||
};
|
};
|
||||||
// In case there is still unparsed text in the declaration, we should roll back.
|
// In case there is still unparsed text in the declaration, we should roll back.
|
||||||
input.expect_exhausted()?;
|
input.expect_exhausted()?;
|
||||||
|
@ -952,10 +958,11 @@ pub fn parse_property_declaration_list(context: &ParserContext,
|
||||||
Ok(importance) => {
|
Ok(importance) => {
|
||||||
block.extend(iter.parser.declarations.drain(), importance);
|
block.extend(iter.parser.declarations.drain(), importance);
|
||||||
}
|
}
|
||||||
Err(range) => {
|
Err(err) => {
|
||||||
iter.parser.declarations.clear();
|
iter.parser.declarations.clear();
|
||||||
let pos = range.start;
|
let pos = err.span.start;
|
||||||
let error = ParseError::UnsupportedPropertyDeclaration(iter.input.slice(range));
|
let error = ContextualParseError::UnsupportedPropertyDeclaration(
|
||||||
|
iter.input.slice(err.span), err.error);
|
||||||
log_css_error(iter.input, pos, error, &context);
|
log_css_error(iter.input, pos, error, &context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,9 +33,9 @@
|
||||||
% endif
|
% endif
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn parse(context: &ParserContext,
|
pub fn parse<'i, 't>(context: &ParserContext,
|
||||||
input: &mut Parser)
|
input: &mut Parser<'i, 't>)
|
||||||
-> Result<SpecifiedValue, ()> {
|
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||||
% if allow_quirks:
|
% if allow_quirks:
|
||||||
specified::${type}::${parse_method}_quirky(context, input, AllowQuirks::Yes)
|
specified::${type}::${parse_method}_quirky(context, input, AllowQuirks::Yes)
|
||||||
% elif needs_context:
|
% elif needs_context:
|
||||||
|
@ -87,12 +87,16 @@
|
||||||
|
|
||||||
pub mod single_value {
|
pub mod single_value {
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use cssparser::Parser;
|
use cssparser::{Parser, BasicParseError};
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use parser::{Parse, ParserContext};
|
use parser::{Parse, ParserContext};
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use properties::ShorthandId;
|
use properties::ShorthandId;
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
|
use selectors::parser::SelectorParseError;
|
||||||
|
#[allow(unused_imports)]
|
||||||
|
use style_traits::{ParseError, StyleParseError};
|
||||||
|
#[allow(unused_imports)]
|
||||||
use values::computed::{Context, ToComputedValue};
|
use values::computed::{Context, ToComputedValue};
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use values::{computed, specified};
|
use values::{computed, specified};
|
||||||
|
@ -207,7 +211,8 @@
|
||||||
% endif
|
% endif
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use parser::parse_space_or_comma_separated;
|
use parser::parse_space_or_comma_separated;
|
||||||
|
|
||||||
|
@ -266,7 +271,7 @@
|
||||||
pub mod ${property.ident} {
|
pub mod ${property.ident} {
|
||||||
% if not property.derived_from:
|
% if not property.derived_from:
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use cssparser::Parser;
|
use cssparser::{Parser, BasicParseError, Token};
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use parser::{Parse, ParserContext};
|
use parser::{Parse, ParserContext};
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
|
@ -287,8 +292,12 @@
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use properties::style_structs;
|
use properties::style_structs;
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
|
use selectors::parser::SelectorParseError;
|
||||||
|
#[allow(unused_imports)]
|
||||||
use stylearc::Arc;
|
use stylearc::Arc;
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
|
use style_traits::{ParseError, StyleParseError};
|
||||||
|
#[allow(unused_imports)]
|
||||||
use values::computed::{Context, ToComputedValue};
|
use values::computed::{Context, ToComputedValue};
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use values::{computed, generics, specified};
|
use values::{computed, generics, specified};
|
||||||
|
@ -423,12 +432,12 @@
|
||||||
% endif
|
% endif
|
||||||
}
|
}
|
||||||
% if not property.derived_from:
|
% if not property.derived_from:
|
||||||
pub fn parse_specified(context: &ParserContext, input: &mut Parser)
|
pub fn parse_specified<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
% if property.boxed:
|
% if property.boxed:
|
||||||
-> Result<Box<SpecifiedValue>, ()> {
|
-> Result<Box<SpecifiedValue>, ParseError<'i>> {
|
||||||
parse(context, input).map(|result| Box::new(result))
|
parse(context, input).map(|result| Box::new(result))
|
||||||
% else:
|
% else:
|
||||||
-> Result<SpecifiedValue, ()> {
|
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||||
% if property.allow_quirks:
|
% if property.allow_quirks:
|
||||||
parse_quirky(context, input, specified::AllowQuirks::Yes)
|
parse_quirky(context, input, specified::AllowQuirks::Yes)
|
||||||
% else:
|
% else:
|
||||||
|
@ -436,11 +445,11 @@
|
||||||
% endif
|
% endif
|
||||||
% endif
|
% endif
|
||||||
}
|
}
|
||||||
pub fn parse_declared(context: &ParserContext, input: &mut Parser)
|
pub fn parse_declared<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
-> Result<PropertyDeclaration, ()> {
|
-> Result<PropertyDeclaration, ParseError<'i>> {
|
||||||
match input.try(|i| CSSWideKeyword::parse(context, i)) {
|
match input.try(|i| CSSWideKeyword::parse(context, i)) {
|
||||||
Ok(keyword) => Ok(PropertyDeclaration::CSSWideKeyword(LonghandId::${property.camel_case}, keyword)),
|
Ok(keyword) => Ok(PropertyDeclaration::CSSWideKeyword(LonghandId::${property.camel_case}, keyword)),
|
||||||
Err(()) => {
|
Err(_) => {
|
||||||
input.look_for_var_functions();
|
input.look_for_var_functions();
|
||||||
let start = input.position();
|
let start = input.position();
|
||||||
let specified = parse_specified(context, input);
|
let specified = parse_specified(context, input);
|
||||||
|
@ -487,7 +496,7 @@
|
||||||
use cssparser::Parser;
|
use cssparser::Parser;
|
||||||
use parser::{Parse, ParserContext};
|
use parser::{Parse, ParserContext};
|
||||||
|
|
||||||
use style_traits::ToCss;
|
use style_traits::{ToCss, ParseError};
|
||||||
define_css_keyword_enum! { T:
|
define_css_keyword_enum! { T:
|
||||||
% for value in keyword.values_for(product):
|
% for value in keyword.values_for(product):
|
||||||
"${value}" => ${to_rust_ident(value)},
|
"${value}" => ${to_rust_ident(value)},
|
||||||
|
@ -495,7 +504,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for T {
|
impl Parse for T {
|
||||||
fn parse(_: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
T::parse(input)
|
T::parse(input)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -518,7 +527,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse(_: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
pub fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>) -> Result<SpecifiedValue, ParseError<'i>> {
|
||||||
Ok(SpecifiedValue::Keyword(computed_value::T::parse(input)?))
|
Ok(SpecifiedValue::Keyword(computed_value::T::parse(input)?))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -716,14 +725,14 @@
|
||||||
SpecifiedValue::${to_rust_ident(values.split()[0])}
|
SpecifiedValue::${to_rust_ident(values.split()[0])}
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn parse(_context: &ParserContext, input: &mut Parser)
|
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
-> Result<SpecifiedValue, ()> {
|
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||||
SpecifiedValue::parse(input)
|
SpecifiedValue::parse(input)
|
||||||
}
|
}
|
||||||
impl Parse for SpecifiedValue {
|
impl Parse for SpecifiedValue {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn parse(_context: &ParserContext, input: &mut Parser)
|
fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
-> Result<SpecifiedValue, ()> {
|
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||||
SpecifiedValue::parse(input)
|
SpecifiedValue::parse(input)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -764,9 +773,11 @@
|
||||||
use parser::ParserContext;
|
use parser::ParserContext;
|
||||||
use properties::{PropertyDeclaration, SourcePropertyDeclaration, MaybeBoxed};
|
use properties::{PropertyDeclaration, SourcePropertyDeclaration, MaybeBoxed};
|
||||||
use properties::{ShorthandId, LonghandId, UnparsedValue, longhands};
|
use properties::{ShorthandId, LonghandId, UnparsedValue, longhands};
|
||||||
|
#[allow(unused_imports)]
|
||||||
|
use selectors::parser::SelectorParseError;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use stylearc::Arc;
|
use stylearc::Arc;
|
||||||
use style_traits::ToCss;
|
use style_traits::{ToCss, ParseError, StyleParseError};
|
||||||
|
|
||||||
pub struct Longhands {
|
pub struct Longhands {
|
||||||
% for sub_property in shorthand.sub_properties:
|
% for sub_property in shorthand.sub_properties:
|
||||||
|
@ -838,8 +849,8 @@
|
||||||
|
|
||||||
/// Parse the given shorthand and fill the result into the
|
/// Parse the given shorthand and fill the result into the
|
||||||
/// `declarations` vector.
|
/// `declarations` vector.
|
||||||
pub fn parse_into(declarations: &mut SourcePropertyDeclaration,
|
pub fn parse_into<'i, 't>(declarations: &mut SourcePropertyDeclaration,
|
||||||
context: &ParserContext, input: &mut Parser) -> Result<(), ()> {
|
context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<(), ParseError<'i>> {
|
||||||
input.look_for_var_functions();
|
input.look_for_var_functions();
|
||||||
let start = input.position();
|
let start = input.position();
|
||||||
let value = input.parse_entirely(|input| parse_value(context, input));
|
let value = input.parse_entirely(|input| parse_value(context, input));
|
||||||
|
@ -872,7 +883,7 @@
|
||||||
% endfor
|
% endfor
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err(())
|
Err(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -890,7 +901,8 @@
|
||||||
use values::generics::rect::Rect;
|
use values::generics::rect::Rect;
|
||||||
use values::specified;
|
use values::specified;
|
||||||
|
|
||||||
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<Longhands, ParseError<'i>> {
|
||||||
let rect = Rect::parse_with(context, input, |_c, i| {
|
let rect = Rect::parse_with(context, input, |_c, i| {
|
||||||
% if allow_quirks:
|
% if allow_quirks:
|
||||||
${parser_function}_quirky(_c, i, specified::AllowQuirks::Yes)
|
${parser_function}_quirky(_c, i, specified::AllowQuirks::Yes)
|
||||||
|
@ -1114,7 +1126,8 @@
|
||||||
use values::computed::${length_type};
|
use values::computed::${length_type};
|
||||||
${length_type}::${initial_value}
|
${length_type}::${initial_value}
|
||||||
}
|
}
|
||||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||||
% if logical:
|
% if logical:
|
||||||
let ret = ${length_type}::parse(context, input);
|
let ret = ${length_type}::parse(context, input);
|
||||||
% else:
|
% else:
|
||||||
|
@ -1123,7 +1136,7 @@
|
||||||
// Keyword values don't make sense in the block direction; don't parse them
|
// Keyword values don't make sense in the block direction; don't parse them
|
||||||
% if "block" in name:
|
% if "block" in name:
|
||||||
if let Ok(${length_type}::ExtremumLength(..)) = ret {
|
if let Ok(${length_type}::ExtremumLength(..)) = ret {
|
||||||
return Err(())
|
return Err(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
% endif
|
% endif
|
||||||
ret.map(SpecifiedValue)
|
ret.map(SpecifiedValue)
|
||||||
|
|
|
@ -27,12 +27,13 @@ use properties::longhands::transform::computed_value::T as TransformList;
|
||||||
use properties::longhands::vertical_align::computed_value::T as VerticalAlign;
|
use properties::longhands::vertical_align::computed_value::T as VerticalAlign;
|
||||||
use properties::longhands::visibility::computed_value::T as Visibility;
|
use properties::longhands::visibility::computed_value::T as Visibility;
|
||||||
#[cfg(feature = "gecko")] use properties::{PropertyDeclarationId, LonghandId};
|
#[cfg(feature = "gecko")] use properties::{PropertyDeclarationId, LonghandId};
|
||||||
|
use selectors::parser::SelectorParseError;
|
||||||
#[cfg(feature = "servo")] use servo_atoms::Atom;
|
#[cfg(feature = "servo")] use servo_atoms::Atom;
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
#[cfg(feature = "gecko")] use std::collections::HashMap;
|
#[cfg(feature = "gecko")] use std::collections::HashMap;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use style_traits::ToCss;
|
use style_traits::{ToCss, ParseError};
|
||||||
use super::ComputedValues;
|
use super::ComputedValues;
|
||||||
use values::CSSFloat;
|
use values::CSSFloat;
|
||||||
use values::{Auto, Either};
|
use values::{Auto, Either};
|
||||||
|
@ -99,9 +100,9 @@ impl TransitionProperty {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a transition-property value.
|
/// Parse a transition-property value.
|
||||||
pub fn parse(input: &mut Parser) -> Result<Self, ()> {
|
pub fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
let ident = try!(input.expect_ident());
|
let ident = try!(input.expect_ident());
|
||||||
match_ignore_ascii_case! { &ident,
|
(match_ignore_ascii_case! { &ident,
|
||||||
"all" => Ok(TransitionProperty::All),
|
"all" => Ok(TransitionProperty::All),
|
||||||
% for prop in data.longhands:
|
% for prop in data.longhands:
|
||||||
% if prop.animatable:
|
% if prop.animatable:
|
||||||
|
@ -118,7 +119,7 @@ impl TransitionProperty {
|
||||||
None => Ok(TransitionProperty::Unsupported((&*ident).into()))
|
None => Ok(TransitionProperty::Unsupported((&*ident).into()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident.into()).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get a transition property from a property declaration.
|
/// Get a transition property from a property declaration.
|
||||||
|
|
|
@ -128,17 +128,20 @@ ${helpers.predefined_type("background-image", "ImageLayer",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||||
let ident = input.expect_ident()?;
|
let ident = input.expect_ident()?;
|
||||||
match_ignore_ascii_case! { &ident,
|
(match_ignore_ascii_case! { &ident,
|
||||||
"repeat-x" => Ok(SpecifiedValue::RepeatX),
|
"repeat-x" => Ok(SpecifiedValue::RepeatX),
|
||||||
"repeat-y" => Ok(SpecifiedValue::RepeatY),
|
"repeat-y" => Ok(SpecifiedValue::RepeatY),
|
||||||
_ => {
|
_ => Err(()),
|
||||||
let horizontal = try!(RepeatKeyword::from_ident(&ident));
|
}).or_else(|()| {
|
||||||
let vertical = input.try(RepeatKeyword::parse).ok();
|
let horizontal: Result<_, ParseError> = RepeatKeyword::from_ident(&ident)
|
||||||
Ok(SpecifiedValue::Other(horizontal, vertical))
|
.map_err(|()| SelectorParseError::UnexpectedIdent(ident).into());
|
||||||
}
|
let horizontal = try!(horizontal);
|
||||||
}
|
let vertical = input.try(RepeatKeyword::parse).ok();
|
||||||
|
Ok(SpecifiedValue::Other(horizontal, vertical))
|
||||||
|
})
|
||||||
}
|
}
|
||||||
</%helpers:vector_longhand>
|
</%helpers:vector_longhand>
|
||||||
|
|
||||||
|
|
|
@ -161,8 +161,8 @@ ${helpers.gecko_keyword_conversion(Keyword('border-style',
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn parse(context: &ParserContext, input: &mut Parser)
|
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
-> Result<SpecifiedValue, ()> {
|
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||||
if input.try(|input| input.expect_ident_matching("none")).is_ok() {
|
if input.try(|input| input.expect_ident_matching("none")).is_ok() {
|
||||||
return Ok(SpecifiedValue::None)
|
return Ok(SpecifiedValue::None)
|
||||||
}
|
}
|
||||||
|
@ -175,7 +175,7 @@ ${helpers.gecko_keyword_conversion(Keyword('border-style',
|
||||||
if !result.is_empty() {
|
if !result.is_empty() {
|
||||||
Ok(SpecifiedValue::Colors(result))
|
Ok(SpecifiedValue::Colors(result))
|
||||||
} else {
|
} else {
|
||||||
Err(())
|
Err(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</%helpers:longhand>
|
</%helpers:longhand>
|
||||||
|
@ -272,7 +272,8 @@ ${helpers.predefined_type("border-image-outset", "LengthOrNumberRect",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||||
let first = try!(RepeatKeyword::parse(input));
|
let first = try!(RepeatKeyword::parse(input));
|
||||||
let second = input.try(RepeatKeyword::parse).ok();
|
let second = input.try(RepeatKeyword::parse).ok();
|
||||||
|
|
||||||
|
|
|
@ -113,16 +113,17 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a display value.
|
/// Parse a display value.
|
||||||
pub fn parse(_context: &ParserContext, input: &mut Parser)
|
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
-> Result<SpecifiedValue, ()> {
|
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||||
match_ignore_ascii_case! { &try!(input.expect_ident()),
|
let ident = try!(input.expect_ident());
|
||||||
|
(match_ignore_ascii_case! { &ident,
|
||||||
% for value in values:
|
% for value in values:
|
||||||
"${value}" => {
|
"${value}" => {
|
||||||
Ok(computed_value::T::${to_rust_ident(value)})
|
Ok(computed_value::T::${to_rust_ident(value)})
|
||||||
},
|
},
|
||||||
% endfor
|
% endfor
|
||||||
_ => Err(())
|
_ => Err(())
|
||||||
}
|
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ComputedValueAsSpecified for SpecifiedValue {}
|
impl ComputedValueAsSpecified for SpecifiedValue {}
|
||||||
|
@ -292,16 +293,18 @@ ${helpers.single_keyword("position", "static absolute relative fixed",
|
||||||
}
|
}
|
||||||
/// baseline | sub | super | top | text-top | middle | bottom | text-bottom
|
/// baseline | sub | super | top | text-top | middle | bottom | text-bottom
|
||||||
/// | <percentage> | <length>
|
/// | <percentage> | <length>
|
||||||
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||||
input.try(|i| specified::LengthOrPercentage::parse_quirky(context, i, AllowQuirks::Yes))
|
input.try(|i| specified::LengthOrPercentage::parse_quirky(context, i, AllowQuirks::Yes))
|
||||||
.map(SpecifiedValue::LengthOrPercentage)
|
.map(SpecifiedValue::LengthOrPercentage)
|
||||||
.or_else(|_| {
|
.or_else(|_| {
|
||||||
match_ignore_ascii_case! { &try!(input.expect_ident()),
|
let ident = try!(input.expect_ident());
|
||||||
|
(match_ignore_ascii_case! { &ident,
|
||||||
% for keyword in vertical_align_keywords:
|
% for keyword in vertical_align_keywords:
|
||||||
"${keyword}" => Ok(SpecifiedValue::${to_rust_ident(keyword)}),
|
"${keyword}" => Ok(SpecifiedValue::${to_rust_ident(keyword)}),
|
||||||
% endfor
|
% endfor
|
||||||
_ => Err(())
|
_ => Err(())
|
||||||
}
|
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -500,17 +503,19 @@ ${helpers.predefined_type("transition-delay",
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for SpecifiedValue {
|
impl Parse for SpecifiedValue {
|
||||||
fn parse(context: &ParserContext, input: &mut ::cssparser::Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(context: &ParserContext, input: &mut ::cssparser::Parser<'i, 't>)
|
||||||
|
-> Result<Self, ParseError<'i>> {
|
||||||
if let Ok(name) = input.try(|input| KeyframesName::parse(context, input)) {
|
if let Ok(name) = input.try(|input| KeyframesName::parse(context, input)) {
|
||||||
Ok(SpecifiedValue(Some(name)))
|
Ok(SpecifiedValue(Some(name)))
|
||||||
} else {
|
} else {
|
||||||
input.expect_ident_matching("none").map(|()| SpecifiedValue(None))
|
input.expect_ident_matching("none").map(|_| SpecifiedValue(None)).map_err(|e| e.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
no_viewport_percentage!(SpecifiedValue);
|
no_viewport_percentage!(SpecifiedValue);
|
||||||
|
|
||||||
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue,()> {
|
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<SpecifiedValue,ParseError<'i>> {
|
||||||
SpecifiedValue::parse(context, input)
|
SpecifiedValue::parse(context, input)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -560,14 +565,15 @@ ${helpers.predefined_type("animation-timing-function",
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for SpecifiedValue {
|
impl Parse for SpecifiedValue {
|
||||||
fn parse(_context: &ParserContext, input: &mut ::cssparser::Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(_context: &ParserContext, input: &mut ::cssparser::Parser<'i, 't>)
|
||||||
|
-> Result<Self, ParseError<'i>> {
|
||||||
if input.try(|input| input.expect_ident_matching("infinite")).is_ok() {
|
if input.try(|input| input.expect_ident_matching("infinite")).is_ok() {
|
||||||
return Ok(SpecifiedValue::Infinite)
|
return Ok(SpecifiedValue::Infinite)
|
||||||
}
|
}
|
||||||
|
|
||||||
let number = try!(input.expect_number());
|
let number = try!(input.expect_number());
|
||||||
if number < 0.0 {
|
if number < 0.0 {
|
||||||
return Err(());
|
return Err(StyleParseError::UnspecifiedError.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(SpecifiedValue::Number(number))
|
Ok(SpecifiedValue::Number(number))
|
||||||
|
@ -587,7 +593,8 @@ ${helpers.predefined_type("animation-timing-function",
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||||
SpecifiedValue::parse(context, input)
|
SpecifiedValue::parse(context, input)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -948,8 +955,8 @@ ${helpers.predefined_type("scroll-snap-coordinate",
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allow unitless zero angle for rotate() and skew() to align with gecko
|
// Allow unitless zero angle for rotate() and skew() to align with gecko
|
||||||
fn parse_internal(context: &ParserContext, input: &mut Parser, prefixed: bool)
|
fn parse_internal<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>, prefixed: bool)
|
||||||
-> Result<SpecifiedValue,()> {
|
-> Result<SpecifiedValue,ParseError<'i>> {
|
||||||
if input.try(|input| input.expect_ident_matching("none")).is_ok() {
|
if input.try(|input| input.expect_ident_matching("none")).is_ok() {
|
||||||
return Ok(SpecifiedValue(Vec::new()))
|
return Ok(SpecifiedValue(Vec::new()))
|
||||||
}
|
}
|
||||||
|
@ -960,7 +967,7 @@ ${helpers.predefined_type("scroll-snap-coordinate",
|
||||||
Ok(name) => name,
|
Ok(name) => name,
|
||||||
Err(_) => break,
|
Err(_) => break,
|
||||||
};
|
};
|
||||||
match_ignore_ascii_case! {
|
let valid_fn = match_ignore_ascii_case! {
|
||||||
&name,
|
&name,
|
||||||
"matrix" => {
|
"matrix" => {
|
||||||
try!(input.parse_nested_block(|input| {
|
try!(input.parse_nested_block(|input| {
|
||||||
|
@ -970,7 +977,7 @@ ${helpers.predefined_type("scroll-snap-coordinate",
|
||||||
specified::parse_number(context, input)
|
specified::parse_number(context, input)
|
||||||
}));
|
}));
|
||||||
if values.len() != 6 {
|
if values.len() != 6 {
|
||||||
return Err(())
|
return Err(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
result.push(SpecifiedOperation::Matrix {
|
result.push(SpecifiedOperation::Matrix {
|
||||||
|
@ -981,7 +988,7 @@ ${helpers.predefined_type("scroll-snap-coordinate",
|
||||||
e: values[4],
|
e: values[4],
|
||||||
f: values[5],
|
f: values[5],
|
||||||
});
|
});
|
||||||
return Ok(());
|
return Ok(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Non-standard prefixed matrix parsing.
|
// Non-standard prefixed matrix parsing.
|
||||||
|
@ -1014,7 +1021,7 @@ ${helpers.predefined_type("scroll-snap-coordinate",
|
||||||
e: lengths[0].clone(),
|
e: lengths[0].clone(),
|
||||||
f: lengths[1].clone(),
|
f: lengths[1].clone(),
|
||||||
});
|
});
|
||||||
Ok(())
|
Ok(true)
|
||||||
}))
|
}))
|
||||||
},
|
},
|
||||||
"matrix3d" => {
|
"matrix3d" => {
|
||||||
|
@ -1023,7 +1030,7 @@ ${helpers.predefined_type("scroll-snap-coordinate",
|
||||||
if !prefixed {
|
if !prefixed {
|
||||||
let values = try!(input.parse_comma_separated(|i| specified::parse_number(context, i)));
|
let values = try!(input.parse_comma_separated(|i| specified::parse_number(context, i)));
|
||||||
if values.len() != 16 {
|
if values.len() != 16 {
|
||||||
return Err(())
|
return Err(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
result.push(SpecifiedOperation::Matrix3D {
|
result.push(SpecifiedOperation::Matrix3D {
|
||||||
|
@ -1032,7 +1039,7 @@ ${helpers.predefined_type("scroll-snap-coordinate",
|
||||||
m31: values[ 8], m32: values[ 9], m33: values[10], m34: values[11],
|
m31: values[ 8], m32: values[ 9], m33: values[10], m34: values[11],
|
||||||
m41: values[12], m42: values[13], m43: values[14], m44: values[15]
|
m41: values[12], m42: values[13], m43: values[14], m44: values[15]
|
||||||
});
|
});
|
||||||
return Ok(());
|
return Ok(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Non-standard prefixed matrix3d parsing.
|
// Non-standard prefixed matrix3d parsing.
|
||||||
|
@ -1069,7 +1076,7 @@ ${helpers.predefined_type("scroll-snap-coordinate",
|
||||||
m41: lops[0].clone(), m42: lops[1].clone(), m43: length_or_number.unwrap(),
|
m41: lops[0].clone(), m42: lops[1].clone(), m43: length_or_number.unwrap(),
|
||||||
m44: values[12]
|
m44: values[12]
|
||||||
});
|
});
|
||||||
Ok(())
|
Ok(true)
|
||||||
}))
|
}))
|
||||||
},
|
},
|
||||||
"translate" => {
|
"translate" => {
|
||||||
|
@ -1081,28 +1088,28 @@ ${helpers.predefined_type("scroll-snap-coordinate",
|
||||||
} else {
|
} else {
|
||||||
result.push(SpecifiedOperation::Translate(sx, None));
|
result.push(SpecifiedOperation::Translate(sx, None));
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(true)
|
||||||
}))
|
}))
|
||||||
},
|
},
|
||||||
"translatex" => {
|
"translatex" => {
|
||||||
try!(input.parse_nested_block(|input| {
|
try!(input.parse_nested_block(|input| {
|
||||||
let tx = try!(specified::LengthOrPercentage::parse(context, input));
|
let tx = try!(specified::LengthOrPercentage::parse(context, input));
|
||||||
result.push(SpecifiedOperation::TranslateX(tx));
|
result.push(SpecifiedOperation::TranslateX(tx));
|
||||||
Ok(())
|
Ok(true)
|
||||||
}))
|
}))
|
||||||
},
|
},
|
||||||
"translatey" => {
|
"translatey" => {
|
||||||
try!(input.parse_nested_block(|input| {
|
try!(input.parse_nested_block(|input| {
|
||||||
let ty = try!(specified::LengthOrPercentage::parse(context, input));
|
let ty = try!(specified::LengthOrPercentage::parse(context, input));
|
||||||
result.push(SpecifiedOperation::TranslateY(ty));
|
result.push(SpecifiedOperation::TranslateY(ty));
|
||||||
Ok(())
|
Ok(true)
|
||||||
}))
|
}))
|
||||||
},
|
},
|
||||||
"translatez" => {
|
"translatez" => {
|
||||||
try!(input.parse_nested_block(|input| {
|
try!(input.parse_nested_block(|input| {
|
||||||
let tz = try!(specified::Length::parse(context, input));
|
let tz = try!(specified::Length::parse(context, input));
|
||||||
result.push(SpecifiedOperation::TranslateZ(tz));
|
result.push(SpecifiedOperation::TranslateZ(tz));
|
||||||
Ok(())
|
Ok(true)
|
||||||
}))
|
}))
|
||||||
},
|
},
|
||||||
"translate3d" => {
|
"translate3d" => {
|
||||||
|
@ -1113,7 +1120,7 @@ ${helpers.predefined_type("scroll-snap-coordinate",
|
||||||
try!(input.expect_comma());
|
try!(input.expect_comma());
|
||||||
let tz = try!(specified::Length::parse(context, input));
|
let tz = try!(specified::Length::parse(context, input));
|
||||||
result.push(SpecifiedOperation::Translate3D(tx, ty, tz));
|
result.push(SpecifiedOperation::Translate3D(tx, ty, tz));
|
||||||
Ok(())
|
Ok(true)
|
||||||
}))
|
}))
|
||||||
},
|
},
|
||||||
"scale" => {
|
"scale" => {
|
||||||
|
@ -1125,28 +1132,28 @@ ${helpers.predefined_type("scroll-snap-coordinate",
|
||||||
} else {
|
} else {
|
||||||
result.push(SpecifiedOperation::Scale(sx, None));
|
result.push(SpecifiedOperation::Scale(sx, None));
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(true)
|
||||||
}))
|
}))
|
||||||
},
|
},
|
||||||
"scalex" => {
|
"scalex" => {
|
||||||
try!(input.parse_nested_block(|input| {
|
try!(input.parse_nested_block(|input| {
|
||||||
let sx = try!(specified::parse_number(context, input));
|
let sx = try!(specified::parse_number(context, input));
|
||||||
result.push(SpecifiedOperation::ScaleX(sx));
|
result.push(SpecifiedOperation::ScaleX(sx));
|
||||||
Ok(())
|
Ok(true)
|
||||||
}))
|
}))
|
||||||
},
|
},
|
||||||
"scaley" => {
|
"scaley" => {
|
||||||
try!(input.parse_nested_block(|input| {
|
try!(input.parse_nested_block(|input| {
|
||||||
let sy = try!(specified::parse_number(context, input));
|
let sy = try!(specified::parse_number(context, input));
|
||||||
result.push(SpecifiedOperation::ScaleY(sy));
|
result.push(SpecifiedOperation::ScaleY(sy));
|
||||||
Ok(())
|
Ok(true)
|
||||||
}))
|
}))
|
||||||
},
|
},
|
||||||
"scalez" => {
|
"scalez" => {
|
||||||
try!(input.parse_nested_block(|input| {
|
try!(input.parse_nested_block(|input| {
|
||||||
let sz = try!(specified::parse_number(context, input));
|
let sz = try!(specified::parse_number(context, input));
|
||||||
result.push(SpecifiedOperation::ScaleZ(sz));
|
result.push(SpecifiedOperation::ScaleZ(sz));
|
||||||
Ok(())
|
Ok(true)
|
||||||
}))
|
}))
|
||||||
},
|
},
|
||||||
"scale3d" => {
|
"scale3d" => {
|
||||||
|
@ -1157,35 +1164,35 @@ ${helpers.predefined_type("scroll-snap-coordinate",
|
||||||
try!(input.expect_comma());
|
try!(input.expect_comma());
|
||||||
let sz = try!(specified::parse_number(context, input));
|
let sz = try!(specified::parse_number(context, input));
|
||||||
result.push(SpecifiedOperation::Scale3D(sx, sy, sz));
|
result.push(SpecifiedOperation::Scale3D(sx, sy, sz));
|
||||||
Ok(())
|
Ok(true)
|
||||||
}))
|
}))
|
||||||
},
|
},
|
||||||
"rotate" => {
|
"rotate" => {
|
||||||
try!(input.parse_nested_block(|input| {
|
try!(input.parse_nested_block(|input| {
|
||||||
let theta = try!(specified::Angle::parse_with_unitless(context, input));
|
let theta = try!(specified::Angle::parse_with_unitless(context, input));
|
||||||
result.push(SpecifiedOperation::Rotate(theta));
|
result.push(SpecifiedOperation::Rotate(theta));
|
||||||
Ok(())
|
Ok(true)
|
||||||
}))
|
}))
|
||||||
},
|
},
|
||||||
"rotatex" => {
|
"rotatex" => {
|
||||||
try!(input.parse_nested_block(|input| {
|
try!(input.parse_nested_block(|input| {
|
||||||
let theta = try!(specified::Angle::parse_with_unitless(context, input));
|
let theta = try!(specified::Angle::parse_with_unitless(context, input));
|
||||||
result.push(SpecifiedOperation::RotateX(theta));
|
result.push(SpecifiedOperation::RotateX(theta));
|
||||||
Ok(())
|
Ok(true)
|
||||||
}))
|
}))
|
||||||
},
|
},
|
||||||
"rotatey" => {
|
"rotatey" => {
|
||||||
try!(input.parse_nested_block(|input| {
|
try!(input.parse_nested_block(|input| {
|
||||||
let theta = try!(specified::Angle::parse_with_unitless(context, input));
|
let theta = try!(specified::Angle::parse_with_unitless(context, input));
|
||||||
result.push(SpecifiedOperation::RotateY(theta));
|
result.push(SpecifiedOperation::RotateY(theta));
|
||||||
Ok(())
|
Ok(true)
|
||||||
}))
|
}))
|
||||||
},
|
},
|
||||||
"rotatez" => {
|
"rotatez" => {
|
||||||
try!(input.parse_nested_block(|input| {
|
try!(input.parse_nested_block(|input| {
|
||||||
let theta = try!(specified::Angle::parse_with_unitless(context, input));
|
let theta = try!(specified::Angle::parse_with_unitless(context, input));
|
||||||
result.push(SpecifiedOperation::RotateZ(theta));
|
result.push(SpecifiedOperation::RotateZ(theta));
|
||||||
Ok(())
|
Ok(true)
|
||||||
}))
|
}))
|
||||||
},
|
},
|
||||||
"rotate3d" => {
|
"rotate3d" => {
|
||||||
|
@ -1199,7 +1206,7 @@ ${helpers.predefined_type("scroll-snap-coordinate",
|
||||||
let theta = try!(specified::Angle::parse_with_unitless(context, input));
|
let theta = try!(specified::Angle::parse_with_unitless(context, input));
|
||||||
// TODO(gw): Check the axis can be normalized!!
|
// TODO(gw): Check the axis can be normalized!!
|
||||||
result.push(SpecifiedOperation::Rotate3D(ax, ay, az, theta));
|
result.push(SpecifiedOperation::Rotate3D(ax, ay, az, theta));
|
||||||
Ok(())
|
Ok(true)
|
||||||
}))
|
}))
|
||||||
},
|
},
|
||||||
"skew" => {
|
"skew" => {
|
||||||
|
@ -1211,51 +1218,56 @@ ${helpers.predefined_type("scroll-snap-coordinate",
|
||||||
} else {
|
} else {
|
||||||
result.push(SpecifiedOperation::Skew(theta_x, None));
|
result.push(SpecifiedOperation::Skew(theta_x, None));
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(true)
|
||||||
}))
|
}))
|
||||||
},
|
},
|
||||||
"skewx" => {
|
"skewx" => {
|
||||||
try!(input.parse_nested_block(|input| {
|
try!(input.parse_nested_block(|input| {
|
||||||
let theta_x = try!(specified::Angle::parse_with_unitless(context, input));
|
let theta_x = try!(specified::Angle::parse_with_unitless(context, input));
|
||||||
result.push(SpecifiedOperation::SkewX(theta_x));
|
result.push(SpecifiedOperation::SkewX(theta_x));
|
||||||
Ok(())
|
Ok(true)
|
||||||
}))
|
}))
|
||||||
},
|
},
|
||||||
"skewy" => {
|
"skewy" => {
|
||||||
try!(input.parse_nested_block(|input| {
|
try!(input.parse_nested_block(|input| {
|
||||||
let theta_y = try!(specified::Angle::parse_with_unitless(context, input));
|
let theta_y = try!(specified::Angle::parse_with_unitless(context, input));
|
||||||
result.push(SpecifiedOperation::SkewY(theta_y));
|
result.push(SpecifiedOperation::SkewY(theta_y));
|
||||||
Ok(())
|
Ok(true)
|
||||||
}))
|
}))
|
||||||
},
|
},
|
||||||
"perspective" => {
|
"perspective" => {
|
||||||
try!(input.parse_nested_block(|input| {
|
try!(input.parse_nested_block(|input| {
|
||||||
let d = try!(specified::Length::parse_non_negative(context, input));
|
let d = try!(specified::Length::parse_non_negative(context, input));
|
||||||
result.push(SpecifiedOperation::Perspective(d));
|
result.push(SpecifiedOperation::Perspective(d));
|
||||||
Ok(())
|
Ok(true)
|
||||||
}))
|
}))
|
||||||
},
|
},
|
||||||
_ => return Err(())
|
_ => false
|
||||||
|
};
|
||||||
|
if !valid_fn {
|
||||||
|
return Err(StyleParseError::UnexpectedFunction(name).into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !result.is_empty() {
|
if !result.is_empty() {
|
||||||
Ok(SpecifiedValue(result))
|
Ok(SpecifiedValue(result))
|
||||||
} else {
|
} else {
|
||||||
Err(())
|
Err(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses `transform` property.
|
/// Parses `transform` property.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue,()> {
|
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<SpecifiedValue,ParseError<'i>> {
|
||||||
parse_internal(context, input, false)
|
parse_internal(context, input, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses `-moz-transform` property. This prefixed property also accepts LengthOrPercentage
|
/// Parses `-moz-transform` property. This prefixed property also accepts LengthOrPercentage
|
||||||
/// in the nondiagonal homogeneous components of matrix and matrix3d.
|
/// in the nondiagonal homogeneous components of matrix and matrix3d.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn parse_prefixed(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue,()> {
|
pub fn parse_prefixed<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<SpecifiedValue,ParseError<'i>> {
|
||||||
parse_internal(context, input, true)
|
parse_internal(context, input, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1771,7 +1783,8 @@ ${helpers.predefined_type("transform-origin",
|
||||||
}
|
}
|
||||||
|
|
||||||
/// none | strict | content | [ size || layout || style || paint ]
|
/// none | strict | content | [ size || layout || style || paint ]
|
||||||
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||||
let mut result = SpecifiedValue::empty();
|
let mut result = SpecifiedValue::empty();
|
||||||
|
|
||||||
if input.try(|input| input.expect_ident_matching("none")).is_ok() {
|
if input.try(|input| input.expect_ident_matching("none")).is_ok() {
|
||||||
|
@ -1784,21 +1797,22 @@ ${helpers.predefined_type("transform-origin",
|
||||||
|
|
||||||
while let Ok(name) = input.try(|input| input.expect_ident()) {
|
while let Ok(name) = input.try(|input| input.expect_ident()) {
|
||||||
let flag = match_ignore_ascii_case! { &name,
|
let flag = match_ignore_ascii_case! { &name,
|
||||||
"layout" => LAYOUT,
|
"layout" => Some(LAYOUT),
|
||||||
"style" => STYLE,
|
"style" => Some(STYLE),
|
||||||
"paint" => PAINT,
|
"paint" => Some(PAINT),
|
||||||
_ => return Err(())
|
_ => None
|
||||||
|
};
|
||||||
|
let flag = match flag {
|
||||||
|
Some(flag) if !result.contains(flag) => flag,
|
||||||
|
_ => return Err(SelectorParseError::UnexpectedIdent(name).into())
|
||||||
};
|
};
|
||||||
if result.contains(flag) {
|
|
||||||
return Err(())
|
|
||||||
}
|
|
||||||
result.insert(flag);
|
result.insert(flag);
|
||||||
}
|
}
|
||||||
|
|
||||||
if !result.is_empty() {
|
if !result.is_empty() {
|
||||||
Ok(result)
|
Ok(result)
|
||||||
} else {
|
} else {
|
||||||
Err(())
|
Err(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</%helpers:longhand>
|
</%helpers:longhand>
|
||||||
|
@ -1900,18 +1914,23 @@ ${helpers.single_keyword("-moz-orient",
|
||||||
}
|
}
|
||||||
|
|
||||||
/// auto | <animateable-feature>#
|
/// auto | <animateable-feature>#
|
||||||
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||||
if input.try(|input| input.expect_ident_matching("auto")).is_ok() {
|
if input.try(|input| input.expect_ident_matching("auto")).is_ok() {
|
||||||
Ok(computed_value::T::Auto)
|
Ok(computed_value::T::Auto)
|
||||||
} else {
|
} else {
|
||||||
input.parse_comma_separated(|i| {
|
input.parse_comma_separated(|i| {
|
||||||
let ident = i.expect_ident()?;
|
let ident = i.expect_ident()?;
|
||||||
match_ignore_ascii_case! { &ident,
|
let bad_keyword = match_ignore_ascii_case! { &ident,
|
||||||
"will-change" | "none" | "all" | "auto" |
|
"will-change" | "none" | "all" | "auto" |
|
||||||
"initial" | "inherit" | "unset" | "default" => return Err(()),
|
"initial" | "inherit" | "unset" | "default" => true,
|
||||||
_ => {},
|
_ => false,
|
||||||
|
};
|
||||||
|
if bad_keyword {
|
||||||
|
Err(SelectorParseError::UnexpectedIdent(ident.into()).into())
|
||||||
|
} else {
|
||||||
|
Ok(Atom::from(ident))
|
||||||
}
|
}
|
||||||
Ok((Atom::from(ident)))
|
|
||||||
}).map(SpecifiedValue::AnimateableFeatures)
|
}).map(SpecifiedValue::AnimateableFeatures)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1976,9 +1995,10 @@ ${helpers.predefined_type("shape-outside", "basic_shape::FloatAreaShape",
|
||||||
TOUCH_ACTION_AUTO
|
TOUCH_ACTION_AUTO
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||||
let ident = input.expect_ident()?;
|
let ident = input.expect_ident()?;
|
||||||
match_ignore_ascii_case! { &ident,
|
(match_ignore_ascii_case! { &ident,
|
||||||
"auto" => Ok(TOUCH_ACTION_AUTO),
|
"auto" => Ok(TOUCH_ACTION_AUTO),
|
||||||
"none" => Ok(TOUCH_ACTION_NONE),
|
"none" => Ok(TOUCH_ACTION_NONE),
|
||||||
"manipulation" => Ok(TOUCH_ACTION_MANIPULATION),
|
"manipulation" => Ok(TOUCH_ACTION_MANIPULATION),
|
||||||
|
@ -1997,6 +2017,6 @@ ${helpers.predefined_type("shape-outside", "basic_shape::FloatAreaShape",
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
_ => Err(()),
|
_ => Err(()),
|
||||||
}
|
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
|
||||||
}
|
}
|
||||||
</%helpers:longhand>
|
</%helpers:longhand>
|
||||||
|
|
|
@ -43,7 +43,8 @@
|
||||||
pub fn get_initial_value() -> computed_value::T {
|
pub fn get_initial_value() -> computed_value::T {
|
||||||
RGBA::new(0, 0, 0, 255) // black
|
RGBA::new(0, 0, 0, 255) // black
|
||||||
}
|
}
|
||||||
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||||
Color::parse_quirky(context, input, AllowQuirks::Yes).map(SpecifiedValue)
|
Color::parse_quirky(context, input, AllowQuirks::Yes).map(SpecifiedValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,7 +119,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SystemColor {
|
impl SystemColor {
|
||||||
pub fn parse(input: &mut Parser) -> Result<Self, ()> {
|
pub fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
use std::ascii::AsciiExt;
|
use std::ascii::AsciiExt;
|
||||||
static PARSE_ARRAY: &'static [(&'static str, SystemColor); ${len(system_colors)}] = &[
|
static PARSE_ARRAY: &'static [(&'static str, SystemColor); ${len(system_colors)}] = &[
|
||||||
|
@ -133,7 +134,7 @@
|
||||||
return Ok(color)
|
return Ok(color)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(())
|
Err(SelectorParseError::UnexpectedIdent(ident).into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
% endif
|
% endif
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
|
|
||||||
<%helpers:longhand name="content" boxed="True" animation_value_type="none"
|
<%helpers:longhand name="content" boxed="True" animation_value_type="none"
|
||||||
spec="https://drafts.csswg.org/css-content/#propdef-content">
|
spec="https://drafts.csswg.org/css-content/#propdef-content">
|
||||||
use cssparser::Token;
|
|
||||||
use values::computed::ComputedValueAsSpecified;
|
use values::computed::ComputedValueAsSpecified;
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
use values::generics::CounterStyleOrNone;
|
use values::generics::CounterStyleOrNone;
|
||||||
|
@ -157,8 +156,8 @@
|
||||||
// normal | none | [ <string> | <counter> | open-quote | close-quote | no-open-quote |
|
// normal | none | [ <string> | <counter> | open-quote | close-quote | no-open-quote |
|
||||||
// no-close-quote ]+
|
// no-close-quote ]+
|
||||||
// TODO: <uri>, attr(<identifier>)
|
// TODO: <uri>, attr(<identifier>)
|
||||||
pub fn parse(context: &ParserContext, input: &mut Parser)
|
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
-> Result<SpecifiedValue, ()> {
|
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||||
if input.try(|input| input.expect_ident_matching("normal")).is_ok() {
|
if input.try(|input| input.expect_ident_matching("normal")).is_ok() {
|
||||||
return Ok(SpecifiedValue::Normal)
|
return Ok(SpecifiedValue::Normal)
|
||||||
}
|
}
|
||||||
|
@ -185,43 +184,50 @@
|
||||||
content.push(ContentItem::String(value.into_owned()))
|
content.push(ContentItem::String(value.into_owned()))
|
||||||
}
|
}
|
||||||
Ok(Token::Function(name)) => {
|
Ok(Token::Function(name)) => {
|
||||||
content.push(try!(match_ignore_ascii_case! { &name,
|
let result = match_ignore_ascii_case! { &name,
|
||||||
"counter" => input.parse_nested_block(|input| {
|
"counter" => Some(input.parse_nested_block(|input| {
|
||||||
let name = try!(input.expect_ident()).into_owned();
|
let name = try!(input.expect_ident()).into_owned();
|
||||||
let style = parse_counter_style(context, input);
|
let style = parse_counter_style(context, input);
|
||||||
Ok(ContentItem::Counter(name, style))
|
Ok(ContentItem::Counter(name, style))
|
||||||
}),
|
})),
|
||||||
"counters" => input.parse_nested_block(|input| {
|
"counters" => Some(input.parse_nested_block(|input| {
|
||||||
let name = try!(input.expect_ident()).into_owned();
|
let name = try!(input.expect_ident()).into_owned();
|
||||||
try!(input.expect_comma());
|
try!(input.expect_comma());
|
||||||
let separator = try!(input.expect_string()).into_owned();
|
let separator = try!(input.expect_string()).into_owned();
|
||||||
let style = parse_counter_style(context, input);
|
let style = parse_counter_style(context, input);
|
||||||
Ok(ContentItem::Counters(name, separator, style))
|
Ok(ContentItem::Counters(name, separator, style))
|
||||||
}),
|
})),
|
||||||
% if product == "gecko":
|
% if product == "gecko":
|
||||||
"attr" => input.parse_nested_block(|input| {
|
"attr" => Some(input.parse_nested_block(|input| {
|
||||||
Ok(ContentItem::Attr(Attr::parse_function(context, input)?))
|
Ok(ContentItem::Attr(Attr::parse_function(context, input)?))
|
||||||
}),
|
})),
|
||||||
% endif
|
% endif
|
||||||
_ => return Err(())
|
_ => None
|
||||||
}));
|
};
|
||||||
|
match result {
|
||||||
|
Some(result) => content.push(try!(result)),
|
||||||
|
None => return Err(StyleParseError::UnexpectedFunction(name).into())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Ok(Token::Ident(ident)) => {
|
Ok(Token::Ident(ident)) => {
|
||||||
match_ignore_ascii_case! { &ident,
|
let valid = match_ignore_ascii_case! { &ident,
|
||||||
"open-quote" => content.push(ContentItem::OpenQuote),
|
"open-quote" => { content.push(ContentItem::OpenQuote); true },
|
||||||
"close-quote" => content.push(ContentItem::CloseQuote),
|
"close-quote" => { content.push(ContentItem::CloseQuote); true },
|
||||||
"no-open-quote" => content.push(ContentItem::NoOpenQuote),
|
"no-open-quote" => { content.push(ContentItem::NoOpenQuote); true },
|
||||||
"no-close-quote" => content.push(ContentItem::NoCloseQuote),
|
"no-close-quote" => { content.push(ContentItem::NoCloseQuote); true },
|
||||||
|
|
||||||
_ => return Err(())
|
_ => false,
|
||||||
|
};
|
||||||
|
if !valid {
|
||||||
|
return Err(SelectorParseError::UnexpectedIdent(ident).into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(_) => break,
|
Err(_) => break,
|
||||||
_ => return Err(())
|
Ok(t) => return Err(BasicParseError::UnexpectedToken(t).into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if content.is_empty() {
|
if content.is_empty() {
|
||||||
return Err(());
|
return Err(StyleParseError::UnspecifiedError.into());
|
||||||
}
|
}
|
||||||
Ok(SpecifiedValue::Items(content))
|
Ok(SpecifiedValue::Items(content))
|
||||||
}
|
}
|
||||||
|
@ -233,8 +239,6 @@
|
||||||
use style_traits::ToCss;
|
use style_traits::ToCss;
|
||||||
use values::CustomIdent;
|
use values::CustomIdent;
|
||||||
|
|
||||||
use cssparser::Token;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct SpecifiedValue(pub Vec<(CustomIdent, specified::Integer)>);
|
pub struct SpecifiedValue(pub Vec<(CustomIdent, specified::Integer)>);
|
||||||
|
|
||||||
|
@ -315,11 +319,13 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||||
parse_common(context, 1, input)
|
parse_common(context, 1, input)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_common(context: &ParserContext, default_value: i32, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
pub fn parse_common<'i, 't>(context: &ParserContext, default_value: i32, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||||
if input.try(|input| input.expect_ident_matching("none")).is_ok() {
|
if input.try(|input| input.expect_ident_matching("none")).is_ok() {
|
||||||
return Ok(SpecifiedValue(Vec::new()))
|
return Ok(SpecifiedValue(Vec::new()))
|
||||||
}
|
}
|
||||||
|
@ -328,7 +334,7 @@
|
||||||
loop {
|
loop {
|
||||||
let counter_name = match input.next() {
|
let counter_name = match input.next() {
|
||||||
Ok(Token::Ident(ident)) => CustomIdent::from_ident(ident, &["none"])?,
|
Ok(Token::Ident(ident)) => CustomIdent::from_ident(ident, &["none"])?,
|
||||||
Ok(_) => return Err(()),
|
Ok(t) => return Err(BasicParseError::UnexpectedToken(t).into()),
|
||||||
Err(_) => break,
|
Err(_) => break,
|
||||||
};
|
};
|
||||||
let counter_delta = input.try(|input| specified::parse_integer(context, input))
|
let counter_delta = input.try(|input| specified::parse_integer(context, input))
|
||||||
|
@ -339,7 +345,7 @@
|
||||||
if !counters.is_empty() {
|
if !counters.is_empty() {
|
||||||
Ok(SpecifiedValue(counters))
|
Ok(SpecifiedValue(counters))
|
||||||
} else {
|
} else {
|
||||||
Err(())
|
Err(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</%helpers:longhand>
|
</%helpers:longhand>
|
||||||
|
@ -349,7 +355,8 @@
|
||||||
pub use super::counter_increment::{SpecifiedValue, computed_value, get_initial_value};
|
pub use super::counter_increment::{SpecifiedValue, computed_value, get_initial_value};
|
||||||
use super::counter_increment::parse_common;
|
use super::counter_increment::parse_common;
|
||||||
|
|
||||||
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue,()> {
|
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<SpecifiedValue,ParseError<'i>> {
|
||||||
parse_common(context, 0, input)
|
parse_common(context, 0, input)
|
||||||
}
|
}
|
||||||
</%helpers:longhand>
|
</%helpers:longhand>
|
||||||
|
|
|
@ -27,7 +27,8 @@ ${helpers.predefined_type("opacity",
|
||||||
pub type T = Shadow;
|
pub type T = Shadow;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<specified::Shadow, ()> {
|
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<specified::Shadow, ParseError<'i>> {
|
||||||
specified::Shadow::parse(context, input, false)
|
specified::Shadow::parse(context, input, false)
|
||||||
}
|
}
|
||||||
</%helpers:vector_longhand>
|
</%helpers:vector_longhand>
|
||||||
|
@ -263,7 +264,8 @@ ${helpers.predefined_type("clip",
|
||||||
computed_value::T::new(Vec::new())
|
computed_value::T::new(Vec::new())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||||
let mut filters = Vec::new();
|
let mut filters = Vec::new();
|
||||||
if input.try(|input| input.expect_ident_matching("none")).is_ok() {
|
if input.try(|input| input.expect_ident_matching("none")).is_ok() {
|
||||||
return Ok(SpecifiedValue(filters))
|
return Ok(SpecifiedValue(filters))
|
||||||
|
@ -290,23 +292,24 @@ ${helpers.predefined_type("clip",
|
||||||
"drop-shadow" => specified::Shadow::parse(context, input, true)
|
"drop-shadow" => specified::Shadow::parse(context, input, true)
|
||||||
.map(SpecifiedFilter::DropShadow),
|
.map(SpecifiedFilter::DropShadow),
|
||||||
% endif
|
% endif
|
||||||
_ => Err(())
|
_ => Err(StyleParseError::UnexpectedFunction(function_name.clone()).into())
|
||||||
}
|
}
|
||||||
})));
|
})));
|
||||||
} else if filters.is_empty() {
|
} else if filters.is_empty() {
|
||||||
return Err(())
|
return Err(StyleParseError::UnspecifiedError.into())
|
||||||
} else {
|
} else {
|
||||||
return Ok(SpecifiedValue(filters))
|
return Ok(SpecifiedValue(filters))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_factor(input: &mut Parser) -> Result<::values::CSSFloat, ()> {
|
fn parse_factor<'i, 't>(input: &mut Parser<'i, 't>) -> Result<::values::CSSFloat, ParseError<'i>> {
|
||||||
use cssparser::Token;
|
use cssparser::Token;
|
||||||
match input.next() {
|
match input.next() {
|
||||||
Ok(Token::Number(value)) if value.value.is_sign_positive() => Ok(value.value),
|
Ok(Token::Number(value)) if value.value.is_sign_positive() => Ok(value.value),
|
||||||
Ok(Token::Percentage(value)) if value.unit_value.is_sign_positive() => Ok(value.unit_value),
|
Ok(Token::Percentage(value)) if value.unit_value.is_sign_positive() => Ok(value.unit_value),
|
||||||
_ => Err(())
|
Ok(t) => Err(BasicParseError::UnexpectedToken(t).into()),
|
||||||
|
Err(e) => Err(e.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -75,7 +75,7 @@
|
||||||
use cssparser::{CssStringWriter, Parser, serialize_identifier};
|
use cssparser::{CssStringWriter, Parser, serialize_identifier};
|
||||||
use std::fmt::{self, Write};
|
use std::fmt::{self, Write};
|
||||||
use Atom;
|
use Atom;
|
||||||
use style_traits::ToCss;
|
use style_traits::{ToCss, ParseError};
|
||||||
pub use self::FontFamily as SingleComputedValue;
|
pub use self::FontFamily as SingleComputedValue;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Clone, Hash)]
|
#[derive(Debug, PartialEq, Eq, Clone, Hash)]
|
||||||
|
@ -137,7 +137,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a font-family value
|
/// Parse a font-family value
|
||||||
pub fn parse(input: &mut Parser) -> Result<Self, ()> {
|
pub fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
if let Ok(value) = input.try(|input| input.expect_string()) {
|
if let Ok(value) = input.try(|input| input.expect_string()) {
|
||||||
return Ok(FontFamily::FamilyName(FamilyName {
|
return Ok(FontFamily::FamilyName(FamilyName {
|
||||||
name: Atom::from(&*value),
|
name: Atom::from(&*value),
|
||||||
|
@ -277,7 +277,8 @@
|
||||||
/// <family-name>#
|
/// <family-name>#
|
||||||
/// <family-name> = <string> | [ <ident>+ ]
|
/// <family-name> = <string> | [ <ident>+ ]
|
||||||
/// TODO: <generic-family>
|
/// TODO: <generic-family>
|
||||||
pub fn parse(_: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
pub fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||||
SpecifiedValue::parse(input)
|
SpecifiedValue::parse(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -331,7 +332,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse(input: &mut Parser) -> Result<Self, ()> {
|
pub fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
input.parse_comma_separated(|input| FontFamily::parse(input)).map(SpecifiedValue::Values)
|
input.parse_comma_separated(|input| FontFamily::parse(input)).map(SpecifiedValue::Values)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -357,11 +358,11 @@
|
||||||
/// `FamilyName::parse` is based on `FontFamily::parse` and not the other way around
|
/// `FamilyName::parse` is based on `FontFamily::parse` and not the other way around
|
||||||
/// because we want the former to exclude generic family keywords.
|
/// because we want the former to exclude generic family keywords.
|
||||||
impl Parse for FamilyName {
|
impl Parse for FamilyName {
|
||||||
fn parse(_: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
match FontFamily::parse(input) {
|
match FontFamily::parse(input) {
|
||||||
Ok(FontFamily::FamilyName(name)) => Ok(name),
|
Ok(FontFamily::FamilyName(name)) => Ok(name),
|
||||||
Ok(FontFamily::Generic(_)) |
|
Ok(FontFamily::Generic(_)) => Err(StyleParseError::UnspecifiedError.into()),
|
||||||
Err(()) => Err(())
|
Err(e) => Err(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -427,17 +428,21 @@ ${helpers.single_keyword_system("font-variant-caps",
|
||||||
}
|
}
|
||||||
|
|
||||||
/// normal | bold | bolder | lighter | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900
|
/// normal | bold | bolder | lighter | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900
|
||||||
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
input.try(|input| {
|
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||||
match_ignore_ascii_case! { &try!(input.expect_ident()),
|
let result: Result<_, ParseError> = input.try(|input| {
|
||||||
|
let ident = try!(input.expect_ident());
|
||||||
|
(match_ignore_ascii_case! { &ident,
|
||||||
"normal" => Ok(SpecifiedValue::Normal),
|
"normal" => Ok(SpecifiedValue::Normal),
|
||||||
"bold" => Ok(SpecifiedValue::Bold),
|
"bold" => Ok(SpecifiedValue::Bold),
|
||||||
"bolder" => Ok(SpecifiedValue::Bolder),
|
"bolder" => Ok(SpecifiedValue::Bolder),
|
||||||
"lighter" => Ok(SpecifiedValue::Lighter),
|
"lighter" => Ok(SpecifiedValue::Lighter),
|
||||||
_ => Err(())
|
_ => Err(())
|
||||||
}
|
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
|
||||||
}).or_else(|()| {
|
});
|
||||||
|
result.or_else(|_| {
|
||||||
SpecifiedValue::from_int(input.expect_integer()?)
|
SpecifiedValue::from_int(input.expect_integer()?)
|
||||||
|
.map_err(|()| StyleParseError::UnspecifiedError.into())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -472,7 +477,7 @@ ${helpers.single_keyword_system("font-variant-caps",
|
||||||
|
|
||||||
/// Used in @font-face, where relative keywords are not allowed.
|
/// Used in @font-face, where relative keywords are not allowed.
|
||||||
impl Parse for computed_value::T {
|
impl Parse for computed_value::T {
|
||||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
match parse(context, input)? {
|
match parse(context, input)? {
|
||||||
% for weight in range(100, 901, 100):
|
% for weight in range(100, 901, 100):
|
||||||
SpecifiedValue::Weight${weight} => Ok(computed_value::T::Weight${weight}),
|
SpecifiedValue::Weight${weight} => Ok(computed_value::T::Weight${weight}),
|
||||||
|
@ -480,7 +485,7 @@ ${helpers.single_keyword_system("font-variant-caps",
|
||||||
SpecifiedValue::Normal => Ok(computed_value::T::Weight400),
|
SpecifiedValue::Normal => Ok(computed_value::T::Weight400),
|
||||||
SpecifiedValue::Bold => Ok(computed_value::T::Weight700),
|
SpecifiedValue::Bold => Ok(computed_value::T::Weight700),
|
||||||
SpecifiedValue::Bolder |
|
SpecifiedValue::Bolder |
|
||||||
SpecifiedValue::Lighter => Err(()),
|
SpecifiedValue::Lighter => Err(StyleParseError::UnspecifiedError.into()),
|
||||||
SpecifiedValue::System(..) => unreachable!(),
|
SpecifiedValue::System(..) => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -666,17 +671,18 @@ ${helpers.single_keyword_system("font-variant-caps",
|
||||||
pub use self::KeywordSize::*;
|
pub use self::KeywordSize::*;
|
||||||
|
|
||||||
impl KeywordSize {
|
impl KeywordSize {
|
||||||
pub fn parse(input: &mut Parser) -> Result<Self, ()> {
|
pub fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
Ok(match_ignore_ascii_case! {&*input.expect_ident()?,
|
let ident = input.expect_ident()?;
|
||||||
"xx-small" => XXSmall,
|
(match_ignore_ascii_case! {&*ident,
|
||||||
"x-small" => XSmall,
|
"xx-small" => Ok(XXSmall),
|
||||||
"small" => Small,
|
"x-small" => Ok(XSmall),
|
||||||
"medium" => Medium,
|
"small" => Ok(Small),
|
||||||
"large" => Large,
|
"medium" => Ok(Medium),
|
||||||
"x-large" => XLarge,
|
"large" => Ok(Large),
|
||||||
"xx-large" => XXLarge,
|
"x-large" => Ok(XLarge),
|
||||||
_ => return Err(())
|
"xx-large" => Ok(XXLarge),
|
||||||
})
|
_ => Err(())
|
||||||
|
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -889,15 +895,16 @@ ${helpers.single_keyword_system("font-variant-caps",
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <length> | <percentage> | <absolute-size> | <relative-size>
|
/// <length> | <percentage> | <absolute-size> | <relative-size>
|
||||||
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||||
parse_quirky(context, input, AllowQuirks::No)
|
parse_quirky(context, input, AllowQuirks::No)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses a font-size, with quirks.
|
/// Parses a font-size, with quirks.
|
||||||
pub fn parse_quirky(context: &ParserContext,
|
pub fn parse_quirky<'i, 't>(context: &ParserContext,
|
||||||
input: &mut Parser,
|
input: &mut Parser<'i, 't>,
|
||||||
allow_quirks: AllowQuirks)
|
allow_quirks: AllowQuirks)
|
||||||
-> Result<SpecifiedValue, ()> {
|
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||||
use self::specified::LengthOrPercentage;
|
use self::specified::LengthOrPercentage;
|
||||||
if let Ok(lop) = input.try(|i| LengthOrPercentage::parse_non_negative_quirky(context, i, allow_quirks)) {
|
if let Ok(lop) = input.try(|i| LengthOrPercentage::parse_non_negative_quirky(context, i, allow_quirks)) {
|
||||||
return Ok(SpecifiedValue::Length(lop))
|
return Ok(SpecifiedValue::Length(lop))
|
||||||
|
@ -907,11 +914,12 @@ ${helpers.single_keyword_system("font-variant-caps",
|
||||||
return Ok(SpecifiedValue::Keyword(kw, 1.))
|
return Ok(SpecifiedValue::Keyword(kw, 1.))
|
||||||
}
|
}
|
||||||
|
|
||||||
match_ignore_ascii_case! {&*input.expect_ident()?,
|
let ident = input.expect_ident()?;
|
||||||
|
(match_ignore_ascii_case! {&*ident,
|
||||||
"smaller" => Ok(SpecifiedValue::Smaller),
|
"smaller" => Ok(SpecifiedValue::Smaller),
|
||||||
"larger" => Ok(SpecifiedValue::Larger),
|
"larger" => Ok(SpecifiedValue::Larger),
|
||||||
_ => Err(())
|
_ => Err(())
|
||||||
}
|
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SpecifiedValue {
|
impl SpecifiedValue {
|
||||||
|
@ -1133,7 +1141,8 @@ ${helpers.single_keyword_system("font-variant-caps",
|
||||||
}
|
}
|
||||||
|
|
||||||
/// none | <number>
|
/// none | <number>
|
||||||
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||||
use values::specified::Number;
|
use values::specified::Number;
|
||||||
|
|
||||||
if input.try(|input| input.expect_ident_matching("none")).is_ok() {
|
if input.try(|input| input.expect_ident_matching("none")).is_ok() {
|
||||||
|
@ -1183,9 +1192,11 @@ ${helpers.single_keyword_system("font-variant-caps",
|
||||||
SpecifiedValue { weight: true, style: true }
|
SpecifiedValue { weight: true, style: true }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||||
let mut result = SpecifiedValue { weight: false, style: false };
|
let mut result = SpecifiedValue { weight: false, style: false };
|
||||||
match_ignore_ascii_case! { &try!(input.expect_ident()),
|
let ident = try!(input.expect_ident());
|
||||||
|
(match_ignore_ascii_case! { &ident,
|
||||||
"none" => Ok(result),
|
"none" => Ok(result),
|
||||||
"weight" => {
|
"weight" => {
|
||||||
result.weight = true;
|
result.weight = true;
|
||||||
|
@ -1202,7 +1213,7 @@ ${helpers.single_keyword_system("font-variant-caps",
|
||||||
Ok(result)
|
Ok(result)
|
||||||
},
|
},
|
||||||
_ => Err(())
|
_ => Err(())
|
||||||
}
|
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
|
||||||
}
|
}
|
||||||
</%helpers:longhand>
|
</%helpers:longhand>
|
||||||
|
|
||||||
|
@ -1319,7 +1330,8 @@ ${helpers.single_keyword_system("font-kerning",
|
||||||
/// swash(<feature-value-name>) ||
|
/// swash(<feature-value-name>) ||
|
||||||
/// ornaments(<feature-value-name>) ||
|
/// ornaments(<feature-value-name>) ||
|
||||||
/// annotation(<feature-value-name>) ]
|
/// annotation(<feature-value-name>) ]
|
||||||
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||||
let mut result = VariantAlternates::empty();
|
let mut result = VariantAlternates::empty();
|
||||||
|
|
||||||
if input.try(|input| input.expect_ident_matching("normal")).is_ok() {
|
if input.try(|input| input.expect_ident_matching("normal")).is_ok() {
|
||||||
|
@ -1328,25 +1340,26 @@ ${helpers.single_keyword_system("font-kerning",
|
||||||
|
|
||||||
while let Ok(ident) = input.try(|input| input.expect_ident()) {
|
while let Ok(ident) = input.try(|input| input.expect_ident()) {
|
||||||
let flag = match_ignore_ascii_case! { &ident,
|
let flag = match_ignore_ascii_case! { &ident,
|
||||||
"stylistic" => STYLISTIC,
|
"stylistic" => Some(STYLISTIC),
|
||||||
"historical-forms" => HISTORICAL_FORMS,
|
"historical-forms" => Some(HISTORICAL_FORMS),
|
||||||
"styleset" => STYLESET,
|
"styleset" => Some(STYLESET),
|
||||||
"character-variant" => CHARACTER_VARIANT,
|
"character-variant" => Some(CHARACTER_VARIANT),
|
||||||
"swash" => SWASH,
|
"swash" => Some(SWASH),
|
||||||
"ornaments" => ORNAMENTS,
|
"ornaments" => Some(ORNAMENTS),
|
||||||
"annotation" => ANNOTATION,
|
"annotation" => Some(ANNOTATION),
|
||||||
_ => return Err(()),
|
_ => None,
|
||||||
|
};
|
||||||
|
let flag = match flag {
|
||||||
|
Some(flag) if !result.intersects(flag) => flag,
|
||||||
|
_ => return Err(SelectorParseError::UnexpectedIdent(ident).into()),
|
||||||
};
|
};
|
||||||
if result.intersects(flag) {
|
|
||||||
return Err(())
|
|
||||||
}
|
|
||||||
result.insert(flag);
|
result.insert(flag);
|
||||||
}
|
}
|
||||||
|
|
||||||
if !result.is_empty() {
|
if !result.is_empty() {
|
||||||
Ok(SpecifiedValue::Value(result))
|
Ok(SpecifiedValue::Value(result))
|
||||||
} else {
|
} else {
|
||||||
Err(())
|
Err(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</%helpers:longhand>
|
</%helpers:longhand>
|
||||||
|
@ -1355,9 +1368,9 @@ ${helpers.single_keyword_system("font-kerning",
|
||||||
macro_rules! exclusive_value {
|
macro_rules! exclusive_value {
|
||||||
(($value:ident, $set:expr) => $ident:ident) => {
|
(($value:ident, $set:expr) => $ident:ident) => {
|
||||||
if $value.intersects($set) {
|
if $value.intersects($set) {
|
||||||
return Err(())
|
None
|
||||||
} else {
|
} else {
|
||||||
$ident
|
Some($ident)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1462,7 +1475,8 @@ macro_rules! exclusive_value {
|
||||||
/// <east-asian-width-values> = [ full-width | proportional-width ]
|
/// <east-asian-width-values> = [ full-width | proportional-width ]
|
||||||
<% east_asian_variant_values = "JIS78 | JIS83 | JIS90 | JIS04 | SIMPLIFIED | TRADITIONAL" %>
|
<% east_asian_variant_values = "JIS78 | JIS83 | JIS90 | JIS04 | SIMPLIFIED | TRADITIONAL" %>
|
||||||
<% east_asian_width_values = "FULL_WIDTH | PROPORTIONAL_WIDTH" %>
|
<% east_asian_width_values = "FULL_WIDTH | PROPORTIONAL_WIDTH" %>
|
||||||
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||||
let mut result = VariantEastAsian::empty();
|
let mut result = VariantEastAsian::empty();
|
||||||
|
|
||||||
if input.try(|input| input.expect_ident_matching("normal")).is_ok() {
|
if input.try(|input| input.expect_ident_matching("normal")).is_ok() {
|
||||||
|
@ -1489,7 +1503,11 @@ macro_rules! exclusive_value {
|
||||||
exclusive_value!((result, ${east_asian_width_values}) => PROPORTIONAL_WIDTH),
|
exclusive_value!((result, ${east_asian_width_values}) => PROPORTIONAL_WIDTH),
|
||||||
"ruby" =>
|
"ruby" =>
|
||||||
exclusive_value!((result, RUBY) => RUBY),
|
exclusive_value!((result, RUBY) => RUBY),
|
||||||
_ => return Err(()),
|
_ => None,
|
||||||
|
};
|
||||||
|
let flag = match flag {
|
||||||
|
Some(flag) => flag,
|
||||||
|
None => return Err(SelectorParseError::UnexpectedIdent(ident).into()),
|
||||||
};
|
};
|
||||||
result.insert(flag);
|
result.insert(flag);
|
||||||
}
|
}
|
||||||
|
@ -1497,7 +1515,7 @@ macro_rules! exclusive_value {
|
||||||
if !result.is_empty() {
|
if !result.is_empty() {
|
||||||
Ok(SpecifiedValue::Value(result))
|
Ok(SpecifiedValue::Value(result))
|
||||||
} else {
|
} else {
|
||||||
Err(())
|
Err(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</%helpers:longhand>
|
</%helpers:longhand>
|
||||||
|
@ -1611,7 +1629,8 @@ macro_rules! exclusive_value {
|
||||||
<% discretionary_lig_values = "DISCRETIONARY_LIGATURES | NO_DISCRETIONARY_LIGATURES" %>
|
<% discretionary_lig_values = "DISCRETIONARY_LIGATURES | NO_DISCRETIONARY_LIGATURES" %>
|
||||||
<% historical_lig_values = "HISTORICAL_LIGATURES | NO_HISTORICAL_LIGATURES" %>
|
<% historical_lig_values = "HISTORICAL_LIGATURES | NO_HISTORICAL_LIGATURES" %>
|
||||||
<% contextual_alt_values = "CONTEXTUAL | NO_CONTEXTUAL" %>
|
<% contextual_alt_values = "CONTEXTUAL | NO_CONTEXTUAL" %>
|
||||||
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||||
let mut result = VariantLigatures::empty();
|
let mut result = VariantLigatures::empty();
|
||||||
|
|
||||||
if input.try(|input| input.expect_ident_matching("normal")).is_ok() {
|
if input.try(|input| input.expect_ident_matching("normal")).is_ok() {
|
||||||
|
@ -1639,7 +1658,11 @@ macro_rules! exclusive_value {
|
||||||
exclusive_value!((result, ${contextual_alt_values}) => CONTEXTUAL),
|
exclusive_value!((result, ${contextual_alt_values}) => CONTEXTUAL),
|
||||||
"no-contextual" =>
|
"no-contextual" =>
|
||||||
exclusive_value!((result, ${contextual_alt_values}) => NO_CONTEXTUAL),
|
exclusive_value!((result, ${contextual_alt_values}) => NO_CONTEXTUAL),
|
||||||
_ => return Err(()),
|
_ => None,
|
||||||
|
};
|
||||||
|
let flag = match flag {
|
||||||
|
Some(flag) => flag,
|
||||||
|
None => return Err(SelectorParseError::UnexpectedIdent(ident).into()),
|
||||||
};
|
};
|
||||||
result.insert(flag);
|
result.insert(flag);
|
||||||
}
|
}
|
||||||
|
@ -1647,7 +1670,7 @@ macro_rules! exclusive_value {
|
||||||
if !result.is_empty() {
|
if !result.is_empty() {
|
||||||
Ok(SpecifiedValue::Value(result))
|
Ok(SpecifiedValue::Value(result))
|
||||||
} else {
|
} else {
|
||||||
Err(())
|
Err(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</%helpers:longhand>
|
</%helpers:longhand>
|
||||||
|
@ -1757,7 +1780,8 @@ macro_rules! exclusive_value {
|
||||||
<% numeric_figure_values = "LINING_NUMS | OLDSTYLE_NUMS" %>
|
<% numeric_figure_values = "LINING_NUMS | OLDSTYLE_NUMS" %>
|
||||||
<% numeric_spacing_values = "PROPORTIONAL_NUMS | TABULAR_NUMS" %>
|
<% numeric_spacing_values = "PROPORTIONAL_NUMS | TABULAR_NUMS" %>
|
||||||
<% numeric_fraction_values = "DIAGONAL_FRACTIONS | STACKED_FRACTIONS" %>
|
<% numeric_fraction_values = "DIAGONAL_FRACTIONS | STACKED_FRACTIONS" %>
|
||||||
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||||
let mut result = VariantNumeric::empty();
|
let mut result = VariantNumeric::empty();
|
||||||
|
|
||||||
if input.try(|input| input.expect_ident_matching("normal")).is_ok() {
|
if input.try(|input| input.expect_ident_matching("normal")).is_ok() {
|
||||||
|
@ -1773,16 +1797,20 @@ macro_rules! exclusive_value {
|
||||||
"lining-nums" =>
|
"lining-nums" =>
|
||||||
exclusive_value!((result, ${numeric_figure_values}) => LINING_NUMS ),
|
exclusive_value!((result, ${numeric_figure_values}) => LINING_NUMS ),
|
||||||
"oldstyle-nums" =>
|
"oldstyle-nums" =>
|
||||||
exclusive_value!((result, ${numeric_figure_values}) => OLDSTYLE_NUMS ),
|
exclusive_value!((result, ${numeric_figure_values}) => OLDSTYLE_NUMS),
|
||||||
"proportional-nums" =>
|
"proportional-nums" =>
|
||||||
exclusive_value!((result, ${numeric_spacing_values}) => PROPORTIONAL_NUMS ),
|
exclusive_value!((result, ${numeric_spacing_values}) => PROPORTIONAL_NUMS),
|
||||||
"tabular-nums" =>
|
"tabular-nums" =>
|
||||||
exclusive_value!((result, ${numeric_spacing_values}) => TABULAR_NUMS ),
|
exclusive_value!((result, ${numeric_spacing_values}) => TABULAR_NUMS),
|
||||||
"diagonal-fractions" =>
|
"diagonal-fractions" =>
|
||||||
exclusive_value!((result, ${numeric_fraction_values}) => DIAGONAL_FRACTIONS ),
|
exclusive_value!((result, ${numeric_fraction_values}) => DIAGONAL_FRACTIONS),
|
||||||
"stacked-fractions" =>
|
"stacked-fractions" =>
|
||||||
exclusive_value!((result, ${numeric_fraction_values}) => STACKED_FRACTIONS ),
|
exclusive_value!((result, ${numeric_fraction_values}) => STACKED_FRACTIONS),
|
||||||
_ => return Err(()),
|
_ => None,
|
||||||
|
};
|
||||||
|
let flag = match flag {
|
||||||
|
Some(flag) => flag,
|
||||||
|
None => return Err(SelectorParseError::UnexpectedIdent(ident).into()),
|
||||||
};
|
};
|
||||||
result.insert(flag);
|
result.insert(flag);
|
||||||
}
|
}
|
||||||
|
@ -1790,7 +1818,7 @@ macro_rules! exclusive_value {
|
||||||
if !result.is_empty() {
|
if !result.is_empty() {
|
||||||
Ok(SpecifiedValue::Value(result))
|
Ok(SpecifiedValue::Value(result))
|
||||||
} else {
|
} else {
|
||||||
Err(())
|
Err(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</%helpers:longhand>
|
</%helpers:longhand>
|
||||||
|
@ -1836,7 +1864,8 @@ ${helpers.single_keyword_system("font-variant-position",
|
||||||
}
|
}
|
||||||
|
|
||||||
/// normal | <feature-tag-value>#
|
/// normal | <feature-tag-value>#
|
||||||
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||||
computed_value::T::parse(context, input).map(SpecifiedValue::Value)
|
computed_value::T::parse(context, input).map(SpecifiedValue::Value)
|
||||||
}
|
}
|
||||||
</%helpers:longhand>
|
</%helpers:longhand>
|
||||||
|
@ -1870,7 +1899,8 @@ https://drafts.csswg.org/css-fonts-4/#low-level-font-variation-settings-control-
|
||||||
}
|
}
|
||||||
|
|
||||||
/// normal | <feature-tag-value>#
|
/// normal | <feature-tag-value>#
|
||||||
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||||
computed_value::T::parse(context, input)
|
computed_value::T::parse(context, input)
|
||||||
}
|
}
|
||||||
</%helpers:longhand>
|
</%helpers:longhand>
|
||||||
|
@ -2000,13 +2030,14 @@ https://drafts.csswg.org/css-fonts-4/#low-level-font-variation-settings-control-
|
||||||
}
|
}
|
||||||
|
|
||||||
/// normal | <string>
|
/// normal | <string>
|
||||||
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||||
if input.try(|input| input.expect_ident_matching("normal")).is_ok() {
|
if input.try(|input| input.expect_ident_matching("normal")).is_ok() {
|
||||||
Ok(SpecifiedValue::Normal)
|
Ok(SpecifiedValue::Normal)
|
||||||
} else {
|
} else {
|
||||||
input.expect_string().map(|cow| {
|
input.expect_string().map(|cow| {
|
||||||
SpecifiedValue::Override(cow.into_owned())
|
SpecifiedValue::Override(cow.into_owned())
|
||||||
})
|
}).map_err(|e| e.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</%helpers:longhand>
|
</%helpers:longhand>
|
||||||
|
@ -2040,9 +2071,10 @@ https://drafts.csswg.org/css-fonts-4/#low-level-font-variation-settings-control-
|
||||||
computed_value::T(atom!(""))
|
computed_value::T(atom!(""))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse(_context: &ParserContext, _input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
pub fn parse<'i, 't>(_context: &ParserContext, _input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||||
debug_assert!(false, "Should be set directly by presentation attributes only.");
|
debug_assert!(false, "Should be set directly by presentation attributes only.");
|
||||||
Err(())
|
Err(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
</%helpers:longhand>
|
</%helpers:longhand>
|
||||||
|
|
||||||
|
@ -2065,9 +2097,10 @@ https://drafts.csswg.org/css-fonts-4/#low-level-font-variation-settings-control-
|
||||||
::gecko_bindings::structs::NS_MATHML_DEFAULT_SCRIPT_SIZE_MULTIPLIER as f32
|
::gecko_bindings::structs::NS_MATHML_DEFAULT_SCRIPT_SIZE_MULTIPLIER as f32
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse(_context: &ParserContext, _input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
pub fn parse<'i, 't>(_context: &ParserContext, _input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||||
debug_assert!(false, "Should be set directly by presentation attributes only.");
|
debug_assert!(false, "Should be set directly by presentation attributes only.");
|
||||||
Err(())
|
Err(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
</%helpers:longhand>
|
</%helpers:longhand>
|
||||||
|
|
||||||
|
@ -2138,7 +2171,8 @@ https://drafts.csswg.org/css-fonts-4/#low-level-font-variation-settings-control-
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||||
if let Ok(i) = input.try(|i| i.expect_integer()) {
|
if let Ok(i) = input.try(|i| i.expect_integer()) {
|
||||||
return Ok(SpecifiedValue::Relative(i))
|
return Ok(SpecifiedValue::Relative(i))
|
||||||
}
|
}
|
||||||
|
@ -2213,9 +2247,10 @@ ${helpers.single_keyword("-moz-math-variant",
|
||||||
Au((NS_MATHML_DEFAULT_SCRIPT_MIN_SIZE_PT as f32 * AU_PER_PT) as i32)
|
Au((NS_MATHML_DEFAULT_SCRIPT_MIN_SIZE_PT as f32 * AU_PER_PT) as i32)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse(_context: &ParserContext, _input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
pub fn parse<'i, 't>(_context: &ParserContext, _input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||||
debug_assert!(false, "Should be set directly by presentation attributes only.");
|
debug_assert!(false, "Should be set directly by presentation attributes only.");
|
||||||
Err(())
|
Err(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
</%helpers:longhand>
|
</%helpers:longhand>
|
||||||
|
|
||||||
|
@ -2240,7 +2275,9 @@ ${helpers.single_keyword("-moz-math-variant",
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
use cssparser::Parser;
|
use cssparser::Parser;
|
||||||
use properties::longhands;
|
use properties::longhands;
|
||||||
|
use selectors::parser::SelectorParseError;
|
||||||
use std::hash::{Hash, Hasher};
|
use std::hash::{Hash, Hasher};
|
||||||
|
use style_traits::ParseError;
|
||||||
use values::computed::{ToComputedValue, Context};
|
use values::computed::{ToComputedValue, Context};
|
||||||
<%
|
<%
|
||||||
system_fonts = """caption icon menu message-box small-caption status-bar
|
system_fonts = """caption icon menu message-box small-caption status-bar
|
||||||
|
@ -2359,13 +2396,14 @@ ${helpers.single_keyword("-moz-math-variant",
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SystemFont {
|
impl SystemFont {
|
||||||
pub fn parse(input: &mut Parser) -> Result<Self, ()> {
|
pub fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
Ok(match_ignore_ascii_case! { &*input.expect_ident()?,
|
let ident = input.expect_ident()?;
|
||||||
|
(match_ignore_ascii_case! { &*ident,
|
||||||
% for font in system_fonts:
|
% for font in system_fonts:
|
||||||
"${font}" => SystemFont::${to_camel_case(font)},
|
"${font}" => Ok(SystemFont::${to_camel_case(font)}),
|
||||||
% endfor
|
% endfor
|
||||||
_ => return Err(())
|
_ => Err(())
|
||||||
})
|
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -174,7 +174,8 @@ ${helpers.single_keyword("image-rendering",
|
||||||
}
|
}
|
||||||
|
|
||||||
// from-image | <angle> | [<angle>? flip]
|
// from-image | <angle> | [<angle>? flip]
|
||||||
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||||
if input.try(|input| input.expect_ident_matching("from-image")).is_ok() {
|
if input.try(|input| input.expect_ident_matching("from-image")).is_ok() {
|
||||||
// Handle from-image
|
// Handle from-image
|
||||||
Ok(SpecifiedValue { angle: None, flipped: false })
|
Ok(SpecifiedValue { angle: None, flipped: false })
|
||||||
|
@ -185,7 +186,7 @@ ${helpers.single_keyword("image-rendering",
|
||||||
// Handle <angle> | <angle> flip
|
// Handle <angle> | <angle> flip
|
||||||
let angle = input.try(|input| Angle::parse(context, input)).ok();
|
let angle = input.try(|input| Angle::parse(context, input)).ok();
|
||||||
if angle.is_none() {
|
if angle.is_none() {
|
||||||
return Err(());
|
return Err(StyleParseError::UnspecifiedError.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
let flipped = input.try(|input| input.expect_ident_matching("flip")).is_ok();
|
let flipped = input.try(|input| input.expect_ident_matching("flip")).is_ok();
|
||||||
|
|
|
@ -183,7 +183,8 @@ ${helpers.predefined_type("marker-end", "UrlOrNone", "Either::Second(None_)",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue,()> {
|
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<SpecifiedValue,ParseError<'i>> {
|
||||||
if let Ok(()) = input.try(|i| i.expect_ident_matching("normal")) {
|
if let Ok(()) = input.try(|i| i.expect_ident_matching("normal")) {
|
||||||
Ok(SpecifiedValue(0))
|
Ok(SpecifiedValue(0))
|
||||||
} else {
|
} else {
|
||||||
|
@ -195,33 +196,34 @@ ${helpers.predefined_type("marker-end", "UrlOrNone", "Either::Second(None_)",
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
|
|
||||||
let result = input.try(|i| {
|
let result: Result<_, ParseError> = input.try(|i| {
|
||||||
match_ignore_ascii_case! { &i.expect_ident()?,
|
let ident = i.expect_ident()?;
|
||||||
|
(match_ignore_ascii_case! { &ident,
|
||||||
"fill" => Ok(FILL),
|
"fill" => Ok(FILL),
|
||||||
"stroke" => Ok(STROKE),
|
"stroke" => Ok(STROKE),
|
||||||
"markers" => Ok(MARKERS),
|
"markers" => Ok(MARKERS),
|
||||||
_ => Err(())
|
_ => Err(())
|
||||||
}
|
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident.into()).into())
|
||||||
});
|
});
|
||||||
|
|
||||||
match result {
|
match result {
|
||||||
Ok(val) => {
|
Ok(val) => {
|
||||||
if (seen & (1 << val)) != 0 {
|
if (seen & (1 << val)) != 0 {
|
||||||
// don't parse the same ident twice
|
// don't parse the same ident twice
|
||||||
return Err(())
|
return Err(StyleParseError::UnspecifiedError.into())
|
||||||
} else {
|
} else {
|
||||||
value |= val << (pos * SHIFT);
|
value |= val << (pos * SHIFT);
|
||||||
seen |= 1 << val;
|
seen |= 1 << val;
|
||||||
pos += 1;
|
pos += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(()) => break,
|
Err(_) => break,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if value == 0 {
|
if value == 0 {
|
||||||
// couldn't find any keyword
|
// couldn't find any keyword
|
||||||
Err(())
|
Err(StyleParseError::UnspecifiedError.into())
|
||||||
} else {
|
} else {
|
||||||
// fill in rest
|
// fill in rest
|
||||||
for i in pos..COUNT {
|
for i in pos..COUNT {
|
||||||
|
@ -285,7 +287,8 @@ ${helpers.predefined_type("marker-end", "UrlOrNone", "Either::Second(None_)",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||||
let i = input.expect_ident()?;
|
let i = input.expect_ident()?;
|
||||||
CustomIdent::from_ident(i, &["all", "none", "auto"])
|
CustomIdent::from_ident(i, &["all", "none", "auto"])
|
||||||
}
|
}
|
||||||
|
|
|
@ -113,11 +113,12 @@ ${helpers.single_keyword("caption-side", "top bottom",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue,()> {
|
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<SpecifiedValue,ParseError<'i>> {
|
||||||
let mut first = None;
|
let mut first = None;
|
||||||
let mut second = None;
|
let mut second = None;
|
||||||
match Length::parse_non_negative_quirky(context, input, AllowQuirks::Yes) {
|
match Length::parse_non_negative_quirky(context, input, AllowQuirks::Yes) {
|
||||||
Err(()) => (),
|
Err(_) => (),
|
||||||
Ok(length) => {
|
Ok(length) => {
|
||||||
first = Some(length);
|
first = Some(length);
|
||||||
if let Ok(len) = input.try(|i| Length::parse_non_negative_quirky(context, i, AllowQuirks::Yes)) {
|
if let Ok(len) = input.try(|i| Length::parse_non_negative_quirky(context, i, AllowQuirks::Yes)) {
|
||||||
|
@ -126,7 +127,7 @@ ${helpers.single_keyword("caption-side", "top bottom",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
match (first, second) {
|
match (first, second) {
|
||||||
(None, None) => Err(()),
|
(None, None) => Err(StyleParseError::UnspecifiedError.into()),
|
||||||
(Some(length), None) => {
|
(Some(length), None) => {
|
||||||
Ok(SpecifiedValue {
|
Ok(SpecifiedValue {
|
||||||
horizontal: length,
|
horizontal: length,
|
||||||
|
|
|
@ -176,7 +176,8 @@ ${helpers.single_keyword("text-align-last",
|
||||||
MatchParent,
|
MatchParent,
|
||||||
MozCenterOrInherit,
|
MozCenterOrInherit,
|
||||||
}
|
}
|
||||||
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||||
// MozCenterOrInherit cannot be parsed, only set directly on th elements
|
// MozCenterOrInherit cannot be parsed, only set directly on th elements
|
||||||
if let Ok(key) = input.try(computed_value::T::parse) {
|
if let Ok(key) = input.try(computed_value::T::parse) {
|
||||||
Ok(SpecifiedValue::Keyword(key))
|
Ok(SpecifiedValue::Keyword(key))
|
||||||
|
@ -252,7 +253,8 @@ ${helpers.single_keyword("text-align-last",
|
||||||
use values::computed::ComputedValueAsSpecified;
|
use values::computed::ComputedValueAsSpecified;
|
||||||
impl ComputedValueAsSpecified for SpecifiedValue {}
|
impl ComputedValueAsSpecified for SpecifiedValue {}
|
||||||
pub use self::computed_value::T as SpecifiedValue;
|
pub use self::computed_value::T as SpecifiedValue;
|
||||||
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||||
computed_value::T::parse(input)
|
computed_value::T::parse(input)
|
||||||
}
|
}
|
||||||
% endif
|
% endif
|
||||||
|
@ -411,7 +413,8 @@ ${helpers.predefined_type("word-spacing",
|
||||||
pub type T = Shadow;
|
pub type T = Shadow;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<specified::Shadow, ()> {
|
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<specified::Shadow, ParseError<'i>> {
|
||||||
specified::Shadow::parse(context, input, true)
|
specified::Shadow::parse(context, input, true)
|
||||||
}
|
}
|
||||||
</%helpers:vector_longhand>
|
</%helpers:vector_longhand>
|
||||||
|
@ -573,7 +576,8 @@ ${helpers.predefined_type("word-spacing",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||||
if input.try(|input| input.expect_ident_matching("none")).is_ok() {
|
if input.try(|input| input.expect_ident_matching("none")).is_ok() {
|
||||||
return Ok(SpecifiedValue::None);
|
return Ok(SpecifiedValue::None);
|
||||||
}
|
}
|
||||||
|
@ -599,7 +603,7 @@ ${helpers.predefined_type("word-spacing",
|
||||||
(Some(fill), Ok(shape)) => KeywordValue::FillAndShape(fill,shape),
|
(Some(fill), Ok(shape)) => KeywordValue::FillAndShape(fill,shape),
|
||||||
(Some(fill), Err(_)) => KeywordValue::Fill(fill),
|
(Some(fill), Err(_)) => KeywordValue::Fill(fill),
|
||||||
(None, Ok(shape)) => KeywordValue::Shape(shape),
|
(None, Ok(shape)) => KeywordValue::Shape(shape),
|
||||||
_ => return Err(()),
|
_ => return Err(StyleParseError::UnspecifiedError.into()),
|
||||||
};
|
};
|
||||||
Ok(SpecifiedValue::Keyword(keyword_value))
|
Ok(SpecifiedValue::Keyword(keyword_value))
|
||||||
}
|
}
|
||||||
|
@ -632,7 +636,8 @@ ${helpers.predefined_type("word-spacing",
|
||||||
SpecifiedValue(HorizontalWritingModeValue::Over, VerticalWritingModeValue::Right)
|
SpecifiedValue(HorizontalWritingModeValue::Over, VerticalWritingModeValue::Right)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||||
if let Ok(horizontal) = input.try(|input| HorizontalWritingModeValue::parse(input)) {
|
if let Ok(horizontal) = input.try(|input| HorizontalWritingModeValue::parse(input)) {
|
||||||
let vertical = try!(VerticalWritingModeValue::parse(input));
|
let vertical = try!(VerticalWritingModeValue::parse(input));
|
||||||
Ok(SpecifiedValue(horizontal, vertical))
|
Ok(SpecifiedValue(horizontal, vertical))
|
||||||
|
|
|
@ -89,7 +89,8 @@ ${helpers.single_keyword("list-style-position", "outside inside", animation_valu
|
||||||
SpecifiedValue::CounterStyle(CounterStyleOrNone::disc())
|
SpecifiedValue::CounterStyle(CounterStyleOrNone::disc())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||||
Ok(if let Ok(style) = input.try(|i| CounterStyleOrNone::parse(context, i)) {
|
Ok(if let Ok(style) = input.try(|i| CounterStyleOrNone::parse(context, i)) {
|
||||||
SpecifiedValue::CounterStyle(style)
|
SpecifiedValue::CounterStyle(style)
|
||||||
} else {
|
} else {
|
||||||
|
@ -126,7 +127,8 @@ ${helpers.single_keyword("list-style-position", "outside inside", animation_valu
|
||||||
pub fn get_initial_specified_value() -> SpecifiedValue {
|
pub fn get_initial_specified_value() -> SpecifiedValue {
|
||||||
SpecifiedValue(Either::Second(None_))
|
SpecifiedValue(Either::Second(None_))
|
||||||
}
|
}
|
||||||
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue,()> {
|
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<SpecifiedValue,ParseError<'i>> {
|
||||||
% if product == "gecko":
|
% if product == "gecko":
|
||||||
let mut value = input.try(|input| UrlOrNone::parse(context, input))?;
|
let mut value = input.try(|input| UrlOrNone::parse(context, input))?;
|
||||||
if let Either::First(ref mut url) = value {
|
if let Either::First(ref mut url) = value {
|
||||||
|
@ -142,7 +144,6 @@ ${helpers.single_keyword("list-style-position", "outside inside", animation_valu
|
||||||
|
|
||||||
<%helpers:longhand name="quotes" animation_value_type="none"
|
<%helpers:longhand name="quotes" animation_value_type="none"
|
||||||
spec="https://drafts.csswg.org/css-content/#propdef-quotes">
|
spec="https://drafts.csswg.org/css-content/#propdef-quotes">
|
||||||
use cssparser::Token;
|
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use style_traits::ToCss;
|
use style_traits::ToCss;
|
||||||
|
@ -187,7 +188,8 @@ ${helpers.single_keyword("list-style-position", "outside inside", animation_valu
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse(_: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue,()> {
|
pub fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<SpecifiedValue,ParseError<'i>> {
|
||||||
if input.try(|input| input.expect_ident_matching("none")).is_ok() {
|
if input.try(|input| input.expect_ident_matching("none")).is_ok() {
|
||||||
return Ok(SpecifiedValue(Vec::new()))
|
return Ok(SpecifiedValue(Vec::new()))
|
||||||
}
|
}
|
||||||
|
@ -196,19 +198,20 @@ ${helpers.single_keyword("list-style-position", "outside inside", animation_valu
|
||||||
loop {
|
loop {
|
||||||
let first = match input.next() {
|
let first = match input.next() {
|
||||||
Ok(Token::QuotedString(value)) => value.into_owned(),
|
Ok(Token::QuotedString(value)) => value.into_owned(),
|
||||||
Ok(_) => return Err(()),
|
Ok(t) => return Err(BasicParseError::UnexpectedToken(t).into()),
|
||||||
Err(()) => break,
|
Err(_) => break,
|
||||||
};
|
};
|
||||||
let second = match input.next() {
|
let second = match input.next() {
|
||||||
Ok(Token::QuotedString(value)) => value.into_owned(),
|
Ok(Token::QuotedString(value)) => value.into_owned(),
|
||||||
_ => return Err(()),
|
Ok(t) => return Err(BasicParseError::UnexpectedToken(t).into()),
|
||||||
|
Err(e) => return Err(e.into()),
|
||||||
};
|
};
|
||||||
quotes.push((first, second))
|
quotes.push((first, second))
|
||||||
}
|
}
|
||||||
if !quotes.is_empty() {
|
if !quotes.is_empty() {
|
||||||
Ok(SpecifiedValue(quotes))
|
Ok(SpecifiedValue(quotes))
|
||||||
} else {
|
} else {
|
||||||
Err(())
|
Err(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</%helpers:longhand>
|
</%helpers:longhand>
|
||||||
|
|
|
@ -46,14 +46,15 @@ ${helpers.predefined_type("outline-color", "Color", "computed_value::T::currentc
|
||||||
pub type T = super::SpecifiedValue;
|
pub type T = super::SpecifiedValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||||
SpecifiedValue::parse(context, input)
|
SpecifiedValue::parse(context, input)
|
||||||
.and_then(|result| {
|
.and_then(|result| {
|
||||||
if let Either::Second(BorderStyle::hidden) = result {
|
if let Either::Second(BorderStyle::hidden) = result {
|
||||||
// The outline-style property accepts the same values as
|
// The outline-style property accepts the same values as
|
||||||
// border-style, except that 'hidden' is not a legal outline
|
// border-style, except that 'hidden' is not a legal outline
|
||||||
// style.
|
// style.
|
||||||
Err(())
|
Err(SelectorParseError::UnexpectedIdent("hidden".into()).into())
|
||||||
} else {
|
} else {
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
|
@ -91,37 +91,43 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for computed_value::Keyword {
|
impl Parse for computed_value::Keyword {
|
||||||
fn parse(_context: &ParserContext, input: &mut Parser) -> Result<computed_value::Keyword, ()> {
|
fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<computed_value::Keyword, ParseError<'i>> {
|
||||||
use std::ascii::AsciiExt;
|
use std::ascii::AsciiExt;
|
||||||
use style_traits::cursor::Cursor;
|
use style_traits::cursor::Cursor;
|
||||||
let ident = try!(input.expect_ident());
|
let ident = try!(input.expect_ident());
|
||||||
if ident.eq_ignore_ascii_case("auto") {
|
if ident.eq_ignore_ascii_case("auto") {
|
||||||
Ok(computed_value::Keyword::Auto)
|
Ok(computed_value::Keyword::Auto)
|
||||||
} else {
|
} else {
|
||||||
Cursor::from_css_keyword(&ident).map(computed_value::Keyword::Cursor)
|
Cursor::from_css_keyword(&ident)
|
||||||
|
.map(computed_value::Keyword::Cursor)
|
||||||
|
.map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
fn parse_image(context: &ParserContext, input: &mut Parser) -> Result<computed_value::Image, ()> {
|
fn parse_image<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<computed_value::Image, ParseError<'i>> {
|
||||||
Ok(computed_value::Image {
|
Ok(computed_value::Image {
|
||||||
url: try!(SpecifiedUrl::parse(context, input)),
|
url: try!(SpecifiedUrl::parse(context, input)),
|
||||||
hotspot: match input.try(|input| input.expect_number()) {
|
hotspot: match input.try(|input| input.expect_number()) {
|
||||||
Ok(number) => Some((number, try!(input.expect_number()))),
|
Ok(number) => Some((number, try!(input.expect_number()))),
|
||||||
Err(()) => None,
|
Err(_) => None,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "gecko"))]
|
#[cfg(not(feature = "gecko"))]
|
||||||
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||||
computed_value::Keyword::parse(context, input)
|
computed_value::Keyword::parse(context, input)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// cursor: [<url> [<number> <number>]?]# [auto | default | ...]
|
/// cursor: [<url> [<number> <number>]?]# [auto | default | ...]
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||||
let mut images = vec![];
|
let mut images = vec![];
|
||||||
loop {
|
loop {
|
||||||
match input.try(|input| parse_image(context, input)) {
|
match input.try(|input| parse_image(context, input)) {
|
||||||
|
@ -129,7 +135,7 @@
|
||||||
image.url.build_image_value();
|
image.url.build_image_value();
|
||||||
images.push(image)
|
images.push(image)
|
||||||
}
|
}
|
||||||
Err(()) => break,
|
Err(_) => break,
|
||||||
}
|
}
|
||||||
try!(input.expect_comma());
|
try!(input.expect_comma());
|
||||||
}
|
}
|
||||||
|
|
|
@ -313,27 +313,32 @@ ${helpers.predefined_type("object-position",
|
||||||
}
|
}
|
||||||
|
|
||||||
/// [ row | column ] || dense
|
/// [ row | column ] || dense
|
||||||
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||||
use self::computed_value::AutoFlow;
|
use self::computed_value::AutoFlow;
|
||||||
|
|
||||||
let mut value = None;
|
let mut value = None;
|
||||||
let mut dense = false;
|
let mut dense = false;
|
||||||
|
|
||||||
while !input.is_exhausted() {
|
while !input.is_exhausted() {
|
||||||
match_ignore_ascii_case! { &input.expect_ident()?,
|
let ident = input.expect_ident()?;
|
||||||
|
let success = match_ignore_ascii_case! { &ident,
|
||||||
"row" if value.is_none() => {
|
"row" if value.is_none() => {
|
||||||
value = Some(AutoFlow::Row);
|
value = Some(AutoFlow::Row);
|
||||||
continue
|
true
|
||||||
},
|
},
|
||||||
"column" if value.is_none() => {
|
"column" if value.is_none() => {
|
||||||
value = Some(AutoFlow::Column);
|
value = Some(AutoFlow::Column);
|
||||||
continue
|
true
|
||||||
},
|
},
|
||||||
"dense" if !dense => {
|
"dense" if !dense => {
|
||||||
dense = true;
|
dense = true;
|
||||||
continue
|
true
|
||||||
},
|
},
|
||||||
_ => return Err(())
|
_ => false
|
||||||
|
};
|
||||||
|
if !success {
|
||||||
|
return Err(SelectorParseError::UnexpectedIdent(ident).into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -343,7 +348,7 @@ ${helpers.predefined_type("object-position",
|
||||||
dense: dense,
|
dense: dense,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
Err(())
|
Err(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</%helpers:longhand>
|
</%helpers:longhand>
|
||||||
|
@ -372,7 +377,8 @@ ${helpers.predefined_type("object-position",
|
||||||
Either::Second(None_)
|
Either::Second(None_)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||||
SpecifiedValue::parse(context, input)
|
SpecifiedValue::parse(context, input)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -394,13 +400,15 @@ ${helpers.predefined_type("object-position",
|
||||||
impl ComputedValueAsSpecified for TemplateAreas {}
|
impl ComputedValueAsSpecified for TemplateAreas {}
|
||||||
|
|
||||||
impl Parse for TemplateAreas {
|
impl Parse for TemplateAreas {
|
||||||
fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<Self, ParseError<'i>> {
|
||||||
let mut strings = vec![];
|
let mut strings = vec![];
|
||||||
while let Ok(string) = input.try(Parser::expect_string) {
|
while let Ok(string) = input.try(Parser::expect_string) {
|
||||||
strings.push(string.into_owned().into_boxed_str());
|
strings.push(string.into_owned().into_boxed_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
TemplateAreas::from_vec(strings)
|
TemplateAreas::from_vec(strings)
|
||||||
|
.map_err(|()| StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -129,7 +129,8 @@ ${helpers.single_keyword("mask-origin",
|
||||||
background_size::get_initial_value()
|
background_size::get_initial_value()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue,()> {
|
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<SpecifiedValue,ParseError<'i>> {
|
||||||
background_size::parse(context, input)
|
background_size::parse(context, input)
|
||||||
}
|
}
|
||||||
</%helpers:longhand>
|
</%helpers:longhand>
|
||||||
|
|
|
@ -40,7 +40,8 @@ ${helpers.single_keyword("table-layout", "auto fixed",
|
||||||
}
|
}
|
||||||
|
|
||||||
// never parse it, only set via presentation attribute
|
// never parse it, only set via presentation attribute
|
||||||
fn parse(_: &ParserContext, _: &mut Parser) -> Result<SpecifiedValue, ()> {
|
fn parse<'i, 't>(_: &ParserContext, _: &mut Parser<'i, 't>)
|
||||||
Err(())
|
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||||
|
Err(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
</%helpers:longhand>
|
</%helpers:longhand>
|
||||||
|
|
|
@ -104,7 +104,8 @@
|
||||||
sides_are_logical: true,
|
sides_are_logical: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||||
let first = try!(Side::parse(context, input));
|
let first = try!(Side::parse(context, input));
|
||||||
let second = input.try(|input| Side::parse(context, input)).ok();
|
let second = input.try(|input| Side::parse(context, input)).ok();
|
||||||
Ok(SpecifiedValue {
|
Ok(SpecifiedValue {
|
||||||
|
@ -113,13 +114,14 @@
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
impl Parse for Side {
|
impl Parse for Side {
|
||||||
fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Side, ()> {
|
fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<Side, ParseError<'i>> {
|
||||||
if let Ok(ident) = input.try(|input| input.expect_ident()) {
|
if let Ok(ident) = input.try(|input| input.expect_ident()) {
|
||||||
match_ignore_ascii_case! { &ident,
|
(match_ignore_ascii_case! { &ident,
|
||||||
"clip" => Ok(Side::Clip),
|
"clip" => Ok(Side::Clip),
|
||||||
"ellipsis" => Ok(Side::Ellipsis),
|
"ellipsis" => Ok(Side::Ellipsis),
|
||||||
_ => Err(())
|
_ => Err(())
|
||||||
}
|
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
|
||||||
} else {
|
} else {
|
||||||
Ok(Side::String(try!(input.expect_string()).into_owned().into_boxed_str()))
|
Ok(Side::String(try!(input.expect_string()).into_owned().into_boxed_str()))
|
||||||
}
|
}
|
||||||
|
@ -217,34 +219,39 @@ ${helpers.single_keyword("unicode-bidi",
|
||||||
SpecifiedValue::empty()
|
SpecifiedValue::empty()
|
||||||
}
|
}
|
||||||
/// none | [ underline || overline || line-through || blink ]
|
/// none | [ underline || overline || line-through || blink ]
|
||||||
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||||
let mut result = SpecifiedValue::empty();
|
let mut result = SpecifiedValue::empty();
|
||||||
if input.try(|input| input.expect_ident_matching("none")).is_ok() {
|
if input.try(|input| input.expect_ident_matching("none")).is_ok() {
|
||||||
return Ok(result)
|
return Ok(result)
|
||||||
}
|
}
|
||||||
let mut empty = true;
|
let mut empty = true;
|
||||||
|
|
||||||
while input.try(|input| {
|
loop {
|
||||||
if let Ok(ident) = input.expect_ident() {
|
let result: Result<_, ParseError> = input.try(|input| {
|
||||||
match_ignore_ascii_case! { &ident,
|
match input.expect_ident() {
|
||||||
"underline" => if result.contains(UNDERLINE) { return Err(()) }
|
Ok(ident) => {
|
||||||
else { empty = false; result.insert(UNDERLINE) },
|
(match_ignore_ascii_case! { &ident,
|
||||||
"overline" => if result.contains(OVERLINE) { return Err(()) }
|
"underline" => if result.contains(UNDERLINE) { Err(()) }
|
||||||
else { empty = false; result.insert(OVERLINE) },
|
else { empty = false; result.insert(UNDERLINE); Ok(()) },
|
||||||
"line-through" => if result.contains(LINE_THROUGH) { return Err(()) }
|
"overline" => if result.contains(OVERLINE) { Err(()) }
|
||||||
else { empty = false; result.insert(LINE_THROUGH) },
|
else { empty = false; result.insert(OVERLINE); Ok(()) },
|
||||||
"blink" => if result.contains(BLINK) { return Err(()) }
|
"line-through" => if result.contains(LINE_THROUGH) { Err(()) }
|
||||||
else { empty = false; result.insert(BLINK) },
|
else { empty = false; result.insert(LINE_THROUGH); Ok(()) },
|
||||||
_ => return Err(())
|
"blink" => if result.contains(BLINK) { Err(()) }
|
||||||
|
else { empty = false; result.insert(BLINK); Ok(()) },
|
||||||
|
_ => Err(())
|
||||||
|
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
|
||||||
}
|
}
|
||||||
} else {
|
Err(e) => return Err(e.into())
|
||||||
return Err(());
|
|
||||||
}
|
}
|
||||||
Ok(())
|
});
|
||||||
}).is_ok() {
|
if result.is_err() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !empty { Ok(result) } else { Err(()) }
|
if !empty { Ok(result) } else { Err(StyleParseError::UnspecifiedError.into()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
% if product == "servo":
|
% if product == "servo":
|
||||||
|
|
|
@ -76,11 +76,12 @@ ${helpers.single_keyword("-moz-window-shadow", "none default menu tooltip sheet"
|
||||||
|
|
||||||
impl ComputedValueAsSpecified for SpecifiedValue {}
|
impl ComputedValueAsSpecified for SpecifiedValue {}
|
||||||
|
|
||||||
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||||
match try!(input.expect_integer()) {
|
match try!(input.expect_integer()) {
|
||||||
0 => Ok(computed_value::T(false)),
|
0 => Ok(computed_value::T(false)),
|
||||||
1 => Ok(computed_value::T(true)),
|
1 => Ok(computed_value::T(true)),
|
||||||
_ => Err(()),
|
_ => Err(StyleParseError::UnspecifiedError.into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</%helpers:longhand>
|
</%helpers:longhand>
|
||||||
|
|
|
@ -20,6 +20,7 @@ use stylearc::{Arc, UniqueArc};
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
#[cfg(feature = "servo")] use cssparser::RGBA;
|
#[cfg(feature = "servo")] use cssparser::RGBA;
|
||||||
use cssparser::{Parser, TokenSerializationType, serialize_identifier};
|
use cssparser::{Parser, TokenSerializationType, serialize_identifier};
|
||||||
|
use cssparser::ParserInput;
|
||||||
use error_reporting::ParseErrorReporter;
|
use error_reporting::ParseErrorReporter;
|
||||||
#[cfg(feature = "servo")] use euclid::side_offsets::SideOffsets2D;
|
#[cfg(feature = "servo")] use euclid::side_offsets::SideOffsets2D;
|
||||||
use computed_values;
|
use computed_values;
|
||||||
|
@ -33,9 +34,10 @@ use media_queries::Device;
|
||||||
use parser::{PARSING_MODE_DEFAULT, Parse, ParserContext};
|
use parser::{PARSING_MODE_DEFAULT, Parse, ParserContext};
|
||||||
use properties::animated_properties::TransitionProperty;
|
use properties::animated_properties::TransitionProperty;
|
||||||
#[cfg(feature = "gecko")] use properties::longhands::system_font::SystemFont;
|
#[cfg(feature = "gecko")] use properties::longhands::system_font::SystemFont;
|
||||||
|
use selectors::parser::SelectorParseError;
|
||||||
#[cfg(feature = "servo")] use servo_config::prefs::PREFS;
|
#[cfg(feature = "servo")] use servo_config::prefs::PREFS;
|
||||||
use shared_lock::StylesheetGuards;
|
use shared_lock::StylesheetGuards;
|
||||||
use style_traits::{HasViewportPercentage, ToCss};
|
use style_traits::{HasViewportPercentage, ToCss, ParseError, PropertyDeclarationParseError};
|
||||||
use stylesheets::{CssRuleType, MallocSizeOf, MallocSizeOfFn, Origin, UrlExtraData};
|
use stylesheets::{CssRuleType, MallocSizeOf, MallocSizeOfFn, Origin, UrlExtraData};
|
||||||
#[cfg(feature = "servo")] use values::Either;
|
#[cfg(feature = "servo")] use values::Either;
|
||||||
use values::generics::text::LineHeight;
|
use values::generics::text::LineHeight;
|
||||||
|
@ -168,6 +170,7 @@ macro_rules! unwrap_or_initial {
|
||||||
pub mod shorthands {
|
pub mod shorthands {
|
||||||
use cssparser::Parser;
|
use cssparser::Parser;
|
||||||
use parser::{Parse, ParserContext};
|
use parser::{Parse, ParserContext};
|
||||||
|
use style_traits::{ParseError, StyleParseError};
|
||||||
use values::specified;
|
use values::specified;
|
||||||
|
|
||||||
<%include file="/shorthand/serialize.mako.rs" />
|
<%include file="/shorthand/serialize.mako.rs" />
|
||||||
|
@ -196,9 +199,11 @@ pub mod shorthands {
|
||||||
use parser::ParserContext;
|
use parser::ParserContext;
|
||||||
use properties::{SourcePropertyDeclaration, AllShorthand, ShorthandId, UnparsedValue};
|
use properties::{SourcePropertyDeclaration, AllShorthand, ShorthandId, UnparsedValue};
|
||||||
use stylearc::Arc;
|
use stylearc::Arc;
|
||||||
|
use style_traits::{ParseError, StyleParseError};
|
||||||
|
|
||||||
pub fn parse_into(declarations: &mut SourcePropertyDeclaration,
|
pub fn parse_into<'i, 't>(declarations: &mut SourcePropertyDeclaration,
|
||||||
context: &ParserContext, input: &mut Parser) -> Result<(), ()> {
|
context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<(), ParseError<'i>> {
|
||||||
// This function is like the parse() that is generated by
|
// This function is like the parse() that is generated by
|
||||||
// helpers:shorthand, but since the only values for the 'all'
|
// helpers:shorthand, but since the only values for the 'all'
|
||||||
// shorthand when not just a single CSS-wide keyword is one
|
// shorthand when not just a single CSS-wide keyword is one
|
||||||
|
@ -222,7 +227,7 @@ pub mod shorthands {
|
||||||
}));
|
}));
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err(())
|
Err(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -397,6 +402,7 @@ impl PropertyDeclarationIdSet {
|
||||||
{
|
{
|
||||||
f(&
|
f(&
|
||||||
::custom_properties::substitute(css, first_token_type, custom_properties)
|
::custom_properties::substitute(css, first_token_type, custom_properties)
|
||||||
|
.ok()
|
||||||
.and_then(|css| {
|
.and_then(|css| {
|
||||||
// As of this writing, only the base URL is used for property values:
|
// As of this writing, only the base URL is used for property values:
|
||||||
//
|
//
|
||||||
|
@ -408,7 +414,8 @@ impl PropertyDeclarationIdSet {
|
||||||
None,
|
None,
|
||||||
PARSING_MODE_DEFAULT,
|
PARSING_MODE_DEFAULT,
|
||||||
quirks_mode);
|
quirks_mode);
|
||||||
Parser::new(&css).parse_entirely(|input| {
|
let mut input = ParserInput::new(&css);
|
||||||
|
Parser::new(&mut input).parse_entirely(|input| {
|
||||||
match from_shorthand {
|
match from_shorthand {
|
||||||
None => {
|
None => {
|
||||||
longhands::${property.ident}
|
longhands::${property.ident}
|
||||||
|
@ -417,7 +424,7 @@ impl PropertyDeclarationIdSet {
|
||||||
Some(ShorthandId::All) => {
|
Some(ShorthandId::All) => {
|
||||||
// No need to parse the 'all' shorthand as anything other than a CSS-wide
|
// No need to parse the 'all' shorthand as anything other than a CSS-wide
|
||||||
// keyword, after variable substitution.
|
// keyword, after variable substitution.
|
||||||
Err(())
|
Err(SelectorParseError::UnexpectedIdent("all".into()).into())
|
||||||
}
|
}
|
||||||
% for shorthand in data.shorthands_except_all():
|
% for shorthand in data.shorthands_except_all():
|
||||||
% if property in shorthand.sub_properties:
|
% if property in shorthand.sub_properties:
|
||||||
|
@ -431,7 +438,7 @@ impl PropertyDeclarationIdSet {
|
||||||
% endfor
|
% endfor
|
||||||
_ => unreachable!()
|
_ => unreachable!()
|
||||||
}
|
}
|
||||||
})
|
}).ok()
|
||||||
})
|
})
|
||||||
.unwrap_or(
|
.unwrap_or(
|
||||||
// Invalid at computed-value time.
|
// Invalid at computed-value time.
|
||||||
|
@ -483,10 +490,11 @@ impl CSSWideKeyword {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for CSSWideKeyword {
|
impl Parse for CSSWideKeyword {
|
||||||
fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
let ident = input.expect_ident()?;
|
let ident = input.expect_ident()?;
|
||||||
input.expect_exhausted()?;
|
input.expect_exhausted()?;
|
||||||
CSSWideKeyword::from_ident(&ident).ok_or(())
|
CSSWideKeyword::from_ident(&ident)
|
||||||
|
.ok_or(SelectorParseError::UnexpectedIdent(ident).into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -929,7 +937,7 @@ impl PropertyId {
|
||||||
/// Returns a given property from the string `s`.
|
/// Returns a given property from the string `s`.
|
||||||
///
|
///
|
||||||
/// Returns Err(()) for unknown non-custom properties
|
/// Returns Err(()) for unknown non-custom properties
|
||||||
pub fn parse(property_name: Cow<str>) -> Result<Self, ()> {
|
pub fn parse<'i>(property_name: Cow<'i, str>) -> Result<Self, ParseError<'i>> {
|
||||||
if let Ok(name) = ::custom_properties::parse_name(&property_name) {
|
if let Ok(name) = ::custom_properties::parse_name(&property_name) {
|
||||||
return Ok(PropertyId::Custom(::custom_properties::Name::from(name)))
|
return Ok(PropertyId::Custom(::custom_properties::Name::from(name)))
|
||||||
}
|
}
|
||||||
|
@ -954,7 +962,7 @@ impl PropertyId {
|
||||||
match static_id(&property_name) {
|
match static_id(&property_name) {
|
||||||
Some(&StaticId::Longhand(id)) => Ok(PropertyId::Longhand(id)),
|
Some(&StaticId::Longhand(id)) => Ok(PropertyId::Longhand(id)),
|
||||||
Some(&StaticId::Shorthand(id)) => Ok(PropertyId::Shorthand(id)),
|
Some(&StaticId::Shorthand(id)) => Ok(PropertyId::Shorthand(id)),
|
||||||
None => Err(()),
|
None => Err(SelectorParseError::UnexpectedIdent(property_name).into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1078,24 +1086,6 @@ impl HasViewportPercentage for PropertyDeclaration {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The result of parsing a property declaration.
|
|
||||||
#[derive(Eq, PartialEq, Copy, Clone)]
|
|
||||||
pub enum PropertyDeclarationParseError {
|
|
||||||
/// The property declaration was for an unknown property.
|
|
||||||
UnknownProperty,
|
|
||||||
/// The property declaration was for a disabled experimental property.
|
|
||||||
ExperimentalProperty,
|
|
||||||
/// The property declaration contained an invalid value.
|
|
||||||
InvalidValue,
|
|
||||||
/// The declaration contained an animation property, and we were parsing
|
|
||||||
/// this as a keyframe block (so that property should be ignored).
|
|
||||||
///
|
|
||||||
/// See: https://drafts.csswg.org/css-animations/#keyframes
|
|
||||||
AnimationPropertyInKeyframeBlock,
|
|
||||||
/// The property is not allowed within a page rule.
|
|
||||||
NotAllowedInPageRule,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Debug for PropertyDeclaration {
|
impl fmt::Debug for PropertyDeclaration {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
try!(self.id().to_css(f));
|
try!(self.id().to_css(f));
|
||||||
|
@ -1390,9 +1380,9 @@ impl PropertyDeclaration {
|
||||||
PropertyId::Custom(name) => {
|
PropertyId::Custom(name) => {
|
||||||
let value = match input.try(|i| CSSWideKeyword::parse(context, i)) {
|
let value = match input.try(|i| CSSWideKeyword::parse(context, i)) {
|
||||||
Ok(keyword) => DeclaredValueOwned::CSSWideKeyword(keyword),
|
Ok(keyword) => DeclaredValueOwned::CSSWideKeyword(keyword),
|
||||||
Err(()) => match ::custom_properties::SpecifiedValue::parse(context, input) {
|
Err(_) => match ::custom_properties::SpecifiedValue::parse(context, input) {
|
||||||
Ok(value) => DeclaredValueOwned::Value(value),
|
Ok(value) => DeclaredValueOwned::Value(value),
|
||||||
Err(()) => return Err(PropertyDeclarationParseError::InvalidValue),
|
Err(_) => return Err(PropertyDeclarationParseError::InvalidValue),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
declarations.push(PropertyDeclaration::Custom(name, value));
|
declarations.push(PropertyDeclaration::Custom(name, value));
|
||||||
|
@ -1425,7 +1415,7 @@ impl PropertyDeclaration {
|
||||||
declarations.push(value);
|
declarations.push(value);
|
||||||
Ok(())
|
Ok(())
|
||||||
},
|
},
|
||||||
Err(()) => Err(PropertyDeclarationParseError::InvalidValue),
|
Err(_) => Err(PropertyDeclarationParseError::InvalidValue),
|
||||||
}
|
}
|
||||||
% else:
|
% else:
|
||||||
Err(PropertyDeclarationParseError::UnknownProperty)
|
Err(PropertyDeclarationParseError::UnknownProperty)
|
||||||
|
@ -1468,9 +1458,9 @@ impl PropertyDeclaration {
|
||||||
% endif
|
% endif
|
||||||
Ok(())
|
Ok(())
|
||||||
},
|
},
|
||||||
Err(()) => {
|
Err(_) => {
|
||||||
shorthands::${shorthand.ident}::parse_into(declarations, context, input)
|
shorthands::${shorthand.ident}::parse_into(declarations, context, input)
|
||||||
.map_err(|()| PropertyDeclarationParseError::InvalidValue)
|
.map_err(|_| PropertyDeclarationParseError::InvalidValue)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,8 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<Longhands, ParseError<'i>> {
|
||||||
let mut background_color = None;
|
let mut background_color = None;
|
||||||
|
|
||||||
% for name in "image position_x position_y repeat size attachment origin clip".split():
|
% for name in "image position_x position_y repeat size attachment origin clip".split():
|
||||||
|
@ -42,7 +43,7 @@
|
||||||
// background-color can only be in the last element, so if it
|
// background-color can only be in the last element, so if it
|
||||||
// is parsed anywhere before, the value is invalid.
|
// is parsed anywhere before, the value is invalid.
|
||||||
if background_color.is_some() {
|
if background_color.is_some() {
|
||||||
return Err(());
|
return Err(StyleParseError::UnspecifiedError.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
% for name in "image position repeat size attachment origin clip".split():
|
% for name in "image position repeat size attachment origin clip".split():
|
||||||
|
@ -107,7 +108,7 @@
|
||||||
% endfor
|
% endfor
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err(())
|
Err(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -194,7 +195,8 @@
|
||||||
use values::specified::AllowQuirks;
|
use values::specified::AllowQuirks;
|
||||||
use values::specified::position::Position;
|
use values::specified::position::Position;
|
||||||
|
|
||||||
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<Longhands, ParseError<'i>> {
|
||||||
let mut position_x = background_position_x::SpecifiedValue(Vec::new());
|
let mut position_x = background_position_x::SpecifiedValue(Vec::new());
|
||||||
let mut position_y = background_position_y::SpecifiedValue(Vec::new());
|
let mut position_y = background_position_y::SpecifiedValue(Vec::new());
|
||||||
let mut any = false;
|
let mut any = false;
|
||||||
|
@ -207,7 +209,7 @@
|
||||||
Ok(())
|
Ok(())
|
||||||
})?;
|
})?;
|
||||||
if !any {
|
if !any {
|
||||||
return Err(());
|
return Err(StyleParseError::UnspecifiedError.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(expanded! {
|
Ok(expanded! {
|
||||||
|
|
|
@ -20,7 +20,8 @@ ${helpers.four_sides_shorthand("border-style", "border-%s-style",
|
||||||
use values::generics::rect::Rect;
|
use values::generics::rect::Rect;
|
||||||
use values::specified::{AllowQuirks, BorderSideWidth};
|
use values::specified::{AllowQuirks, BorderSideWidth};
|
||||||
|
|
||||||
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<Longhands, ParseError<'i>> {
|
||||||
let rect = Rect::parse_with(context, input, |_, i| {
|
let rect = Rect::parse_with(context, input, |_, i| {
|
||||||
BorderSideWidth::parse_quirky(context, i, AllowQuirks::Yes)
|
BorderSideWidth::parse_quirky(context, i, AllowQuirks::Yes)
|
||||||
})?;
|
})?;
|
||||||
|
@ -43,10 +44,10 @@ ${helpers.four_sides_shorthand("border-style", "border-%s-style",
|
||||||
</%helpers:shorthand>
|
</%helpers:shorthand>
|
||||||
|
|
||||||
|
|
||||||
pub fn parse_border(context: &ParserContext, input: &mut Parser)
|
pub fn parse_border<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
-> Result<(specified::Color,
|
-> Result<(specified::Color,
|
||||||
specified::BorderStyle,
|
specified::BorderStyle,
|
||||||
specified::BorderSideWidth), ()> {
|
specified::BorderSideWidth), ParseError<'i>> {
|
||||||
use values::specified::{Color, BorderStyle, BorderSideWidth};
|
use values::specified::{Color, BorderStyle, BorderSideWidth};
|
||||||
let _unused = context;
|
let _unused = context;
|
||||||
let mut color = None;
|
let mut color = None;
|
||||||
|
@ -82,7 +83,7 @@ pub fn parse_border(context: &ParserContext, input: &mut Parser)
|
||||||
style.unwrap_or(BorderStyle::none),
|
style.unwrap_or(BorderStyle::none),
|
||||||
width.unwrap_or(BorderSideWidth::Medium)))
|
width.unwrap_or(BorderSideWidth::Medium)))
|
||||||
} else {
|
} else {
|
||||||
Err(())
|
Err(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,7 +102,8 @@ pub fn parse_border(context: &ParserContext, input: &mut Parser)
|
||||||
alias="${maybe_moz_logical_alias(product, (side, logical), '-moz-border-%s')}"
|
alias="${maybe_moz_logical_alias(product, (side, logical), '-moz-border-%s')}"
|
||||||
spec="${spec}">
|
spec="${spec}">
|
||||||
|
|
||||||
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<Longhands, ParseError<'i>> {
|
||||||
let (color, style, width) = try!(super::parse_border(context, input));
|
let (color, style, width) = try!(super::parse_border(context, input));
|
||||||
Ok(expanded! {
|
Ok(expanded! {
|
||||||
border_${to_rust_ident(side)}_color: color,
|
border_${to_rust_ident(side)}_color: color,
|
||||||
|
@ -139,7 +141,8 @@ pub fn parse_border(context: &ParserContext, input: &mut Parser)
|
||||||
_moz_border_bottom_colors, _moz_border_left_colors};
|
_moz_border_bottom_colors, _moz_border_left_colors};
|
||||||
% endif
|
% endif
|
||||||
|
|
||||||
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<Longhands, ParseError<'i>> {
|
||||||
use properties::longhands::{border_image_outset, border_image_repeat, border_image_slice};
|
use properties::longhands::{border_image_outset, border_image_repeat, border_image_slice};
|
||||||
use properties::longhands::{border_image_source, border_image_width};
|
use properties::longhands::{border_image_source, border_image_width};
|
||||||
|
|
||||||
|
@ -209,7 +212,8 @@ pub fn parse_border(context: &ParserContext, input: &mut Parser)
|
||||||
use values::specified::border::BorderRadius;
|
use values::specified::border::BorderRadius;
|
||||||
use parser::Parse;
|
use parser::Parse;
|
||||||
|
|
||||||
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<Longhands, ParseError<'i>> {
|
||||||
let radii = try!(BorderRadius::parse(context, input));
|
let radii = try!(BorderRadius::parse(context, input));
|
||||||
Ok(expanded! {
|
Ok(expanded! {
|
||||||
border_top_left_radius: radii.top_left,
|
border_top_left_radius: radii.top_left,
|
||||||
|
@ -242,12 +246,13 @@ pub fn parse_border(context: &ParserContext, input: &mut Parser)
|
||||||
use properties::longhands::{border_image_outset, border_image_repeat, border_image_slice};
|
use properties::longhands::{border_image_outset, border_image_repeat, border_image_slice};
|
||||||
use properties::longhands::{border_image_source, border_image_width};
|
use properties::longhands::{border_image_source, border_image_width};
|
||||||
|
|
||||||
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<Longhands, ParseError<'i>> {
|
||||||
% for name in "outset repeat slice source width".split():
|
% for name in "outset repeat slice source width".split():
|
||||||
let mut border_image_${name} = border_image_${name}::get_initial_specified_value();
|
let mut border_image_${name} = border_image_${name}::get_initial_specified_value();
|
||||||
% endfor
|
% endfor
|
||||||
|
|
||||||
try!(input.try(|input| {
|
let result: Result<_, ParseError> = input.try(|input| {
|
||||||
% for name in "outset repeat slice source width".split():
|
% for name in "outset repeat slice source width".split():
|
||||||
let mut ${name} = None;
|
let mut ${name} = None;
|
||||||
% endfor
|
% endfor
|
||||||
|
@ -256,7 +261,7 @@ pub fn parse_border(context: &ParserContext, input: &mut Parser)
|
||||||
if let Ok(value) = input.try(|input| border_image_slice::parse(context, input)) {
|
if let Ok(value) = input.try(|input| border_image_slice::parse(context, input)) {
|
||||||
slice = Some(value);
|
slice = Some(value);
|
||||||
// Parse border image width and outset, if applicable.
|
// Parse border image width and outset, if applicable.
|
||||||
let maybe_width_outset: Result<_, ()> = input.try(|input| {
|
let maybe_width_outset: Result<_, ParseError> = input.try(|input| {
|
||||||
try!(input.expect_delim('/'));
|
try!(input.expect_delim('/'));
|
||||||
|
|
||||||
// Parse border image width, if applicable.
|
// Parse border image width, if applicable.
|
||||||
|
@ -269,7 +274,7 @@ pub fn parse_border(context: &ParserContext, input: &mut Parser)
|
||||||
border_image_outset::parse(context, input)
|
border_image_outset::parse(context, input)
|
||||||
}).ok();
|
}).ok();
|
||||||
if w.is_none() && o.is_none() {
|
if w.is_none() && o.is_none() {
|
||||||
Err(())
|
Err(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Ok((w, o))
|
Ok((w, o))
|
||||||
|
@ -305,9 +310,10 @@ pub fn parse_border(context: &ParserContext, input: &mut Parser)
|
||||||
% endfor
|
% endfor
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err(())
|
Err(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
}));
|
});
|
||||||
|
try!(result);
|
||||||
|
|
||||||
Ok(expanded! {
|
Ok(expanded! {
|
||||||
% for name in "outset repeat slice source width".split():
|
% for name in "outset repeat slice source width".split():
|
||||||
|
|
|
@ -11,29 +11,33 @@
|
||||||
use properties::longhands::overflow_x::SpecifiedValue;
|
use properties::longhands::overflow_x::SpecifiedValue;
|
||||||
% endif
|
% endif
|
||||||
|
|
||||||
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<Longhands, ParseError<'i>> {
|
||||||
% if product == "gecko":
|
% if product == "gecko":
|
||||||
let moz_kw_found = input.try(|i| match_ignore_ascii_case! {
|
let moz_kw_found = input.try(|i| {
|
||||||
&i.expect_ident()?,
|
let ident = i.expect_ident()?;
|
||||||
"-moz-scrollbars-horizontal" => {
|
(match_ignore_ascii_case! {
|
||||||
Ok(expanded! {
|
&ident,
|
||||||
overflow_x: SpecifiedValue::scroll,
|
"-moz-scrollbars-horizontal" => {
|
||||||
overflow_y: SpecifiedValue::hidden,
|
Ok(expanded! {
|
||||||
})
|
overflow_x: SpecifiedValue::scroll,
|
||||||
}
|
overflow_y: SpecifiedValue::hidden,
|
||||||
"-moz-scrollbars-vertical" => {
|
})
|
||||||
Ok(expanded! {
|
}
|
||||||
overflow_x: SpecifiedValue::hidden,
|
"-moz-scrollbars-vertical" => {
|
||||||
overflow_y: SpecifiedValue::scroll,
|
Ok(expanded! {
|
||||||
})
|
overflow_x: SpecifiedValue::hidden,
|
||||||
}
|
overflow_y: SpecifiedValue::scroll,
|
||||||
"-moz-scrollbars-none" => {
|
})
|
||||||
Ok(expanded! {
|
}
|
||||||
overflow_x: SpecifiedValue::hidden,
|
"-moz-scrollbars-none" => {
|
||||||
overflow_y: SpecifiedValue::hidden,
|
Ok(expanded! {
|
||||||
})
|
overflow_x: SpecifiedValue::hidden,
|
||||||
}
|
overflow_y: SpecifiedValue::hidden,
|
||||||
_ => Err(())
|
})
|
||||||
|
}
|
||||||
|
_ => Err(())
|
||||||
|
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
|
||||||
});
|
});
|
||||||
if moz_kw_found.is_ok() {
|
if moz_kw_found.is_ok() {
|
||||||
return moz_kw_found
|
return moz_kw_found
|
||||||
|
@ -88,14 +92,16 @@ macro_rules! try_parse_one {
|
||||||
use properties::longhands::transition_${prop};
|
use properties::longhands::transition_${prop};
|
||||||
% endfor
|
% endfor
|
||||||
|
|
||||||
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<Longhands, ParseError<'i>> {
|
||||||
struct SingleTransition {
|
struct SingleTransition {
|
||||||
% for prop in "property duration timing_function delay".split():
|
% for prop in "property duration timing_function delay".split():
|
||||||
transition_${prop}: transition_${prop}::SingleSpecifiedValue,
|
transition_${prop}: transition_${prop}::SingleSpecifiedValue,
|
||||||
% endfor
|
% endfor
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_one_transition(context: &ParserContext, input: &mut Parser) -> Result<SingleTransition,()> {
|
fn parse_one_transition<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<SingleTransition,ParseError<'i>> {
|
||||||
% for prop in "property duration timing_function delay".split():
|
% for prop in "property duration timing_function delay".split():
|
||||||
let mut ${prop} = None;
|
let mut ${prop} = None;
|
||||||
% endfor
|
% endfor
|
||||||
|
@ -123,7 +129,7 @@ macro_rules! try_parse_one {
|
||||||
% endfor
|
% endfor
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
Err(())
|
Err(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -202,14 +208,16 @@ macro_rules! try_parse_one {
|
||||||
use properties::longhands::animation_${prop};
|
use properties::longhands::animation_${prop};
|
||||||
% endfor
|
% endfor
|
||||||
|
|
||||||
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<Longhands, ParseError<'i>> {
|
||||||
struct SingleAnimation {
|
struct SingleAnimation {
|
||||||
% for prop in props:
|
% for prop in props:
|
||||||
animation_${prop}: animation_${prop}::SingleSpecifiedValue,
|
animation_${prop}: animation_${prop}::SingleSpecifiedValue,
|
||||||
% endfor
|
% endfor
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_one_animation(context: &ParserContext, input: &mut Parser) -> Result<SingleAnimation,()> {
|
fn parse_one_animation<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<SingleAnimation,ParseError<'i>> {
|
||||||
% for prop in props:
|
% for prop in props:
|
||||||
let mut ${prop} = None;
|
let mut ${prop} = None;
|
||||||
% endfor
|
% endfor
|
||||||
|
@ -237,7 +245,7 @@ macro_rules! try_parse_one {
|
||||||
|
|
||||||
// If nothing is parsed, this is an invalid entry.
|
// If nothing is parsed, this is an invalid entry.
|
||||||
if parsed == 0 {
|
if parsed == 0 {
|
||||||
Err(())
|
Err(StyleParseError::UnspecifiedError.into())
|
||||||
} else {
|
} else {
|
||||||
Ok(SingleAnimation {
|
Ok(SingleAnimation {
|
||||||
% for prop in props:
|
% for prop in props:
|
||||||
|
@ -303,7 +311,8 @@ macro_rules! try_parse_one {
|
||||||
spec="https://drafts.csswg.org/css-scroll-snap/#propdef-scroll-snap-type">
|
spec="https://drafts.csswg.org/css-scroll-snap/#propdef-scroll-snap-type">
|
||||||
use properties::longhands::scroll_snap_type_x;
|
use properties::longhands::scroll_snap_type_x;
|
||||||
|
|
||||||
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<Longhands, ParseError<'i>> {
|
||||||
let result = try!(scroll_snap_type_x::parse(context, input));
|
let result = try!(scroll_snap_type_x::parse(context, input));
|
||||||
Ok(expanded! {
|
Ok(expanded! {
|
||||||
scroll_snap_type_x: result,
|
scroll_snap_type_x: result,
|
||||||
|
@ -331,7 +340,8 @@ macro_rules! try_parse_one {
|
||||||
spec="Non-standard: https://developer.mozilla.org/en-US/docs/Web/CSS/transform">
|
spec="Non-standard: https://developer.mozilla.org/en-US/docs/Web/CSS/transform">
|
||||||
use properties::longhands::transform;
|
use properties::longhands::transform;
|
||||||
|
|
||||||
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<Longhands, ParseError<'i>> {
|
||||||
Ok(expanded! {
|
Ok(expanded! {
|
||||||
transform: transform::parse_prefixed(context, input)?,
|
transform: transform::parse_prefixed(context, input)?,
|
||||||
})
|
})
|
||||||
|
|
|
@ -8,7 +8,8 @@
|
||||||
extra_prefixes="moz" spec="https://drafts.csswg.org/css-multicol/#propdef-columns">
|
extra_prefixes="moz" spec="https://drafts.csswg.org/css-multicol/#propdef-columns">
|
||||||
use properties::longhands::{column_count, column_width};
|
use properties::longhands::{column_count, column_width};
|
||||||
|
|
||||||
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<Longhands, ParseError<'i>> {
|
||||||
|
|
||||||
let mut column_count = None;
|
let mut column_count = None;
|
||||||
let mut column_width = None;
|
let mut column_width = None;
|
||||||
|
@ -40,7 +41,7 @@
|
||||||
|
|
||||||
let values = autos + column_count.iter().len() + column_width.iter().len();
|
let values = autos + column_count.iter().len() + column_width.iter().len();
|
||||||
if values == 0 || values > 2 {
|
if values == 0 || values > 2 {
|
||||||
Err(())
|
Err(StyleParseError::UnspecifiedError.into())
|
||||||
} else {
|
} else {
|
||||||
Ok(expanded! {
|
Ok(expanded! {
|
||||||
column_count: unwrap_or_initial!(column_count),
|
column_count: unwrap_or_initial!(column_count),
|
||||||
|
@ -65,7 +66,8 @@
|
||||||
use properties::longhands::{column_rule_width, column_rule_style};
|
use properties::longhands::{column_rule_width, column_rule_style};
|
||||||
use properties::longhands::column_rule_color;
|
use properties::longhands::column_rule_color;
|
||||||
|
|
||||||
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<Longhands, ParseError<'i>> {
|
||||||
% for name in "width style color".split():
|
% for name in "width style color".split():
|
||||||
let mut column_rule_${name} = None;
|
let mut column_rule_${name} = None;
|
||||||
% endfor
|
% endfor
|
||||||
|
@ -92,7 +94,7 @@
|
||||||
column_rule_color: unwrap_or_initial!(column_rule_color),
|
column_rule_color: unwrap_or_initial!(column_rule_color),
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
Err(())
|
Err(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,8 @@
|
||||||
% endif
|
% endif
|
||||||
use self::font_family::SpecifiedValue as FontFamily;
|
use self::font_family::SpecifiedValue as FontFamily;
|
||||||
|
|
||||||
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<Longhands, ParseError<'i>> {
|
||||||
let mut nb_normals = 0;
|
let mut nb_normals = 0;
|
||||||
let mut style = None;
|
let mut style = None;
|
||||||
let mut variant_caps = None;
|
let mut variant_caps = None;
|
||||||
|
@ -97,7 +98,7 @@
|
||||||
}
|
}
|
||||||
if size.is_none() ||
|
if size.is_none() ||
|
||||||
(count(&style) + count(&weight) + count(&variant_caps) + count(&stretch) + nb_normals) > 4 {
|
(count(&style) + count(&weight) + count(&variant_caps) + count(&stretch) + nb_normals) > 4 {
|
||||||
return Err(())
|
return Err(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
let line_height = if input.try(|input| input.expect_delim('/')).is_ok() {
|
let line_height = if input.try(|input| input.expect_delim('/')).is_ok() {
|
||||||
Some(try!(LineHeight::parse(context, input)))
|
Some(try!(LineHeight::parse(context, input)))
|
||||||
|
@ -239,7 +240,8 @@
|
||||||
% endfor
|
% endfor
|
||||||
% endif
|
% endif
|
||||||
|
|
||||||
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<Longhands, ParseError<'i>> {
|
||||||
let mut nb_normals = 0;
|
let mut nb_normals = 0;
|
||||||
let mut caps = None;
|
let mut caps = None;
|
||||||
loop {
|
loop {
|
||||||
|
@ -264,7 +266,7 @@
|
||||||
}
|
}
|
||||||
let count = count(&caps) + nb_normals;
|
let count = count(&caps) + nb_normals;
|
||||||
if count == 0 || count > 1 {
|
if count == 0 || count > 1 {
|
||||||
return Err(())
|
return Err(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
Ok(expanded! {
|
Ok(expanded! {
|
||||||
font_variant_caps: unwrap_or_initial!(font_variant_caps, caps),
|
font_variant_caps: unwrap_or_initial!(font_variant_caps, caps),
|
||||||
|
|
|
@ -9,7 +9,8 @@
|
||||||
spec="https://www.w3.org/TR/SVG2/painting.html#MarkerShorthand">
|
spec="https://www.w3.org/TR/SVG2/painting.html#MarkerShorthand">
|
||||||
use values::specified::UrlOrNone;
|
use values::specified::UrlOrNone;
|
||||||
|
|
||||||
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<Longhands, ParseError<'i>> {
|
||||||
use parser::Parse;
|
use parser::Parse;
|
||||||
let url = UrlOrNone::parse(context, input)?;
|
let url = UrlOrNone::parse(context, input)?;
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,8 @@
|
||||||
spec="https://drafts.csswg.org/css-text-decor-3/#text-emphasis-property">
|
spec="https://drafts.csswg.org/css-text-decor-3/#text-emphasis-property">
|
||||||
use properties::longhands::{text_emphasis_color, text_emphasis_style};
|
use properties::longhands::{text_emphasis_color, text_emphasis_style};
|
||||||
|
|
||||||
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<Longhands, ParseError<'i>> {
|
||||||
let mut color = None;
|
let mut color = None;
|
||||||
let mut style = None;
|
let mut style = None;
|
||||||
|
|
||||||
|
@ -34,7 +35,7 @@
|
||||||
text_emphasis_style: unwrap_or_initial!(text_emphasis_style, style),
|
text_emphasis_style: unwrap_or_initial!(text_emphasis_style, style),
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
Err(())
|
Err(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,7 +57,8 @@
|
||||||
spec="https://compat.spec.whatwg.org/#the-webkit-text-stroke">
|
spec="https://compat.spec.whatwg.org/#the-webkit-text-stroke">
|
||||||
use properties::longhands::{_webkit_text_stroke_color, _webkit_text_stroke_width};
|
use properties::longhands::{_webkit_text_stroke_color, _webkit_text_stroke_width};
|
||||||
|
|
||||||
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<Longhands, ParseError<'i>> {
|
||||||
let mut color = None;
|
let mut color = None;
|
||||||
let mut width = None;
|
let mut width = None;
|
||||||
loop {
|
loop {
|
||||||
|
@ -82,7 +84,7 @@
|
||||||
_webkit_text_stroke_width: unwrap_or_initial!(_webkit_text_stroke_width, width),
|
_webkit_text_stroke_width: unwrap_or_initial!(_webkit_text_stroke_width, width),
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
Err(())
|
Err(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,8 @@
|
||||||
use properties::longhands::{list_style_image, list_style_position, list_style_type};
|
use properties::longhands::{list_style_image, list_style_position, list_style_type};
|
||||||
use values::{Either, None_};
|
use values::{Either, None_};
|
||||||
|
|
||||||
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<Longhands, ParseError<'i>> {
|
||||||
// `none` is ambiguous until we've finished parsing the shorthands, so we count the number
|
// `none` is ambiguous until we've finished parsing the shorthands, so we count the number
|
||||||
// of times we see it.
|
// of times we see it.
|
||||||
let mut nones = 0u8;
|
let mut nones = 0u8;
|
||||||
|
@ -19,7 +20,7 @@
|
||||||
if input.try(|input| input.expect_ident_matching("none")).is_ok() {
|
if input.try(|input| input.expect_ident_matching("none")).is_ok() {
|
||||||
nones = nones + 1;
|
nones = nones + 1;
|
||||||
if nones > 2 {
|
if nones > 2 {
|
||||||
return Err(())
|
return Err(SelectorParseError::UnexpectedIdent("none".into()).into())
|
||||||
}
|
}
|
||||||
any = true;
|
any = true;
|
||||||
continue
|
continue
|
||||||
|
@ -104,7 +105,7 @@
|
||||||
list_style_type: unwrap_or_initial!(list_style_type),
|
list_style_type: unwrap_or_initial!(list_style_type),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
_ => Err(()),
|
_ => Err(StyleParseError::UnspecifiedError.into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,8 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<Longhands, ParseError<'i>> {
|
||||||
% for name in "image mode position_x position_y size repeat origin clip composite".split():
|
% for name in "image mode position_x position_y size repeat origin clip composite".split():
|
||||||
let mut mask_${name} = mask_${name}::SpecifiedValue(Vec::new());
|
let mut mask_${name} = mask_${name}::SpecifiedValue(Vec::new());
|
||||||
% endfor
|
% endfor
|
||||||
|
@ -103,7 +104,7 @@
|
||||||
% endfor
|
% endfor
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err(())
|
Err(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -180,7 +181,8 @@
|
||||||
use values::specified::position::Position;
|
use values::specified::position::Position;
|
||||||
use parser::Parse;
|
use parser::Parse;
|
||||||
|
|
||||||
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<Longhands, ParseError<'i>> {
|
||||||
let mut position_x = mask_position_x::SpecifiedValue(Vec::new());
|
let mut position_x = mask_position_x::SpecifiedValue(Vec::new());
|
||||||
let mut position_y = mask_position_y::SpecifiedValue(Vec::new());
|
let mut position_y = mask_position_y::SpecifiedValue(Vec::new());
|
||||||
let mut any = false;
|
let mut any = false;
|
||||||
|
@ -193,7 +195,7 @@
|
||||||
Ok(())
|
Ok(())
|
||||||
})?;
|
})?;
|
||||||
if any == false {
|
if any == false {
|
||||||
return Err(());
|
return Err(StyleParseError::UnspecifiedError.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(expanded! {
|
Ok(expanded! {
|
||||||
|
|
|
@ -10,7 +10,8 @@
|
||||||
use values::specified;
|
use values::specified;
|
||||||
use parser::Parse;
|
use parser::Parse;
|
||||||
|
|
||||||
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<Longhands, ParseError<'i>> {
|
||||||
let _unused = context;
|
let _unused = context;
|
||||||
let mut color = None;
|
let mut color = None;
|
||||||
let mut style = None;
|
let mut style = None;
|
||||||
|
@ -47,7 +48,7 @@
|
||||||
outline_width: unwrap_or_initial!(outline_width, width),
|
outline_width: unwrap_or_initial!(outline_width, width),
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
Err(())
|
Err(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,7 +72,8 @@
|
||||||
use values::specified::border::BorderRadius;
|
use values::specified::border::BorderRadius;
|
||||||
use parser::Parse;
|
use parser::Parse;
|
||||||
|
|
||||||
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<Longhands, ParseError<'i>> {
|
||||||
let radii = try!(BorderRadius::parse(context, input));
|
let radii = try!(BorderRadius::parse(context, input));
|
||||||
Ok(expanded! {
|
Ok(expanded! {
|
||||||
_moz_outline_radius_topleft: radii.top_left,
|
_moz_outline_radius_topleft: radii.top_left,
|
||||||
|
|
|
@ -8,7 +8,8 @@
|
||||||
spec="https://drafts.csswg.org/css-flexbox/#flex-flow-property">
|
spec="https://drafts.csswg.org/css-flexbox/#flex-flow-property">
|
||||||
use properties::longhands::{flex_direction, flex_wrap};
|
use properties::longhands::{flex_direction, flex_wrap};
|
||||||
|
|
||||||
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<Longhands, ParseError<'i>> {
|
||||||
let mut direction = None;
|
let mut direction = None;
|
||||||
let mut wrap = None;
|
let mut wrap = None;
|
||||||
loop {
|
loop {
|
||||||
|
@ -28,7 +29,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
if direction.is_none() && wrap.is_none() {
|
if direction.is_none() && wrap.is_none() {
|
||||||
return Err(())
|
return Err(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
Ok(expanded! {
|
Ok(expanded! {
|
||||||
flex_direction: unwrap_or_initial!(flex_direction, direction),
|
flex_direction: unwrap_or_initial!(flex_direction, direction),
|
||||||
|
@ -50,14 +51,15 @@
|
||||||
spec="https://drafts.csswg.org/css-flexbox/#flex-property">
|
spec="https://drafts.csswg.org/css-flexbox/#flex-property">
|
||||||
use values::specified::Number;
|
use values::specified::Number;
|
||||||
|
|
||||||
fn parse_flexibility(context: &ParserContext, input: &mut Parser)
|
fn parse_flexibility<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
-> Result<(Number, Option<Number>),()> {
|
-> Result<(Number, Option<Number>),ParseError<'i>> {
|
||||||
let grow = try!(Number::parse_non_negative(context, input));
|
let grow = try!(Number::parse_non_negative(context, input));
|
||||||
let shrink = input.try(|i| Number::parse_non_negative(context, i)).ok();
|
let shrink = input.try(|i| Number::parse_non_negative(context, i)).ok();
|
||||||
Ok((grow, shrink))
|
Ok((grow, shrink))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<Longhands, ParseError<'i>> {
|
||||||
let mut grow = None;
|
let mut grow = None;
|
||||||
let mut shrink = None;
|
let mut shrink = None;
|
||||||
let mut basis = None;
|
let mut basis = None;
|
||||||
|
@ -87,7 +89,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
if grow.is_none() && basis.is_none() {
|
if grow.is_none() && basis.is_none() {
|
||||||
return Err(())
|
return Err(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
Ok(expanded! {
|
Ok(expanded! {
|
||||||
flex_grow: grow.unwrap_or(Number::new(1.0)),
|
flex_grow: grow.unwrap_or(Number::new(1.0)),
|
||||||
|
@ -118,7 +120,8 @@
|
||||||
products="gecko">
|
products="gecko">
|
||||||
use properties::longhands::{grid_row_gap, grid_column_gap};
|
use properties::longhands::{grid_row_gap, grid_column_gap};
|
||||||
|
|
||||||
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<Longhands, ParseError<'i>> {
|
||||||
let row_gap = grid_row_gap::parse(context, input)?;
|
let row_gap = grid_row_gap::parse(context, input)?;
|
||||||
let column_gap = input.try(|input| grid_column_gap::parse(context, input)).unwrap_or(row_gap.clone());
|
let column_gap = input.try(|input| grid_column_gap::parse(context, input)).unwrap_or(row_gap.clone());
|
||||||
|
|
||||||
|
@ -152,7 +155,8 @@
|
||||||
// NOTE: Since both the shorthands have the same code, we should (re-)use code from one to implement
|
// NOTE: Since both the shorthands have the same code, we should (re-)use code from one to implement
|
||||||
// the other. This might not be a big deal for now, but we should consider looking into this in the future
|
// the other. This might not be a big deal for now, but we should consider looking into this in the future
|
||||||
// to limit the amount of code generated.
|
// to limit the amount of code generated.
|
||||||
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<Longhands, ParseError<'i>> {
|
||||||
let start = input.try(|i| GridLine::parse(context, i))?;
|
let start = input.try(|i| GridLine::parse(context, i))?;
|
||||||
let end = if input.try(|i| i.expect_delim('/')).is_ok() {
|
let end = if input.try(|i| i.expect_delim('/')).is_ok() {
|
||||||
GridLine::parse(context, input)?
|
GridLine::parse(context, input)?
|
||||||
|
@ -189,7 +193,8 @@
|
||||||
use parser::Parse;
|
use parser::Parse;
|
||||||
|
|
||||||
// The code is the same as `grid-{row,column}` except that this can have four values at most.
|
// The code is the same as `grid-{row,column}` except that this can have four values at most.
|
||||||
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<Longhands, ParseError<'i>> {
|
||||||
fn line_with_ident_from(other: &GridLine) -> GridLine {
|
fn line_with_ident_from(other: &GridLine) -> GridLine {
|
||||||
let mut this = GridLine::default();
|
let mut this = GridLine::default();
|
||||||
if other.line_num.is_none() && !other.is_span {
|
if other.line_num.is_none() && !other.is_span {
|
||||||
|
@ -259,8 +264,9 @@
|
||||||
use values::specified::grid::parse_line_names;
|
use values::specified::grid::parse_line_names;
|
||||||
|
|
||||||
/// Parsing for `<grid-template>` shorthand (also used by `grid` shorthand).
|
/// Parsing for `<grid-template>` shorthand (also used by `grid` shorthand).
|
||||||
pub fn parse_grid_template(context: &ParserContext, input: &mut Parser)
|
pub fn parse_grid_template<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
-> Result<(TrackListOrNone, TrackListOrNone, Either<TemplateAreas, None_>), ()> {
|
-> Result<(TrackListOrNone, TrackListOrNone, Either<TemplateAreas, None_>),
|
||||||
|
ParseError<'i>> {
|
||||||
if input.try(|i| i.expect_ident_matching("none")).is_ok() {
|
if input.try(|i| i.expect_ident_matching("none")).is_ok() {
|
||||||
return Ok((Either::Second(None_), Either::Second(None_), Either::Second(None_)))
|
return Ok((Either::Second(None_), Either::Second(None_), Either::Second(None_)))
|
||||||
}
|
}
|
||||||
|
@ -295,7 +301,8 @@
|
||||||
line_names.push(vec![]); // should be one longer than track sizes
|
line_names.push(vec![]); // should be one longer than track sizes
|
||||||
}
|
}
|
||||||
|
|
||||||
let template_areas = TemplateAreas::from_vec(strings)?;
|
let template_areas = TemplateAreas::from_vec(strings)
|
||||||
|
.map_err(|()| StyleParseError::UnspecifiedError)?;
|
||||||
let template_rows = TrackList {
|
let template_rows = TrackList {
|
||||||
list_type: TrackListType::Normal,
|
list_type: TrackListType::Normal,
|
||||||
values: values,
|
values: values,
|
||||||
|
@ -306,7 +313,7 @@
|
||||||
let template_cols = if input.try(|i| i.expect_delim('/')).is_ok() {
|
let template_cols = if input.try(|i| i.expect_delim('/')).is_ok() {
|
||||||
let track_list = TrackList::parse(context, input)?;
|
let track_list = TrackList::parse(context, input)?;
|
||||||
if track_list.list_type != TrackListType::Explicit {
|
if track_list.list_type != TrackListType::Explicit {
|
||||||
return Err(())
|
return Err(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
Either::First(track_list)
|
Either::First(track_list)
|
||||||
|
@ -326,7 +333,8 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<Longhands, ParseError<'i>> {
|
||||||
let (rows, columns, areas) = parse_grid_template(context, input)?;
|
let (rows, columns, areas) = parse_grid_template(context, input)?;
|
||||||
Ok(expanded! {
|
Ok(expanded! {
|
||||||
grid_template_rows: rows,
|
grid_template_rows: rows,
|
||||||
|
@ -410,7 +418,8 @@
|
||||||
use values::{Either, None_};
|
use values::{Either, None_};
|
||||||
use values::specified::{LengthOrPercentage, TrackSize};
|
use values::specified::{LengthOrPercentage, TrackSize};
|
||||||
|
|
||||||
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<Longhands, ParseError<'i>> {
|
||||||
let mut temp_rows = Either::Second(None_);
|
let mut temp_rows = Either::Second(None_);
|
||||||
let mut temp_cols = Either::Second(None_);
|
let mut temp_cols = Either::Second(None_);
|
||||||
let mut temp_areas = Either::Second(None_);
|
let mut temp_areas = Either::Second(None_);
|
||||||
|
@ -418,7 +427,8 @@
|
||||||
let mut auto_cols = TrackSize::default();
|
let mut auto_cols = TrackSize::default();
|
||||||
let mut flow = grid_auto_flow::get_initial_value();
|
let mut flow = grid_auto_flow::get_initial_value();
|
||||||
|
|
||||||
fn parse_auto_flow(input: &mut Parser, is_row: bool) -> Result<SpecifiedAutoFlow, ()> {
|
fn parse_auto_flow<'i, 't>(input: &mut Parser<'i, 't>, is_row: bool)
|
||||||
|
-> Result<SpecifiedAutoFlow, ParseError<'i>> {
|
||||||
let mut auto_flow = None;
|
let mut auto_flow = None;
|
||||||
let mut dense = false;
|
let mut dense = false;
|
||||||
for _ in 0..2 {
|
for _ in 0..2 {
|
||||||
|
@ -440,7 +450,7 @@
|
||||||
autoflow: flow,
|
autoflow: flow,
|
||||||
dense: dense,
|
dense: dense,
|
||||||
}
|
}
|
||||||
}).ok_or(())
|
}).ok_or(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Ok((rows, cols, areas)) = input.try(|i| super::grid_template::parse_grid_template(context, i)) {
|
if let Ok((rows, cols, areas)) = input.try(|i| super::grid_template::parse_grid_template(context, i)) {
|
||||||
|
@ -506,15 +516,16 @@
|
||||||
use properties::longhands::align_content;
|
use properties::longhands::align_content;
|
||||||
use properties::longhands::justify_content;
|
use properties::longhands::justify_content;
|
||||||
|
|
||||||
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<Longhands, ParseError<'i>> {
|
||||||
let align = align_content::parse(context, input)?;
|
let align = align_content::parse(context, input)?;
|
||||||
if align.has_extra_flags() {
|
if align.has_extra_flags() {
|
||||||
return Err(());
|
return Err(StyleParseError::UnspecifiedError.into());
|
||||||
}
|
}
|
||||||
let justify = input.try(|input| justify_content::parse(context, input))
|
let justify = input.try(|input| justify_content::parse(context, input))
|
||||||
.unwrap_or(justify_content::SpecifiedValue::from(align));
|
.unwrap_or(justify_content::SpecifiedValue::from(align));
|
||||||
if justify.has_extra_flags() {
|
if justify.has_extra_flags() {
|
||||||
return Err(());
|
return Err(StyleParseError::UnspecifiedError.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(expanded! {
|
Ok(expanded! {
|
||||||
|
@ -541,14 +552,15 @@
|
||||||
use values::specified::align::AlignJustifySelf;
|
use values::specified::align::AlignJustifySelf;
|
||||||
use parser::Parse;
|
use parser::Parse;
|
||||||
|
|
||||||
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<Longhands, ParseError<'i>> {
|
||||||
let align = AlignJustifySelf::parse(context, input)?;
|
let align = AlignJustifySelf::parse(context, input)?;
|
||||||
if align.has_extra_flags() {
|
if align.has_extra_flags() {
|
||||||
return Err(());
|
return Err(StyleParseError::UnspecifiedError.into());
|
||||||
}
|
}
|
||||||
let justify = input.try(|input| AlignJustifySelf::parse(context, input)).unwrap_or(align.clone());
|
let justify = input.try(|input| AlignJustifySelf::parse(context, input)).unwrap_or(align.clone());
|
||||||
if justify.has_extra_flags() {
|
if justify.has_extra_flags() {
|
||||||
return Err(());
|
return Err(StyleParseError::UnspecifiedError.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(expanded! {
|
Ok(expanded! {
|
||||||
|
@ -582,15 +594,16 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<Longhands, ParseError<'i>> {
|
||||||
let align = AlignItems::parse(context, input)?;
|
let align = AlignItems::parse(context, input)?;
|
||||||
if align.has_extra_flags() {
|
if align.has_extra_flags() {
|
||||||
return Err(());
|
return Err(StyleParseError::UnspecifiedError.into());
|
||||||
}
|
}
|
||||||
let justify = input.try(|input| JustifyItems::parse(context, input))
|
let justify = input.try(|input| JustifyItems::parse(context, input))
|
||||||
.unwrap_or(JustifyItems::from(align));
|
.unwrap_or(JustifyItems::from(align));
|
||||||
if justify.has_extra_flags() {
|
if justify.has_extra_flags() {
|
||||||
return Err(());
|
return Err(StyleParseError::UnspecifiedError.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(expanded! {
|
Ok(expanded! {
|
||||||
|
|
|
@ -16,7 +16,8 @@
|
||||||
use properties::longhands::text_decoration_line;
|
use properties::longhands::text_decoration_line;
|
||||||
% endif
|
% endif
|
||||||
|
|
||||||
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<Longhands, ParseError<'i>> {
|
||||||
% if product == "gecko" or data.testing:
|
% if product == "gecko" or data.testing:
|
||||||
let (mut line, mut style, mut color, mut any) = (None, None, None, false);
|
let (mut line, mut style, mut color, mut any) = (None, None, None, false);
|
||||||
% else:
|
% else:
|
||||||
|
@ -47,7 +48,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
if !any {
|
if !any {
|
||||||
return Err(());
|
return Err(StyleParseError::UnspecifiedError.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(expanded! {
|
Ok(expanded! {
|
||||||
|
|
|
@ -6,10 +6,11 @@
|
||||||
|
|
||||||
#![deny(missing_docs)]
|
#![deny(missing_docs)]
|
||||||
|
|
||||||
use cssparser::Parser as CssParser;
|
use cssparser::{Parser as CssParser, ParserInput};
|
||||||
use selectors::Element;
|
use selectors::Element;
|
||||||
use selectors::parser::SelectorList;
|
use selectors::parser::SelectorList;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
|
use style_traits::ParseError;
|
||||||
use stylesheets::{Origin, Namespaces};
|
use stylesheets::{Origin, Namespaces};
|
||||||
|
|
||||||
/// A convenient alias for the type that represents an attribute value used for
|
/// A convenient alias for the type that represents an attribute value used for
|
||||||
|
@ -59,13 +60,14 @@ impl<'a> SelectorParser<'a> {
|
||||||
///
|
///
|
||||||
/// This is used for some DOM APIs like `querySelector`.
|
/// This is used for some DOM APIs like `querySelector`.
|
||||||
pub fn parse_author_origin_no_namespace(input: &str)
|
pub fn parse_author_origin_no_namespace(input: &str)
|
||||||
-> Result<SelectorList<SelectorImpl>, ()> {
|
-> Result<SelectorList<SelectorImpl>, ParseError> {
|
||||||
let namespaces = Namespaces::default();
|
let namespaces = Namespaces::default();
|
||||||
let parser = SelectorParser {
|
let parser = SelectorParser {
|
||||||
stylesheet_origin: Origin::Author,
|
stylesheet_origin: Origin::Author,
|
||||||
namespaces: &namespaces,
|
namespaces: &namespaces,
|
||||||
};
|
};
|
||||||
SelectorList::parse(&parser, &mut CssParser::new(input))
|
let mut input = ParserInput::new(input);
|
||||||
|
SelectorList::parse(&parser, &mut CssParser::new(&mut input))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Whether we're parsing selectors in a user-agent stylesheet.
|
/// Whether we're parsing selectors in a user-agent stylesheet.
|
||||||
|
|
|
@ -13,9 +13,10 @@ use media_queries::MediaType;
|
||||||
use parser::ParserContext;
|
use parser::ParserContext;
|
||||||
use properties::{ComputedValues, StyleBuilder};
|
use properties::{ComputedValues, StyleBuilder};
|
||||||
use properties::longhands::font_size;
|
use properties::longhands::font_size;
|
||||||
|
use selectors::parser::SelectorParseError;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::sync::atomic::{AtomicBool, AtomicIsize, Ordering};
|
use std::sync::atomic::{AtomicBool, AtomicIsize, Ordering};
|
||||||
use style_traits::{CSSPixel, ToCss};
|
use style_traits::{CSSPixel, ToCss, ParseError};
|
||||||
use style_traits::viewport::ViewportConstraints;
|
use style_traits::viewport::ViewportConstraints;
|
||||||
use values::computed::{self, ToComputedValue};
|
use values::computed::{self, ToComputedValue};
|
||||||
use values::specified;
|
use values::specified;
|
||||||
|
@ -151,7 +152,8 @@ impl Expression {
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// Only supports width and width ranges for now.
|
/// Only supports width and width ranges for now.
|
||||||
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<Self, ParseError<'i>> {
|
||||||
try!(input.expect_parenthesis_block());
|
try!(input.expect_parenthesis_block());
|
||||||
input.parse_nested_block(|input| {
|
input.parse_nested_block(|input| {
|
||||||
let name = try!(input.expect_ident());
|
let name = try!(input.expect_ident());
|
||||||
|
@ -167,7 +169,7 @@ impl Expression {
|
||||||
"width" => {
|
"width" => {
|
||||||
ExpressionKind::Width(Range::Eq(try!(specified::Length::parse_non_negative(context, input))))
|
ExpressionKind::Width(Range::Eq(try!(specified::Length::parse_non_negative(context, input))))
|
||||||
},
|
},
|
||||||
_ => return Err(())
|
_ => return Err(SelectorParseError::UnexpectedIdent(name.clone()).into())
|
||||||
}))
|
}))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ use restyle_hints::ElementSnapshot;
|
||||||
use selector_parser::{AttrValue as SelectorAttrValue, ElementExt, PseudoElementCascadeType, SelectorParser};
|
use selector_parser::{AttrValue as SelectorAttrValue, ElementExt, PseudoElementCascadeType, SelectorParser};
|
||||||
use selectors::Element;
|
use selectors::Element;
|
||||||
use selectors::attr::{AttrSelectorOperation, NamespaceConstraint};
|
use selectors::attr::{AttrSelectorOperation, NamespaceConstraint};
|
||||||
use selectors::parser::SelectorMethods;
|
use selectors::parser::{SelectorMethods, SelectorParseError};
|
||||||
use selectors::visitor::SelectorVisitor;
|
use selectors::visitor::SelectorVisitor;
|
||||||
use std::ascii::AsciiExt;
|
use std::ascii::AsciiExt;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
@ -24,6 +24,7 @@ use std::fmt;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
|
use style_traits::{ParseError, StyleParseError};
|
||||||
|
|
||||||
/// A pseudo-element, both public and private.
|
/// A pseudo-element, both public and private.
|
||||||
///
|
///
|
||||||
|
@ -300,10 +301,12 @@ impl ::selectors::SelectorImpl for SelectorImpl {
|
||||||
type BorrowedNamespaceUrl = Namespace;
|
type BorrowedNamespaceUrl = Namespace;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ::selectors::Parser for SelectorParser<'a> {
|
impl<'a, 'i> ::selectors::Parser<'i> for SelectorParser<'a> {
|
||||||
type Impl = SelectorImpl;
|
type Impl = SelectorImpl;
|
||||||
|
type Error = StyleParseError<'i>;
|
||||||
|
|
||||||
fn parse_non_ts_pseudo_class(&self, name: Cow<str>) -> Result<NonTSPseudoClass, ()> {
|
fn parse_non_ts_pseudo_class(&self, name: Cow<'i, str>)
|
||||||
|
-> Result<NonTSPseudoClass, ParseError<'i>> {
|
||||||
use self::NonTSPseudoClass::*;
|
use self::NonTSPseudoClass::*;
|
||||||
let pseudo_class = match_ignore_ascii_case! { &name,
|
let pseudo_class = match_ignore_ascii_case! { &name,
|
||||||
"active" => Active,
|
"active" => Active,
|
||||||
|
@ -323,20 +326,21 @@ impl<'a> ::selectors::Parser for SelectorParser<'a> {
|
||||||
"visited" => Visited,
|
"visited" => Visited,
|
||||||
"-servo-nonzero-border" => {
|
"-servo-nonzero-border" => {
|
||||||
if !self.in_user_agent_stylesheet() {
|
if !self.in_user_agent_stylesheet() {
|
||||||
return Err(());
|
return Err(SelectorParseError::UnexpectedIdent(
|
||||||
|
"-servo-nonzero-border".into()).into());
|
||||||
}
|
}
|
||||||
ServoNonZeroBorder
|
ServoNonZeroBorder
|
||||||
},
|
},
|
||||||
_ => return Err(())
|
_ => return Err(SelectorParseError::UnexpectedIdent(name.clone()).into()),
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(pseudo_class)
|
Ok(pseudo_class)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_non_ts_functional_pseudo_class(&self,
|
fn parse_non_ts_functional_pseudo_class<'t>(&self,
|
||||||
name: Cow<str>,
|
name: Cow<'i, str>,
|
||||||
parser: &mut CssParser)
|
parser: &mut CssParser<'i, 't>)
|
||||||
-> Result<NonTSPseudoClass, ()> {
|
-> Result<NonTSPseudoClass, ParseError<'i>> {
|
||||||
use self::NonTSPseudoClass::*;
|
use self::NonTSPseudoClass::*;
|
||||||
let pseudo_class = match_ignore_ascii_case!{ &name,
|
let pseudo_class = match_ignore_ascii_case!{ &name,
|
||||||
"lang" => {
|
"lang" => {
|
||||||
|
@ -344,18 +348,17 @@ impl<'a> ::selectors::Parser for SelectorParser<'a> {
|
||||||
}
|
}
|
||||||
"-servo-case-sensitive-type-attr" => {
|
"-servo-case-sensitive-type-attr" => {
|
||||||
if !self.in_user_agent_stylesheet() {
|
if !self.in_user_agent_stylesheet() {
|
||||||
return Err(());
|
return Err(SelectorParseError::UnexpectedIdent(name.clone()).into());
|
||||||
}
|
}
|
||||||
ServoCaseSensitiveTypeAttr(Atom::from(parser.expect_ident()?))
|
ServoCaseSensitiveTypeAttr(Atom::from(parser.expect_ident()?))
|
||||||
}
|
}
|
||||||
_ => return Err(())
|
_ => return Err(SelectorParseError::UnexpectedIdent(name.clone()).into())
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(pseudo_class)
|
Ok(pseudo_class)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_pseudo_element(&self, name: Cow<str>)
|
fn parse_pseudo_element(&self, name: Cow<'i, str>) -> Result<PseudoElement, ParseError<'i>> {
|
||||||
-> Result<PseudoElement, ()> {
|
|
||||||
use self::PseudoElement::*;
|
use self::PseudoElement::*;
|
||||||
let pseudo_element = match_ignore_ascii_case! { &name,
|
let pseudo_element = match_ignore_ascii_case! { &name,
|
||||||
"before" => Before,
|
"before" => Before,
|
||||||
|
@ -363,77 +366,78 @@ impl<'a> ::selectors::Parser for SelectorParser<'a> {
|
||||||
"selection" => Selection,
|
"selection" => Selection,
|
||||||
"-servo-details-summary" => {
|
"-servo-details-summary" => {
|
||||||
if !self.in_user_agent_stylesheet() {
|
if !self.in_user_agent_stylesheet() {
|
||||||
return Err(())
|
return Err(SelectorParseError::UnexpectedIdent(name.clone()).into())
|
||||||
}
|
}
|
||||||
DetailsSummary
|
DetailsSummary
|
||||||
},
|
},
|
||||||
"-servo-details-content" => {
|
"-servo-details-content" => {
|
||||||
if !self.in_user_agent_stylesheet() {
|
if !self.in_user_agent_stylesheet() {
|
||||||
return Err(())
|
return Err(SelectorParseError::UnexpectedIdent(name.clone()).into())
|
||||||
}
|
}
|
||||||
DetailsContent
|
DetailsContent
|
||||||
},
|
},
|
||||||
"-servo-text" => {
|
"-servo-text" => {
|
||||||
if !self.in_user_agent_stylesheet() {
|
if !self.in_user_agent_stylesheet() {
|
||||||
return Err(())
|
return Err(SelectorParseError::UnexpectedIdent(name.clone()).into())
|
||||||
}
|
}
|
||||||
ServoText
|
ServoText
|
||||||
},
|
},
|
||||||
"-servo-input-text" => {
|
"-servo-input-text" => {
|
||||||
if !self.in_user_agent_stylesheet() {
|
if !self.in_user_agent_stylesheet() {
|
||||||
return Err(())
|
return Err(SelectorParseError::UnexpectedIdent(name.clone()).into())
|
||||||
}
|
}
|
||||||
ServoInputText
|
ServoInputText
|
||||||
},
|
},
|
||||||
"-servo-table-wrapper" => {
|
"-servo-table-wrapper" => {
|
||||||
if !self.in_user_agent_stylesheet() {
|
if !self.in_user_agent_stylesheet() {
|
||||||
return Err(())
|
return Err(SelectorParseError::UnexpectedIdent(name.clone()).into())
|
||||||
}
|
}
|
||||||
ServoTableWrapper
|
ServoTableWrapper
|
||||||
},
|
},
|
||||||
"-servo-anonymous-table-wrapper" => {
|
"-servo-anonymous-table-wrapper" => {
|
||||||
if !self.in_user_agent_stylesheet() {
|
if !self.in_user_agent_stylesheet() {
|
||||||
return Err(())
|
return Err(SelectorParseError::UnexpectedIdent(name.clone()).into())
|
||||||
}
|
}
|
||||||
ServoAnonymousTableWrapper
|
ServoAnonymousTableWrapper
|
||||||
},
|
},
|
||||||
"-servo-anonymous-table" => {
|
"-servo-anonymous-table" => {
|
||||||
if !self.in_user_agent_stylesheet() {
|
if !self.in_user_agent_stylesheet() {
|
||||||
return Err(())
|
return Err(SelectorParseError::UnexpectedIdent(name.clone()).into())
|
||||||
}
|
}
|
||||||
ServoAnonymousTable
|
ServoAnonymousTable
|
||||||
},
|
},
|
||||||
"-servo-anonymous-table-row" => {
|
"-servo-anonymous-table-row" => {
|
||||||
if !self.in_user_agent_stylesheet() {
|
if !self.in_user_agent_stylesheet() {
|
||||||
return Err(())
|
return Err(SelectorParseError::UnexpectedIdent(name.clone()).into())
|
||||||
}
|
}
|
||||||
ServoAnonymousTableRow
|
ServoAnonymousTableRow
|
||||||
},
|
},
|
||||||
"-servo-anonymous-table-cell" => {
|
"-servo-anonymous-table-cell" => {
|
||||||
if !self.in_user_agent_stylesheet() {
|
if !self.in_user_agent_stylesheet() {
|
||||||
return Err(())
|
return Err(SelectorParseError::UnexpectedIdent(name.clone()).into())
|
||||||
}
|
}
|
||||||
ServoAnonymousTableCell
|
ServoAnonymousTableCell
|
||||||
},
|
},
|
||||||
"-servo-anonymous-block" => {
|
"-servo-anonymous-block" => {
|
||||||
if !self.in_user_agent_stylesheet() {
|
if !self.in_user_agent_stylesheet() {
|
||||||
return Err(())
|
return Err(SelectorParseError::UnexpectedIdent(name.clone()).into())
|
||||||
}
|
}
|
||||||
ServoAnonymousBlock
|
ServoAnonymousBlock
|
||||||
},
|
},
|
||||||
"-servo-inline-block-wrapper" => {
|
"-servo-inline-block-wrapper" => {
|
||||||
if !self.in_user_agent_stylesheet() {
|
if !self.in_user_agent_stylesheet() {
|
||||||
return Err(())
|
return Err(SelectorParseError::UnexpectedIdent(name.clone()).into())
|
||||||
}
|
}
|
||||||
ServoInlineBlockWrapper
|
ServoInlineBlockWrapper
|
||||||
},
|
},
|
||||||
"-servo-input-absolute" => {
|
"-servo-input-absolute" => {
|
||||||
if !self.in_user_agent_stylesheet() {
|
if !self.in_user_agent_stylesheet() {
|
||||||
return Err(())
|
return Err(SelectorParseError::UnexpectedIdent(name.clone()).into())
|
||||||
}
|
}
|
||||||
ServoInlineAbsolute
|
ServoInlineAbsolute
|
||||||
},
|
},
|
||||||
_ => return Err(())
|
_ => return Err(SelectorParseError::UnexpectedIdent(name.clone()).into())
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(pseudo_element)
|
Ok(pseudo_element)
|
||||||
|
|
|
@ -13,7 +13,7 @@ use std::fmt::{self, Write};
|
||||||
// nonzero optimization is important in keeping the size of SpecifiedUrl below
|
// nonzero optimization is important in keeping the size of SpecifiedUrl below
|
||||||
// the threshold.
|
// the threshold.
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use style_traits::ToCss;
|
use style_traits::{ToCss, ParseError};
|
||||||
|
|
||||||
/// A specified url() value for servo.
|
/// A specified url() value for servo.
|
||||||
///
|
///
|
||||||
|
@ -43,7 +43,7 @@ impl SpecifiedUrl {
|
||||||
/// gecko version.
|
/// gecko version.
|
||||||
pub fn parse_from_string<'a>(url: Cow<'a, str>,
|
pub fn parse_from_string<'a>(url: Cow<'a, str>,
|
||||||
context: &ParserContext)
|
context: &ParserContext)
|
||||||
-> Result<Self, ()> {
|
-> Result<Self, ParseError<'a>> {
|
||||||
let serialization = Arc::new(url.into_owned());
|
let serialization = Arc::new(url.into_owned());
|
||||||
let resolved = context.url_data.join(&serialization).ok();
|
let resolved = context.url_data.join(&serialization).ok();
|
||||||
Ok(SpecifiedUrl {
|
Ok(SpecifiedUrl {
|
||||||
|
|
|
@ -6,12 +6,12 @@
|
||||||
//! initially in CSS Conditional Rules Module Level 3, @document has been postponed to the level 4.
|
//! initially in CSS Conditional Rules Module Level 3, @document has been postponed to the level 4.
|
||||||
//! We implement the prefixed `@-moz-document`.
|
//! We implement the prefixed `@-moz-document`.
|
||||||
|
|
||||||
use cssparser::{Parser, Token, SourceLocation};
|
use cssparser::{Parser, Token, SourceLocation, BasicParseError};
|
||||||
use media_queries::Device;
|
use media_queries::Device;
|
||||||
use parser::{Parse, ParserContext};
|
use parser::{Parse, ParserContext};
|
||||||
use shared_lock::{DeepCloneWithLock, Locked, SharedRwLock, SharedRwLockReadGuard, ToCssWithGuard};
|
use shared_lock::{DeepCloneWithLock, Locked, SharedRwLock, SharedRwLockReadGuard, ToCssWithGuard};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use style_traits::ToCss;
|
use style_traits::{ToCss, ParseError, StyleParseError};
|
||||||
use stylearc::Arc;
|
use stylearc::Arc;
|
||||||
use stylesheets::CssRules;
|
use stylesheets::CssRules;
|
||||||
use values::specified::url::SpecifiedUrl;
|
use values::specified::url::SpecifiedUrl;
|
||||||
|
@ -90,9 +90,10 @@ macro_rules! parse_quoted_or_unquoted_string {
|
||||||
match input.next() {
|
match input.next() {
|
||||||
Ok(Token::QuotedString(value)) =>
|
Ok(Token::QuotedString(value)) =>
|
||||||
Ok($url_matching_function(value.into_owned())),
|
Ok($url_matching_function(value.into_owned())),
|
||||||
_ => Err(()),
|
Ok(t) => Err(BasicParseError::UnexpectedToken(t).into()),
|
||||||
|
Err(e) => Err(e.into()),
|
||||||
}
|
}
|
||||||
}).or_else(|_| {
|
}).or_else(|_: ParseError| {
|
||||||
while let Ok(_) = input.next() {}
|
while let Ok(_) = input.next() {}
|
||||||
Ok($url_matching_function(input.slice_from(start).to_string()))
|
Ok($url_matching_function(input.slice_from(start).to_string()))
|
||||||
})
|
})
|
||||||
|
@ -102,8 +103,8 @@ macro_rules! parse_quoted_or_unquoted_string {
|
||||||
|
|
||||||
impl UrlMatchingFunction {
|
impl UrlMatchingFunction {
|
||||||
/// Parse a URL matching function for a`@document` rule's condition.
|
/// Parse a URL matching function for a`@document` rule's condition.
|
||||||
pub fn parse(context: &ParserContext, input: &mut Parser)
|
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
-> Result<UrlMatchingFunction, ()> {
|
-> Result<UrlMatchingFunction, ParseError<'i>> {
|
||||||
if input.try(|input| input.expect_function_matching("url-prefix")).is_ok() {
|
if input.try(|input| input.expect_function_matching("url-prefix")).is_ok() {
|
||||||
parse_quoted_or_unquoted_string!(input, UrlMatchingFunction::UrlPrefix)
|
parse_quoted_or_unquoted_string!(input, UrlMatchingFunction::UrlPrefix)
|
||||||
} else if input.try(|input| input.expect_function_matching("domain")).is_ok() {
|
} else if input.try(|input| input.expect_function_matching("domain")).is_ok() {
|
||||||
|
@ -115,7 +116,7 @@ impl UrlMatchingFunction {
|
||||||
} else if let Ok(url) = input.try(|input| SpecifiedUrl::parse(context, input)) {
|
} else if let Ok(url) = input.try(|input| SpecifiedUrl::parse(context, input)) {
|
||||||
Ok(UrlMatchingFunction::Url(url))
|
Ok(UrlMatchingFunction::Url(url))
|
||||||
} else {
|
} else {
|
||||||
Err(())
|
Err(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -189,8 +190,8 @@ pub struct DocumentCondition(Vec<UrlMatchingFunction>);
|
||||||
|
|
||||||
impl DocumentCondition {
|
impl DocumentCondition {
|
||||||
/// Parse a document condition.
|
/// Parse a document condition.
|
||||||
pub fn parse(context: &ParserContext, input: &mut Parser)
|
pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
-> Result<Self, ()> {
|
-> Result<Self, ParseError<'i>> {
|
||||||
input.parse_comma_separated(|input| UrlMatchingFunction::parse(context, input))
|
input.parse_comma_separated(|input| UrlMatchingFunction::parse(context, input))
|
||||||
.map(DocumentCondition)
|
.map(DocumentCondition)
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,18 +4,20 @@
|
||||||
|
|
||||||
//! Keyframes: https://drafts.csswg.org/css-animations/#keyframes
|
//! Keyframes: https://drafts.csswg.org/css-animations/#keyframes
|
||||||
|
|
||||||
use cssparser::{AtRuleParser, Parser, QualifiedRuleParser, RuleListParser};
|
use cssparser::{AtRuleParser, Parser, QualifiedRuleParser, RuleListParser, ParserInput};
|
||||||
use cssparser::{DeclarationListParser, DeclarationParser, parse_one_rule, SourceLocation};
|
use cssparser::{DeclarationListParser, DeclarationParser, parse_one_rule, SourceLocation};
|
||||||
use error_reporting::{NullReporter, ParseError};
|
use error_reporting::{NullReporter, ContextualParseError};
|
||||||
use parser::{PARSING_MODE_DEFAULT, ParserContext, log_css_error};
|
use parser::{PARSING_MODE_DEFAULT, ParserContext, log_css_error};
|
||||||
use properties::{Importance, PropertyDeclaration, PropertyDeclarationBlock, PropertyId};
|
use properties::{Importance, PropertyDeclaration, PropertyDeclarationBlock, PropertyId};
|
||||||
use properties::{PropertyDeclarationId, LonghandId, SourcePropertyDeclaration};
|
use properties::{PropertyDeclarationId, LonghandId, SourcePropertyDeclaration};
|
||||||
use properties::LonghandIdSet;
|
use properties::LonghandIdSet;
|
||||||
use properties::animated_properties::TransitionProperty;
|
use properties::animated_properties::TransitionProperty;
|
||||||
use properties::longhands::transition_timing_function::single_value::SpecifiedValue as SpecifiedTimingFunction;
|
use properties::longhands::transition_timing_function::single_value::SpecifiedValue as SpecifiedTimingFunction;
|
||||||
|
use selectors::parser::SelectorParseError;
|
||||||
use shared_lock::{DeepCloneWithLock, SharedRwLock, SharedRwLockReadGuard, Locked, ToCssWithGuard};
|
use shared_lock::{DeepCloneWithLock, SharedRwLock, SharedRwLockReadGuard, Locked, ToCssWithGuard};
|
||||||
|
use std::borrow::Cow;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use style_traits::ToCss;
|
use style_traits::{ToCss, ParseError, StyleParseError};
|
||||||
use stylearc::Arc;
|
use stylearc::Arc;
|
||||||
use stylesheets::{CssRuleType, Stylesheet};
|
use stylesheets::{CssRuleType, Stylesheet};
|
||||||
use stylesheets::rule_parser::VendorPrefix;
|
use stylesheets::rule_parser::VendorPrefix;
|
||||||
|
@ -61,7 +63,8 @@ impl KeyframesRule {
|
||||||
/// Related spec:
|
/// Related spec:
|
||||||
/// https://drafts.csswg.org/css-animations-1/#interface-csskeyframesrule-findrule
|
/// https://drafts.csswg.org/css-animations-1/#interface-csskeyframesrule-findrule
|
||||||
pub fn find_rule(&self, guard: &SharedRwLockReadGuard, selector: &str) -> Option<usize> {
|
pub fn find_rule(&self, guard: &SharedRwLockReadGuard, selector: &str) -> Option<usize> {
|
||||||
if let Ok(selector) = Parser::new(selector).parse_entirely(KeyframeSelector::parse) {
|
let mut input = ParserInput::new(selector);
|
||||||
|
if let Ok(selector) = Parser::new(&mut input).parse_entirely(KeyframeSelector::parse) {
|
||||||
for (i, keyframe) in self.keyframes.iter().enumerate().rev() {
|
for (i, keyframe) in self.keyframes.iter().enumerate().rev() {
|
||||||
if keyframe.read_with(guard).selector == selector {
|
if keyframe.read_with(guard).selector == selector {
|
||||||
return Some(i);
|
return Some(i);
|
||||||
|
@ -120,7 +123,7 @@ impl KeyframePercentage {
|
||||||
KeyframePercentage(value)
|
KeyframePercentage(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse(input: &mut Parser) -> Result<KeyframePercentage, ()> {
|
fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result<KeyframePercentage, ParseError<'i>> {
|
||||||
let percentage = if input.try(|input| input.expect_ident_matching("from")).is_ok() {
|
let percentage = if input.try(|input| input.expect_ident_matching("from")).is_ok() {
|
||||||
KeyframePercentage::new(0.)
|
KeyframePercentage::new(0.)
|
||||||
} else if input.try(|input| input.expect_ident_matching("to")).is_ok() {
|
} else if input.try(|input| input.expect_ident_matching("to")).is_ok() {
|
||||||
|
@ -130,7 +133,7 @@ impl KeyframePercentage {
|
||||||
if percentage >= 0. && percentage <= 1. {
|
if percentage >= 0. && percentage <= 1. {
|
||||||
KeyframePercentage::new(percentage)
|
KeyframePercentage::new(percentage)
|
||||||
} else {
|
} else {
|
||||||
return Err(());
|
return Err(StyleParseError::UnspecifiedError.into());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -168,7 +171,7 @@ impl KeyframeSelector {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a keyframe selector from CSS input.
|
/// Parse a keyframe selector from CSS input.
|
||||||
pub fn parse(input: &mut Parser) -> Result<Self, ()> {
|
pub fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
input.parse_comma_separated(KeyframePercentage::parse)
|
input.parse_comma_separated(KeyframePercentage::parse)
|
||||||
.map(KeyframeSelector)
|
.map(KeyframeSelector)
|
||||||
}
|
}
|
||||||
|
@ -200,8 +203,8 @@ impl ToCssWithGuard for Keyframe {
|
||||||
|
|
||||||
impl Keyframe {
|
impl Keyframe {
|
||||||
/// Parse a CSS keyframe.
|
/// Parse a CSS keyframe.
|
||||||
pub fn parse(css: &str, parent_stylesheet: &Stylesheet)
|
pub fn parse<'i>(css: &'i str, parent_stylesheet: &Stylesheet)
|
||||||
-> Result<Arc<Locked<Self>>, ()> {
|
-> Result<Arc<Locked<Self>>, ParseError<'i>> {
|
||||||
let error_reporter = NullReporter;
|
let error_reporter = NullReporter;
|
||||||
let context = ParserContext::new(parent_stylesheet.origin,
|
let context = ParserContext::new(parent_stylesheet.origin,
|
||||||
&parent_stylesheet.url_data,
|
&parent_stylesheet.url_data,
|
||||||
|
@ -209,7 +212,8 @@ impl Keyframe {
|
||||||
Some(CssRuleType::Keyframe),
|
Some(CssRuleType::Keyframe),
|
||||||
PARSING_MODE_DEFAULT,
|
PARSING_MODE_DEFAULT,
|
||||||
parent_stylesheet.quirks_mode);
|
parent_stylesheet.quirks_mode);
|
||||||
let mut input = Parser::new(css);
|
let mut input = ParserInput::new(css);
|
||||||
|
let mut input = Parser::new(&mut input);
|
||||||
|
|
||||||
let mut declarations = SourcePropertyDeclaration::new();
|
let mut declarations = SourcePropertyDeclaration::new();
|
||||||
let mut rule_parser = KeyframeListParser {
|
let mut rule_parser = KeyframeListParser {
|
||||||
|
@ -445,29 +449,31 @@ pub fn parse_keyframe_list(context: &ParserContext, input: &mut Parser, shared_l
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Void {}
|
enum Void {}
|
||||||
impl<'a> AtRuleParser for KeyframeListParser<'a> {
|
impl<'a, 'i> AtRuleParser<'i> for KeyframeListParser<'a> {
|
||||||
type Prelude = Void;
|
type Prelude = Void;
|
||||||
type AtRule = Arc<Locked<Keyframe>>;
|
type AtRule = Arc<Locked<Keyframe>>;
|
||||||
|
type Error = SelectorParseError<'i, StyleParseError<'i>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> QualifiedRuleParser for KeyframeListParser<'a> {
|
impl<'a, 'i> QualifiedRuleParser<'i> for KeyframeListParser<'a> {
|
||||||
type Prelude = KeyframeSelector;
|
type Prelude = KeyframeSelector;
|
||||||
type QualifiedRule = Arc<Locked<Keyframe>>;
|
type QualifiedRule = Arc<Locked<Keyframe>>;
|
||||||
|
type Error = SelectorParseError<'i, StyleParseError<'i>>;
|
||||||
|
|
||||||
fn parse_prelude(&mut self, input: &mut Parser) -> Result<Self::Prelude, ()> {
|
fn parse_prelude<'t>(&mut self, input: &mut Parser<'i, 't>) -> Result<Self::Prelude, ParseError<'i>> {
|
||||||
let start = input.position();
|
let start = input.position();
|
||||||
match KeyframeSelector::parse(input) {
|
match KeyframeSelector::parse(input) {
|
||||||
Ok(sel) => Ok(sel),
|
Ok(sel) => Ok(sel),
|
||||||
Err(()) => {
|
Err(e) => {
|
||||||
let error = ParseError::InvalidKeyframeRule(input.slice_from(start));
|
let error = ContextualParseError::InvalidKeyframeRule(input.slice_from(start), e.clone());
|
||||||
log_css_error(input, start, error, self.context);
|
log_css_error(input, start, error, self.context);
|
||||||
Err(())
|
Err(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_block(&mut self, prelude: Self::Prelude, input: &mut Parser)
|
fn parse_block<'t>(&mut self, prelude: Self::Prelude, input: &mut Parser<'i, 't>)
|
||||||
-> Result<Self::QualifiedRule, ()> {
|
-> Result<Self::QualifiedRule, ParseError<'i>> {
|
||||||
let context = ParserContext::new_with_rule_type(self.context, Some(CssRuleType::Keyframe));
|
let context = ParserContext::new_with_rule_type(self.context, Some(CssRuleType::Keyframe));
|
||||||
let parser = KeyframeDeclarationParser {
|
let parser = KeyframeDeclarationParser {
|
||||||
context: &context,
|
context: &context,
|
||||||
|
@ -480,10 +486,11 @@ impl<'a> QualifiedRuleParser for KeyframeListParser<'a> {
|
||||||
Ok(()) => {
|
Ok(()) => {
|
||||||
block.extend(iter.parser.declarations.drain(), Importance::Normal);
|
block.extend(iter.parser.declarations.drain(), Importance::Normal);
|
||||||
}
|
}
|
||||||
Err(range) => {
|
Err(err) => {
|
||||||
iter.parser.declarations.clear();
|
iter.parser.declarations.clear();
|
||||||
let pos = range.start;
|
let pos = err.span.start;
|
||||||
let error = ParseError::UnsupportedKeyframePropertyDeclaration(iter.input.slice(range));
|
let error = ContextualParseError::UnsupportedKeyframePropertyDeclaration(
|
||||||
|
iter.input.slice(err.span), err.error);
|
||||||
log_css_error(iter.input, pos, error, &context);
|
log_css_error(iter.input, pos, error, &context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -502,22 +509,25 @@ struct KeyframeDeclarationParser<'a, 'b: 'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Default methods reject all at rules.
|
/// Default methods reject all at rules.
|
||||||
impl<'a, 'b> AtRuleParser for KeyframeDeclarationParser<'a, 'b> {
|
impl<'a, 'b, 'i> AtRuleParser<'i> for KeyframeDeclarationParser<'a, 'b> {
|
||||||
type Prelude = ();
|
type Prelude = ();
|
||||||
type AtRule = ();
|
type AtRule = ();
|
||||||
|
type Error = SelectorParseError<'i, StyleParseError<'i>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b> DeclarationParser for KeyframeDeclarationParser<'a, 'b> {
|
impl<'a, 'b, 'i> DeclarationParser<'i> for KeyframeDeclarationParser<'a, 'b> {
|
||||||
type Declaration = ();
|
type Declaration = ();
|
||||||
|
type Error = SelectorParseError<'i, StyleParseError<'i>>;
|
||||||
|
|
||||||
fn parse_value(&mut self, name: &str, input: &mut Parser) -> Result<(), ()> {
|
fn parse_value<'t>(&mut self, name: Cow<'i, str>, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<(), ParseError<'i>> {
|
||||||
let id = try!(PropertyId::parse(name.into()));
|
let id = try!(PropertyId::parse(name.into()));
|
||||||
match PropertyDeclaration::parse_into(self.declarations, id, self.context, input) {
|
match PropertyDeclaration::parse_into(self.declarations, id, self.context, input) {
|
||||||
Ok(()) => {
|
Ok(()) => {
|
||||||
// In case there is still unparsed text in the declaration, we should roll back.
|
// In case there is still unparsed text in the declaration, we should roll back.
|
||||||
input.expect_exhausted()
|
input.expect_exhausted().map_err(|e| e.into())
|
||||||
}
|
}
|
||||||
Err(_) => Err(())
|
Err(_e) => Err(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ mod stylesheet;
|
||||||
pub mod supports_rule;
|
pub mod supports_rule;
|
||||||
pub mod viewport_rule;
|
pub mod viewport_rule;
|
||||||
|
|
||||||
use cssparser::{parse_one_rule, Parser};
|
use cssparser::{parse_one_rule, Parser, ParserInput};
|
||||||
use error_reporting::NullReporter;
|
use error_reporting::NullReporter;
|
||||||
use parser::{ParserContext, PARSING_MODE_DEFAULT};
|
use parser::{ParserContext, PARSING_MODE_DEFAULT};
|
||||||
use shared_lock::{DeepCloneWithLock, Locked, SharedRwLock, SharedRwLockReadGuard, ToCssWithGuard};
|
use shared_lock::{DeepCloneWithLock, Locked, SharedRwLock, SharedRwLockReadGuard, ToCssWithGuard};
|
||||||
|
@ -234,7 +234,8 @@ impl CssRule {
|
||||||
parent_stylesheet.quirks_mode
|
parent_stylesheet.quirks_mode
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut input = Parser::new(css);
|
let mut input = ParserInput::new(css);
|
||||||
|
let mut input = Parser::new(&mut input);
|
||||||
|
|
||||||
let mut guard = parent_stylesheet.namespaces.write();
|
let mut guard = parent_stylesheet.namespaces.write();
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
use {Namespace, Prefix};
|
use {Namespace, Prefix};
|
||||||
use counter_style::{parse_counter_style_body, parse_counter_style_name};
|
use counter_style::{parse_counter_style_body, parse_counter_style_name};
|
||||||
use cssparser::{AtRuleParser, AtRuleType, Parser, QualifiedRuleParser, RuleListParser, SourceLocation};
|
use cssparser::{AtRuleParser, AtRuleType, Parser, QualifiedRuleParser, RuleListParser, SourceLocation};
|
||||||
use error_reporting::ParseError;
|
use error_reporting::ContextualParseError;
|
||||||
use font_face::parse_font_face_block;
|
use font_face::parse_font_face_block;
|
||||||
use media_queries::{parse_media_query_list, MediaList};
|
use media_queries::{parse_media_query_list, MediaList};
|
||||||
use parking_lot::RwLock;
|
use parking_lot::RwLock;
|
||||||
|
@ -15,9 +15,12 @@ use parser::{Parse, ParserContext, log_css_error};
|
||||||
use properties::parse_property_declaration_list;
|
use properties::parse_property_declaration_list;
|
||||||
use selector_parser::{SelectorImpl, SelectorParser};
|
use selector_parser::{SelectorImpl, SelectorParser};
|
||||||
use selectors::SelectorList;
|
use selectors::SelectorList;
|
||||||
|
use selectors::parser::SelectorParseError;
|
||||||
use shared_lock::{Locked, SharedRwLock};
|
use shared_lock::{Locked, SharedRwLock};
|
||||||
|
use std::borrow::Cow;
|
||||||
use std::sync::atomic::AtomicBool;
|
use std::sync::atomic::AtomicBool;
|
||||||
use str::starts_with_ignore_ascii_case;
|
use str::starts_with_ignore_ascii_case;
|
||||||
|
use style_traits::{StyleParseError, ParseError};
|
||||||
use stylearc::Arc;
|
use stylearc::Arc;
|
||||||
use stylesheets::{CssRule, CssRules, CssRuleType, Origin, StylesheetLoader};
|
use stylesheets::{CssRule, CssRules, CssRuleType, Origin, StylesheetLoader};
|
||||||
use stylesheets::{DocumentRule, ImportRule, KeyframesRule, MediaRule, NamespaceRule, PageRule};
|
use stylesheets::{DocumentRule, ImportRule, KeyframesRule, MediaRule, NamespaceRule, PageRule};
|
||||||
|
@ -133,22 +136,24 @@ fn register_namespace(_: &Namespace) -> Result<(), ()> {
|
||||||
Ok(()) // servo doesn't use namespace ids
|
Ok(()) // servo doesn't use namespace ids
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> AtRuleParser for TopLevelRuleParser<'a> {
|
impl<'a, 'i> AtRuleParser<'i> for TopLevelRuleParser<'a> {
|
||||||
type Prelude = AtRulePrelude;
|
type Prelude = AtRulePrelude;
|
||||||
type AtRule = CssRule;
|
type AtRule = CssRule;
|
||||||
|
type Error = SelectorParseError<'i, StyleParseError<'i>>;
|
||||||
|
|
||||||
fn parse_prelude(
|
fn parse_prelude<'t>(
|
||||||
&mut self,
|
&mut self,
|
||||||
name: &str,
|
name: Cow<'i, str>,
|
||||||
input: &mut Parser
|
input: &mut Parser<'i, 't>
|
||||||
) -> Result<AtRuleType<AtRulePrelude, CssRule>, ()> {
|
) -> Result<AtRuleType<AtRulePrelude, CssRule>, ParseError<'i>> {
|
||||||
let location = get_location_with_offset(input.current_source_location(),
|
let location = get_location_with_offset(input.current_source_location(),
|
||||||
self.context.line_number_offset);
|
self.context.line_number_offset);
|
||||||
match_ignore_ascii_case! { name,
|
match_ignore_ascii_case! { &*name,
|
||||||
"import" => {
|
"import" => {
|
||||||
if self.state > State::Imports {
|
if self.state > State::Imports {
|
||||||
self.state = State::Invalid;
|
self.state = State::Invalid;
|
||||||
return Err(()) // "@import must be before any rule but @charset"
|
// "@import must be before any rule but @charset"
|
||||||
|
return Err(StyleParseError::UnexpectedImportRule.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
self.state = State::Imports;
|
self.state = State::Imports;
|
||||||
|
@ -191,14 +196,16 @@ impl<'a> AtRuleParser for TopLevelRuleParser<'a> {
|
||||||
"namespace" => {
|
"namespace" => {
|
||||||
if self.state > State::Namespaces {
|
if self.state > State::Namespaces {
|
||||||
self.state = State::Invalid;
|
self.state = State::Invalid;
|
||||||
return Err(()) // "@namespace must be before any rule but @charset and @import"
|
// "@namespace must be before any rule but @charset and @import"
|
||||||
|
return Err(StyleParseError::UnexpectedNamespaceRule.into())
|
||||||
}
|
}
|
||||||
self.state = State::Namespaces;
|
self.state = State::Namespaces;
|
||||||
|
|
||||||
let prefix_result = input.try(|input| input.expect_ident());
|
let prefix_result = input.try(|input| input.expect_ident());
|
||||||
let url = Namespace::from(try!(input.expect_url_or_string()));
|
let url = Namespace::from(try!(input.expect_url_or_string()));
|
||||||
|
|
||||||
let id = register_namespace(&url)?;
|
let id = register_namespace(&url)
|
||||||
|
.map_err(|()| StyleParseError::UnspecifiedError)?;
|
||||||
|
|
||||||
let mut namespaces = self.namespaces.as_mut().unwrap();
|
let mut namespaces = self.namespaces.as_mut().unwrap();
|
||||||
|
|
||||||
|
@ -223,13 +230,13 @@ impl<'a> AtRuleParser for TopLevelRuleParser<'a> {
|
||||||
},
|
},
|
||||||
// @charset is removed by rust-cssparser if it’s the first rule in the stylesheet
|
// @charset is removed by rust-cssparser if it’s the first rule in the stylesheet
|
||||||
// anything left is invalid.
|
// anything left is invalid.
|
||||||
"charset" => return Err(()), // (insert appropriate error message)
|
"charset" => return Err(StyleParseError::UnexpectedCharsetRule.into()),
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
// Don't allow starting with an invalid state
|
// Don't allow starting with an invalid state
|
||||||
if self.state > State::Body {
|
if self.state > State::Body {
|
||||||
self.state = State::Invalid;
|
self.state = State::Invalid;
|
||||||
return Err(());
|
return Err(StyleParseError::UnspecifiedError.into());
|
||||||
}
|
}
|
||||||
self.state = State::Body;
|
self.state = State::Body;
|
||||||
|
|
||||||
|
@ -243,18 +250,21 @@ impl<'a> AtRuleParser for TopLevelRuleParser<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn parse_block(&mut self, prelude: AtRulePrelude, input: &mut Parser) -> Result<CssRule, ()> {
|
fn parse_block<'t>(&mut self, prelude: AtRulePrelude, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<CssRule, ParseError<'i>> {
|
||||||
AtRuleParser::parse_block(&mut self.nested(), prelude, input)
|
AtRuleParser::parse_block(&mut self.nested(), prelude, input)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl<'a> QualifiedRuleParser for TopLevelRuleParser<'a> {
|
impl<'a, 'i> QualifiedRuleParser<'i> for TopLevelRuleParser<'a> {
|
||||||
type Prelude = SelectorList<SelectorImpl>;
|
type Prelude = SelectorList<SelectorImpl>;
|
||||||
type QualifiedRule = CssRule;
|
type QualifiedRule = CssRule;
|
||||||
|
type Error = SelectorParseError<'i, StyleParseError<'i>>;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn parse_prelude(&mut self, input: &mut Parser) -> Result<SelectorList<SelectorImpl>, ()> {
|
fn parse_prelude<'t>(&mut self, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<SelectorList<SelectorImpl>, ParseError<'i>> {
|
||||||
self.state = State::Body;
|
self.state = State::Body;
|
||||||
|
|
||||||
// "Freeze" the namespace map (no more namespace rules can be parsed
|
// "Freeze" the namespace map (no more namespace rules can be parsed
|
||||||
|
@ -268,11 +278,11 @@ impl<'a> QualifiedRuleParser for TopLevelRuleParser<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn parse_block(
|
fn parse_block<'t>(
|
||||||
&mut self,
|
&mut self,
|
||||||
prelude: SelectorList<SelectorImpl>,
|
prelude: SelectorList<SelectorImpl>,
|
||||||
input: &mut Parser
|
input: &mut Parser<'i, 't>
|
||||||
) -> Result<CssRule, ()> {
|
) -> Result<CssRule, ParseError<'i>> {
|
||||||
QualifiedRuleParser::parse_block(&mut self.nested(), prelude, input)
|
QualifiedRuleParser::parse_block(&mut self.nested(), prelude, input)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -303,9 +313,10 @@ impl<'a, 'b> NestedRuleParser<'a, 'b> {
|
||||||
while let Some(result) = iter.next() {
|
while let Some(result) = iter.next() {
|
||||||
match result {
|
match result {
|
||||||
Ok(rule) => rules.push(rule),
|
Ok(rule) => rules.push(rule),
|
||||||
Err(range) => {
|
Err(err) => {
|
||||||
let pos = range.start;
|
let pos = err.span.start;
|
||||||
let error = ParseError::UnsupportedRule(iter.input.slice(range));
|
let error = ContextualParseError::UnsupportedRule(
|
||||||
|
iter.input.slice(err.span), err.error);
|
||||||
log_css_error(iter.input, pos, error, self.context);
|
log_css_error(iter.input, pos, error, self.context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -325,22 +336,23 @@ fn is_viewport_enabled() -> bool {
|
||||||
false // Gecko doesn't support @viewport.
|
false // Gecko doesn't support @viewport.
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b> AtRuleParser for NestedRuleParser<'a, 'b> {
|
impl<'a, 'b, 'i> AtRuleParser<'i> for NestedRuleParser<'a, 'b> {
|
||||||
type Prelude = AtRulePrelude;
|
type Prelude = AtRulePrelude;
|
||||||
type AtRule = CssRule;
|
type AtRule = CssRule;
|
||||||
|
type Error = SelectorParseError<'i, StyleParseError<'i>>;
|
||||||
|
|
||||||
fn parse_prelude(
|
fn parse_prelude<'t>(
|
||||||
&mut self,
|
&mut self,
|
||||||
name: &str,
|
name: Cow<'i, str>,
|
||||||
input: &mut Parser
|
input: &mut Parser<'i, 't>
|
||||||
) -> Result<AtRuleType<AtRulePrelude, CssRule>, ()> {
|
) -> Result<AtRuleType<AtRulePrelude, CssRule>, ParseError<'i>> {
|
||||||
let location =
|
let location =
|
||||||
get_location_with_offset(
|
get_location_with_offset(
|
||||||
input.current_source_location(),
|
input.current_source_location(),
|
||||||
self.context.line_number_offset
|
self.context.line_number_offset
|
||||||
);
|
);
|
||||||
|
|
||||||
match_ignore_ascii_case! { name,
|
match_ignore_ascii_case! { &*name,
|
||||||
"media" => {
|
"media" => {
|
||||||
let media_queries = parse_media_query_list(self.context, input);
|
let media_queries = parse_media_query_list(self.context, input);
|
||||||
let arc = Arc::new(self.shared_lock.wrap(media_queries));
|
let arc = Arc::new(self.shared_lock.wrap(media_queries));
|
||||||
|
@ -356,14 +368,14 @@ impl<'a, 'b> AtRuleParser for NestedRuleParser<'a, 'b> {
|
||||||
"counter-style" => {
|
"counter-style" => {
|
||||||
if !cfg!(feature = "gecko") {
|
if !cfg!(feature = "gecko") {
|
||||||
// Support for this rule is not fully implemented in Servo yet.
|
// Support for this rule is not fully implemented in Servo yet.
|
||||||
return Err(())
|
return Err(StyleParseError::UnsupportedAtRule(name.clone()).into())
|
||||||
}
|
}
|
||||||
let name = parse_counter_style_name(input)?;
|
let name = parse_counter_style_name(input)?;
|
||||||
// ASCII-case-insensitive matches for "decimal" are already
|
// ASCII-case-insensitive matches for "decimal" are already
|
||||||
// lower-cased by `parse_counter_style_name`, so we can use ==
|
// lower-cased by `parse_counter_style_name`, so we can use ==
|
||||||
// here.
|
// here.
|
||||||
if name.0 == atom!("decimal") {
|
if name.0 == atom!("decimal") {
|
||||||
return Err(())
|
return Err(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
Ok(AtRuleType::WithBlock(AtRulePrelude::CounterStyle(name)))
|
Ok(AtRuleType::WithBlock(AtRulePrelude::CounterStyle(name)))
|
||||||
},
|
},
|
||||||
|
@ -371,13 +383,13 @@ impl<'a, 'b> AtRuleParser for NestedRuleParser<'a, 'b> {
|
||||||
if is_viewport_enabled() {
|
if is_viewport_enabled() {
|
||||||
Ok(AtRuleType::WithBlock(AtRulePrelude::Viewport))
|
Ok(AtRuleType::WithBlock(AtRulePrelude::Viewport))
|
||||||
} else {
|
} else {
|
||||||
Err(())
|
Err(StyleParseError::UnsupportedAtRule(name.clone()).into())
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"keyframes" | "-webkit-keyframes" | "-moz-keyframes" => {
|
"keyframes" | "-webkit-keyframes" | "-moz-keyframes" => {
|
||||||
let prefix = if starts_with_ignore_ascii_case(name, "-webkit-") {
|
let prefix = if starts_with_ignore_ascii_case(&*name, "-webkit-") {
|
||||||
Some(VendorPrefix::WebKit)
|
Some(VendorPrefix::WebKit)
|
||||||
} else if starts_with_ignore_ascii_case(name, "-moz-") {
|
} else if starts_with_ignore_ascii_case(&*name, "-moz-") {
|
||||||
Some(VendorPrefix::Moz)
|
Some(VendorPrefix::Moz)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
@ -385,7 +397,7 @@ impl<'a, 'b> AtRuleParser for NestedRuleParser<'a, 'b> {
|
||||||
if cfg!(feature = "servo") &&
|
if cfg!(feature = "servo") &&
|
||||||
prefix.as_ref().map_or(false, |p| matches!(*p, VendorPrefix::Moz)) {
|
prefix.as_ref().map_or(false, |p| matches!(*p, VendorPrefix::Moz)) {
|
||||||
// Servo should not support @-moz-keyframes.
|
// Servo should not support @-moz-keyframes.
|
||||||
return Err(())
|
return Err(StyleParseError::UnsupportedAtRule(name.clone()).into())
|
||||||
}
|
}
|
||||||
let name = KeyframesName::parse(self.context, input)?;
|
let name = KeyframesName::parse(self.context, input)?;
|
||||||
|
|
||||||
|
@ -395,7 +407,7 @@ impl<'a, 'b> AtRuleParser for NestedRuleParser<'a, 'b> {
|
||||||
if cfg!(feature = "gecko") {
|
if cfg!(feature = "gecko") {
|
||||||
Ok(AtRuleType::WithBlock(AtRulePrelude::Page(location)))
|
Ok(AtRuleType::WithBlock(AtRulePrelude::Page(location)))
|
||||||
} else {
|
} else {
|
||||||
Err(())
|
Err(StyleParseError::UnsupportedAtRule(name.clone()).into())
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"-moz-document" => {
|
"-moz-document" => {
|
||||||
|
@ -403,18 +415,18 @@ impl<'a, 'b> AtRuleParser for NestedRuleParser<'a, 'b> {
|
||||||
let cond = DocumentCondition::parse(self.context, input)?;
|
let cond = DocumentCondition::parse(self.context, input)?;
|
||||||
Ok(AtRuleType::WithBlock(AtRulePrelude::Document(cond, location)))
|
Ok(AtRuleType::WithBlock(AtRulePrelude::Document(cond, location)))
|
||||||
} else {
|
} else {
|
||||||
Err(())
|
Err(StyleParseError::UnsupportedAtRule(name.clone()).into())
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
_ => Err(())
|
_ => Err(StyleParseError::UnsupportedAtRule(name.clone()).into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_block(
|
fn parse_block<'t>(
|
||||||
&mut self,
|
&mut self,
|
||||||
prelude: AtRulePrelude,
|
prelude: AtRulePrelude,
|
||||||
input: &mut Parser
|
input: &mut Parser<'i, 't>
|
||||||
) -> Result<CssRule, ()> {
|
) -> Result<CssRule, ParseError<'i>> {
|
||||||
match prelude {
|
match prelude {
|
||||||
AtRulePrelude::FontFace(location) => {
|
AtRulePrelude::FontFace(location) => {
|
||||||
let context = ParserContext::new_with_rule_type(self.context, Some(CssRuleType::FontFace));
|
let context = ParserContext::new_with_rule_type(self.context, Some(CssRuleType::FontFace));
|
||||||
|
@ -479,11 +491,13 @@ impl<'a, 'b> AtRuleParser for NestedRuleParser<'a, 'b> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b> QualifiedRuleParser for NestedRuleParser<'a, 'b> {
|
impl<'a, 'b, 'i> QualifiedRuleParser<'i> for NestedRuleParser<'a, 'b> {
|
||||||
type Prelude = SelectorList<SelectorImpl>;
|
type Prelude = SelectorList<SelectorImpl>;
|
||||||
type QualifiedRule = CssRule;
|
type QualifiedRule = CssRule;
|
||||||
|
type Error = SelectorParseError<'i, StyleParseError<'i>>;
|
||||||
|
|
||||||
fn parse_prelude(&mut self, input: &mut Parser) -> Result<SelectorList<SelectorImpl>, ()> {
|
fn parse_prelude<'t>(&mut self, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<SelectorList<SelectorImpl>, ParseError<'i>> {
|
||||||
let selector_parser = SelectorParser {
|
let selector_parser = SelectorParser {
|
||||||
stylesheet_origin: self.stylesheet_origin,
|
stylesheet_origin: self.stylesheet_origin,
|
||||||
namespaces: self.context.namespaces.unwrap(),
|
namespaces: self.context.namespaces.unwrap(),
|
||||||
|
@ -492,11 +506,11 @@ impl<'a, 'b> QualifiedRuleParser for NestedRuleParser<'a, 'b> {
|
||||||
SelectorList::parse(&selector_parser, input)
|
SelectorList::parse(&selector_parser, input)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_block(
|
fn parse_block<'t>(
|
||||||
&mut self,
|
&mut self,
|
||||||
prelude: SelectorList<SelectorImpl>,
|
prelude: SelectorList<SelectorImpl>,
|
||||||
input: &mut Parser
|
input: &mut Parser<'i, 't>
|
||||||
) -> Result<CssRule, ()> {
|
) -> Result<CssRule, ParseError<'i>> {
|
||||||
let location = get_location_with_offset(input.current_source_location(),
|
let location = get_location_with_offset(input.current_source_location(),
|
||||||
self.context.line_number_offset);
|
self.context.line_number_offset);
|
||||||
let context = ParserContext::new_with_rule_type(self.context, Some(CssRuleType::Style));
|
let context = ParserContext::new_with_rule_type(self.context, Some(CssRuleType::Style));
|
||||||
|
|
|
@ -4,8 +4,8 @@
|
||||||
|
|
||||||
use {Prefix, Namespace};
|
use {Prefix, Namespace};
|
||||||
use context::QuirksMode;
|
use context::QuirksMode;
|
||||||
use cssparser::{Parser, RuleListParser};
|
use cssparser::{Parser, RuleListParser, ParserInput};
|
||||||
use error_reporting::{ParseErrorReporter, ParseError};
|
use error_reporting::{ParseErrorReporter, ContextualParseError};
|
||||||
use fnv::FnvHashMap;
|
use fnv::FnvHashMap;
|
||||||
use media_queries::{MediaList, Device};
|
use media_queries::{MediaList, Device};
|
||||||
use parking_lot::RwLock;
|
use parking_lot::RwLock;
|
||||||
|
@ -110,7 +110,8 @@ impl Stylesheet {
|
||||||
line_number_offset: u64
|
line_number_offset: u64
|
||||||
) -> (Vec<CssRule>, bool) {
|
) -> (Vec<CssRule>, bool) {
|
||||||
let mut rules = Vec::new();
|
let mut rules = Vec::new();
|
||||||
let mut input = Parser::new(css);
|
let mut input = ParserInput::new(css);
|
||||||
|
let mut input = Parser::new(&mut input);
|
||||||
|
|
||||||
let context =
|
let context =
|
||||||
ParserContext::new_with_line_number_offset(
|
ParserContext::new_with_line_number_offset(
|
||||||
|
@ -140,9 +141,10 @@ impl Stylesheet {
|
||||||
while let Some(result) = iter.next() {
|
while let Some(result) = iter.next() {
|
||||||
match result {
|
match result {
|
||||||
Ok(rule) => rules.push(rule),
|
Ok(rule) => rules.push(rule),
|
||||||
Err(range) => {
|
Err(err) => {
|
||||||
let pos = range.start;
|
let pos = err.span.start;
|
||||||
let error = ParseError::InvalidRule(iter.input.slice(range));
|
let error = ContextualParseError::InvalidRule(
|
||||||
|
iter.input.slice(err.span), err.error);
|
||||||
log_css_error(iter.input, pos, error, iter.parser.context());
|
log_css_error(iter.input, pos, error, iter.parser.context());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,12 +4,14 @@
|
||||||
|
|
||||||
//! [@supports rules](https://drafts.csswg.org/css-conditional-3/#at-supports)
|
//! [@supports rules](https://drafts.csswg.org/css-conditional-3/#at-supports)
|
||||||
|
|
||||||
|
use cssparser::{BasicParseError, ParseError as CssParseError, ParserInput};
|
||||||
use cssparser::{Delimiter, parse_important, Parser, SourceLocation, Token};
|
use cssparser::{Delimiter, parse_important, Parser, SourceLocation, Token};
|
||||||
use parser::ParserContext;
|
use parser::ParserContext;
|
||||||
use properties::{PropertyId, PropertyDeclaration, SourcePropertyDeclaration};
|
use properties::{PropertyId, PropertyDeclaration, SourcePropertyDeclaration};
|
||||||
|
use selectors::parser::SelectorParseError;
|
||||||
use shared_lock::{DeepCloneWithLock, Locked, SharedRwLock, SharedRwLockReadGuard, ToCssWithGuard};
|
use shared_lock::{DeepCloneWithLock, Locked, SharedRwLock, SharedRwLockReadGuard, ToCssWithGuard};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use style_traits::ToCss;
|
use style_traits::{ToCss, ParseError, StyleParseError};
|
||||||
use stylearc::Arc;
|
use stylearc::Arc;
|
||||||
use stylesheets::{CssRuleType, CssRules};
|
use stylesheets::{CssRuleType, CssRules};
|
||||||
|
|
||||||
|
@ -81,7 +83,7 @@ impl SupportsCondition {
|
||||||
/// Parse a condition
|
/// Parse a condition
|
||||||
///
|
///
|
||||||
/// https://drafts.csswg.org/css-conditional/#supports_condition
|
/// https://drafts.csswg.org/css-conditional/#supports_condition
|
||||||
pub fn parse(input: &mut Parser) -> Result<SupportsCondition, ()> {
|
pub fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result<SupportsCondition, ParseError<'i>> {
|
||||||
if let Ok(_) = input.try(|i| i.expect_ident_matching("not")) {
|
if let Ok(_) = input.try(|i| i.expect_ident_matching("not")) {
|
||||||
let inner = SupportsCondition::parse_in_parens(input)?;
|
let inner = SupportsCondition::parse_in_parens(input)?;
|
||||||
return Ok(SupportsCondition::Not(Box::new(inner)));
|
return Ok(SupportsCondition::Not(Box::new(inner)));
|
||||||
|
@ -90,7 +92,7 @@ impl SupportsCondition {
|
||||||
let in_parens = SupportsCondition::parse_in_parens(input)?;
|
let in_parens = SupportsCondition::parse_in_parens(input)?;
|
||||||
|
|
||||||
let (keyword, wrapper) = match input.next() {
|
let (keyword, wrapper) = match input.next() {
|
||||||
Err(()) => {
|
Err(_) => {
|
||||||
// End of input
|
// End of input
|
||||||
return Ok(in_parens)
|
return Ok(in_parens)
|
||||||
}
|
}
|
||||||
|
@ -98,10 +100,10 @@ impl SupportsCondition {
|
||||||
match_ignore_ascii_case! { &ident,
|
match_ignore_ascii_case! { &ident,
|
||||||
"and" => ("and", SupportsCondition::And as fn(_) -> _),
|
"and" => ("and", SupportsCondition::And as fn(_) -> _),
|
||||||
"or" => ("or", SupportsCondition::Or as fn(_) -> _),
|
"or" => ("or", SupportsCondition::Or as fn(_) -> _),
|
||||||
_ => return Err(())
|
_ => return Err(SelectorParseError::UnexpectedIdent(ident.clone()).into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => return Err(())
|
Ok(t) => return Err(CssParseError::Basic(BasicParseError::UnexpectedToken(t)))
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut conditions = Vec::with_capacity(2);
|
let mut conditions = Vec::with_capacity(2);
|
||||||
|
@ -118,7 +120,7 @@ impl SupportsCondition {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// https://drafts.csswg.org/css-conditional-3/#supports_condition_in_parens
|
/// https://drafts.csswg.org/css-conditional-3/#supports_condition_in_parens
|
||||||
fn parse_in_parens(input: &mut Parser) -> Result<SupportsCondition, ()> {
|
fn parse_in_parens<'i, 't>(input: &mut Parser<'i, 't>) -> Result<SupportsCondition, ParseError<'i>> {
|
||||||
// Whitespace is normally taken care of in `Parser::next`,
|
// Whitespace is normally taken care of in `Parser::next`,
|
||||||
// but we want to not include it in `pos` for the SupportsCondition::FutureSyntax cases.
|
// but we want to not include it in `pos` for the SupportsCondition::FutureSyntax cases.
|
||||||
while input.try(Parser::expect_whitespace).is_ok() {}
|
while input.try(Parser::expect_whitespace).is_ok() {}
|
||||||
|
@ -127,17 +129,18 @@ impl SupportsCondition {
|
||||||
Token::ParenthesisBlock => {
|
Token::ParenthesisBlock => {
|
||||||
input.parse_nested_block(|input| {
|
input.parse_nested_block(|input| {
|
||||||
// `input.try()` not needed here since the alternative uses `consume_all()`.
|
// `input.try()` not needed here since the alternative uses `consume_all()`.
|
||||||
parse_condition_or_declaration(input).or_else(|()| {
|
parse_condition_or_declaration(input).or_else(|_| {
|
||||||
consume_all(input);
|
consume_all(input);
|
||||||
Ok(SupportsCondition::FutureSyntax(input.slice_from(pos).to_owned()))
|
Ok(SupportsCondition::FutureSyntax(input.slice_from(pos).to_owned()))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
Token::Function(_) => {
|
Token::Function(_) => {
|
||||||
input.parse_nested_block(|i| Ok(consume_all(i))).unwrap();
|
let result: Result<_, ParseError> = input.parse_nested_block(|i| Ok(consume_all(i)));
|
||||||
|
result.unwrap();
|
||||||
Ok(SupportsCondition::FutureSyntax(input.slice_from(pos).to_owned()))
|
Ok(SupportsCondition::FutureSyntax(input.slice_from(pos).to_owned()))
|
||||||
}
|
}
|
||||||
_ => Err(())
|
t => Err(CssParseError::Basic(BasicParseError::UnexpectedToken(t)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,7 +159,8 @@ impl SupportsCondition {
|
||||||
|
|
||||||
/// supports_condition | declaration
|
/// supports_condition | declaration
|
||||||
/// https://drafts.csswg.org/css-conditional/#dom-css-supports-conditiontext-conditiontext
|
/// https://drafts.csswg.org/css-conditional/#dom-css-supports-conditiontext-conditiontext
|
||||||
pub fn parse_condition_or_declaration(input: &mut Parser) -> Result<SupportsCondition, ()> {
|
pub fn parse_condition_or_declaration<'i, 't>(input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<SupportsCondition, ParseError<'i>> {
|
||||||
if let Ok(condition) = input.try(SupportsCondition::parse) {
|
if let Ok(condition) = input.try(SupportsCondition::parse) {
|
||||||
Ok(SupportsCondition::Parenthesized(Box::new(condition)))
|
Ok(SupportsCondition::Parenthesized(Box::new(condition)))
|
||||||
} else {
|
} else {
|
||||||
|
@ -244,7 +248,7 @@ fn consume_all(input: &mut Parser) {
|
||||||
|
|
||||||
impl Declaration {
|
impl Declaration {
|
||||||
/// Parse a declaration
|
/// Parse a declaration
|
||||||
pub fn parse(input: &mut Parser) -> Result<Declaration, ()> {
|
pub fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Declaration, ParseError<'i>> {
|
||||||
let prop = input.expect_ident()?.into_owned();
|
let prop = input.expect_ident()?.into_owned();
|
||||||
input.expect_colon()?;
|
input.expect_colon()?;
|
||||||
let val = parse_anything(input);
|
let val = parse_anything(input);
|
||||||
|
@ -260,12 +264,13 @@ impl Declaration {
|
||||||
} else {
|
} else {
|
||||||
return false
|
return false
|
||||||
};
|
};
|
||||||
let mut input = Parser::new(&self.val);
|
let mut input = ParserInput::new(&self.val);
|
||||||
|
let mut input = Parser::new(&mut input);
|
||||||
let context = ParserContext::new_with_rule_type(cx, Some(CssRuleType::Style));
|
let context = ParserContext::new_with_rule_type(cx, Some(CssRuleType::Style));
|
||||||
let mut declarations = SourcePropertyDeclaration::new();
|
let mut declarations = SourcePropertyDeclaration::new();
|
||||||
let res = input.parse_until_before(Delimiter::Bang, |input| {
|
let res = input.parse_until_before(Delimiter::Bang, |input| {
|
||||||
PropertyDeclaration::parse_into(&mut declarations, id, &context, input)
|
PropertyDeclaration::parse_into(&mut declarations, id, &context, input)
|
||||||
.map_err(|_| ())
|
.map_err(|e| StyleParseError::PropertyDeclaration(e).into())
|
||||||
});
|
});
|
||||||
let _ = input.try(parse_important);
|
let _ = input.try(parse_important);
|
||||||
res.is_ok() && input.is_exhausted()
|
res.is_ok() && input.is_exhausted()
|
||||||
|
|
|
@ -11,19 +11,20 @@ use app_units::Au;
|
||||||
use context::QuirksMode;
|
use context::QuirksMode;
|
||||||
use cssparser::{AtRuleParser, DeclarationListParser, DeclarationParser, Parser, parse_important};
|
use cssparser::{AtRuleParser, DeclarationListParser, DeclarationParser, Parser, parse_important};
|
||||||
use cssparser::ToCss as ParserToCss;
|
use cssparser::ToCss as ParserToCss;
|
||||||
use error_reporting::ParseError;
|
use error_reporting::ContextualParseError;
|
||||||
use euclid::size::TypedSize2D;
|
use euclid::size::TypedSize2D;
|
||||||
use font_metrics::get_metrics_provider_for_product;
|
use font_metrics::get_metrics_provider_for_product;
|
||||||
use media_queries::Device;
|
use media_queries::Device;
|
||||||
use parser::{Parse, ParserContext, log_css_error};
|
use parser::{Parse, ParserContext, log_css_error};
|
||||||
use properties::StyleBuilder;
|
use properties::StyleBuilder;
|
||||||
|
use selectors::parser::SelectorParseError;
|
||||||
use shared_lock::{SharedRwLockReadGuard, ToCssWithGuard};
|
use shared_lock::{SharedRwLockReadGuard, ToCssWithGuard};
|
||||||
use std::ascii::AsciiExt;
|
use std::ascii::AsciiExt;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::iter::Enumerate;
|
use std::iter::Enumerate;
|
||||||
use std::str::Chars;
|
use std::str::Chars;
|
||||||
use style_traits::{PinchZoomFactor, ToCss};
|
use style_traits::{PinchZoomFactor, ToCss, ParseError, StyleParseError};
|
||||||
use style_traits::viewport::{Orientation, UserZoom, ViewportConstraints, Zoom};
|
use style_traits::viewport::{Orientation, UserZoom, ViewportConstraints, Zoom};
|
||||||
use stylearc::Arc;
|
use stylearc::Arc;
|
||||||
use stylesheets::{Stylesheet, Origin};
|
use stylesheets::{Stylesheet, Origin};
|
||||||
|
@ -168,7 +169,8 @@ impl FromMeta for ViewportLength {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ViewportLength {
|
impl ViewportLength {
|
||||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<Self, ParseError<'i>> {
|
||||||
// we explicitly do not accept 'extend-to-zoom', since it is a UA
|
// we explicitly do not accept 'extend-to-zoom', since it is a UA
|
||||||
// internal value for <META> viewport translation
|
// internal value for <META> viewport translation
|
||||||
LengthOrPercentageOrAuto::parse_non_negative(context, input).map(ViewportLength::Specified)
|
LengthOrPercentageOrAuto::parse_non_negative(context, input).map(ViewportLength::Specified)
|
||||||
|
@ -247,23 +249,27 @@ impl ToCss for ViewportDescriptorDeclaration {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_shorthand(context: &ParserContext, input: &mut Parser) -> Result<(ViewportLength, ViewportLength), ()> {
|
fn parse_shorthand<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<(ViewportLength, ViewportLength), ParseError<'i>> {
|
||||||
let min = try!(ViewportLength::parse(context, input));
|
let min = try!(ViewportLength::parse(context, input));
|
||||||
match input.try(|i| ViewportLength::parse(context, i)) {
|
match input.try(|i| ViewportLength::parse(context, i)) {
|
||||||
Err(()) => Ok((min.clone(), min)),
|
Err(_) => Ok((min.clone(), min)),
|
||||||
Ok(max) => Ok((min, max))
|
Ok(max) => Ok((min, max))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b> AtRuleParser for ViewportRuleParser<'a, 'b> {
|
impl<'a, 'b, 'i> AtRuleParser<'i> for ViewportRuleParser<'a, 'b> {
|
||||||
type Prelude = ();
|
type Prelude = ();
|
||||||
type AtRule = Vec<ViewportDescriptorDeclaration>;
|
type AtRule = Vec<ViewportDescriptorDeclaration>;
|
||||||
|
type Error = SelectorParseError<'i, StyleParseError<'i>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b> DeclarationParser for ViewportRuleParser<'a, 'b> {
|
impl<'a, 'b, 'i> DeclarationParser<'i> for ViewportRuleParser<'a, 'b> {
|
||||||
type Declaration = Vec<ViewportDescriptorDeclaration>;
|
type Declaration = Vec<ViewportDescriptorDeclaration>;
|
||||||
|
type Error = SelectorParseError<'i, StyleParseError<'i>>;
|
||||||
|
|
||||||
fn parse_value(&mut self, name: &str, input: &mut Parser) -> Result<Vec<ViewportDescriptorDeclaration>, ()> {
|
fn parse_value<'t>(&mut self, name: Cow<'i, str>, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<Vec<ViewportDescriptorDeclaration>, ParseError<'i>> {
|
||||||
macro_rules! declaration {
|
macro_rules! declaration {
|
||||||
($declaration:ident($parse:expr)) => {
|
($declaration:ident($parse:expr)) => {
|
||||||
declaration!($declaration(value: try!($parse(input)),
|
declaration!($declaration(value: try!($parse(input)),
|
||||||
|
@ -290,7 +296,7 @@ impl<'a, 'b> DeclarationParser for ViewportRuleParser<'a, 'b> {
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|
||||||
match_ignore_ascii_case! { name,
|
match_ignore_ascii_case! { &*name,
|
||||||
"min-width" => ok!(MinWidth(|i| ViewportLength::parse(self.context, i))),
|
"min-width" => ok!(MinWidth(|i| ViewportLength::parse(self.context, i))),
|
||||||
"max-width" => ok!(MaxWidth(|i| ViewportLength::parse(self.context, i))),
|
"max-width" => ok!(MaxWidth(|i| ViewportLength::parse(self.context, i))),
|
||||||
"width" => ok!(shorthand -> [MinWidth, MaxWidth]),
|
"width" => ok!(shorthand -> [MinWidth, MaxWidth]),
|
||||||
|
@ -302,7 +308,7 @@ impl<'a, 'b> DeclarationParser for ViewportRuleParser<'a, 'b> {
|
||||||
"max-zoom" => ok!(MaxZoom(Zoom::parse)),
|
"max-zoom" => ok!(MaxZoom(Zoom::parse)),
|
||||||
"user-zoom" => ok!(UserZoom(UserZoom::parse)),
|
"user-zoom" => ok!(UserZoom(UserZoom::parse)),
|
||||||
"orientation" => ok!(Orientation(Orientation::parse)),
|
"orientation" => ok!(Orientation(Orientation::parse)),
|
||||||
_ => Err(()),
|
_ => Err(SelectorParseError::UnexpectedIdent(name.clone()).into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -329,7 +335,7 @@ fn is_whitespace_separator_or_equals(c: &char) -> bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for ViewportRule {
|
impl Parse for ViewportRule {
|
||||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
let parser = ViewportRuleParser { context: context };
|
let parser = ViewportRuleParser { context: context };
|
||||||
|
|
||||||
let mut cascade = Cascade::new();
|
let mut cascade = Cascade::new();
|
||||||
|
@ -341,9 +347,10 @@ impl Parse for ViewportRule {
|
||||||
cascade.add(Cow::Owned(declarations))
|
cascade.add(Cow::Owned(declarations))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(range) => {
|
Err(err) => {
|
||||||
let pos = range.start;
|
let pos = err.span.start;
|
||||||
let error = ParseError::UnsupportedViewportDescriptorDeclaration(parser.input.slice(range));
|
let error = ContextualParseError::UnsupportedViewportDescriptorDeclaration(
|
||||||
|
parser.input.slice(err.span), err.error);
|
||||||
log_css_error(parser.input, pos, error, &context);
|
log_css_error(parser.input, pos, error, &context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,8 +7,9 @@
|
||||||
|
|
||||||
use cssparser::{Parser, serialize_identifier};
|
use cssparser::{Parser, serialize_identifier};
|
||||||
use parser::{Parse, ParserContext};
|
use parser::{Parse, ParserContext};
|
||||||
|
use selectors::parser::SelectorParseError;
|
||||||
use std::{fmt, mem, usize};
|
use std::{fmt, mem, usize};
|
||||||
use style_traits::ToCss;
|
use style_traits::{ToCss, ParseError, StyleParseError};
|
||||||
use values::{CSSFloat, CustomIdent};
|
use values::{CSSFloat, CustomIdent};
|
||||||
use values::computed::{self, ComputedValueAsSpecified, Context, ToComputedValue};
|
use values::computed::{self, ComputedValueAsSpecified, Context, ToComputedValue};
|
||||||
use values::specified::Integer;
|
use values::specified::Integer;
|
||||||
|
@ -70,7 +71,7 @@ impl ToCss for GridLine {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for GridLine {
|
impl Parse for GridLine {
|
||||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
let mut grid_line = Default::default();
|
let mut grid_line = Default::default();
|
||||||
if input.try(|i| i.expect_ident_matching("auto")).is_ok() {
|
if input.try(|i| i.expect_ident_matching("auto")).is_ok() {
|
||||||
return Ok(grid_line)
|
return Ok(grid_line)
|
||||||
|
@ -85,7 +86,7 @@ impl Parse for GridLine {
|
||||||
for _ in 0..3 { // Maximum possible entities for <grid-line>
|
for _ in 0..3 { // Maximum possible entities for <grid-line>
|
||||||
if input.try(|i| i.expect_ident_matching("span")).is_ok() {
|
if input.try(|i| i.expect_ident_matching("span")).is_ok() {
|
||||||
if grid_line.is_span {
|
if grid_line.is_span {
|
||||||
return Err(())
|
return Err(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
if grid_line.line_num.is_some() || grid_line.ident.is_some() {
|
if grid_line.line_num.is_some() || grid_line.ident.is_some() {
|
||||||
|
@ -95,14 +96,14 @@ impl Parse for GridLine {
|
||||||
grid_line.is_span = true;
|
grid_line.is_span = true;
|
||||||
} else if let Ok(i) = input.try(|i| Integer::parse(context, i)) {
|
} else if let Ok(i) = input.try(|i| Integer::parse(context, i)) {
|
||||||
if i.value() == 0 || val_before_span || grid_line.line_num.is_some() {
|
if i.value() == 0 || val_before_span || grid_line.line_num.is_some() {
|
||||||
return Err(())
|
return Err(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
grid_line.line_num = Some(i);
|
grid_line.line_num = Some(i);
|
||||||
} else if let Ok(name) = input.try(|i| i.expect_ident()) {
|
} else if let Ok(name) = input.try(|i| i.expect_ident()) {
|
||||||
if val_before_span || grid_line.ident.is_some() ||
|
if val_before_span || grid_line.ident.is_some() ||
|
||||||
CustomIdent::from_ident((&*name).into(), &[]).is_err() {
|
CustomIdent::from_ident((&*name).into(), &[]).is_err() {
|
||||||
return Err(())
|
return Err(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
grid_line.ident = Some(name.into_owned());
|
grid_line.ident = Some(name.into_owned());
|
||||||
|
@ -112,18 +113,18 @@ impl Parse for GridLine {
|
||||||
}
|
}
|
||||||
|
|
||||||
if grid_line.is_auto() {
|
if grid_line.is_auto() {
|
||||||
return Err(())
|
return Err(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
if grid_line.is_span {
|
if grid_line.is_span {
|
||||||
if let Some(i) = grid_line.line_num {
|
if let Some(i) = grid_line.line_num {
|
||||||
if i.value() <= 0 { // disallow negative integers for grid spans
|
if i.value() <= 0 { // disallow negative integers for grid spans
|
||||||
return Err(())
|
return Err(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
} else if grid_line.ident.is_some() { // integer could be omitted
|
} else if grid_line.ident.is_some() { // integer could be omitted
|
||||||
grid_line.line_num = Some(Integer::new(1));
|
grid_line.line_num = Some(Integer::new(1));
|
||||||
} else {
|
} else {
|
||||||
return Err(())
|
return Err(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -341,19 +342,20 @@ pub enum RepeatCount {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for RepeatCount {
|
impl Parse for RepeatCount {
|
||||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
if let Ok(i) = input.try(|i| Integer::parse(context, i)) {
|
if let Ok(i) = input.try(|i| Integer::parse(context, i)) {
|
||||||
if i.value() > 0 {
|
if i.value() > 0 {
|
||||||
Ok(RepeatCount::Number(i))
|
Ok(RepeatCount::Number(i))
|
||||||
} else {
|
} else {
|
||||||
Err(())
|
Err(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
match_ignore_ascii_case! { &input.expect_ident()?,
|
let ident = input.expect_ident()?;
|
||||||
|
(match_ignore_ascii_case! { &ident,
|
||||||
"auto-fill" => Ok(RepeatCount::AutoFill),
|
"auto-fill" => Ok(RepeatCount::AutoFill),
|
||||||
"auto-fit" => Ok(RepeatCount::AutoFit),
|
"auto-fit" => Ok(RepeatCount::AutoFit),
|
||||||
_ => Err(()),
|
_ => Err(()),
|
||||||
}
|
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,8 +8,9 @@
|
||||||
use counter_style::{Symbols, parse_counter_style_name};
|
use counter_style::{Symbols, parse_counter_style_name};
|
||||||
use cssparser::Parser;
|
use cssparser::Parser;
|
||||||
use parser::{Parse, ParserContext};
|
use parser::{Parse, ParserContext};
|
||||||
|
use selectors::parser::SelectorParseError;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use style_traits::{OneOrMoreCommaSeparated, ToCss};
|
use style_traits::{OneOrMoreCommaSeparated, ToCss, ParseError, StyleParseError};
|
||||||
use super::CustomIdent;
|
use super::CustomIdent;
|
||||||
use values::specified::url::SpecifiedUrl;
|
use values::specified::url::SpecifiedUrl;
|
||||||
|
|
||||||
|
@ -79,7 +80,7 @@ impl CounterStyleOrNone {
|
||||||
no_viewport_percentage!(CounterStyleOrNone);
|
no_viewport_percentage!(CounterStyleOrNone);
|
||||||
|
|
||||||
impl Parse for CounterStyleOrNone {
|
impl Parse for CounterStyleOrNone {
|
||||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
if let Ok(name) = input.try(|i| parse_counter_style_name(i)) {
|
if let Ok(name) = input.try(|i| parse_counter_style_name(i)) {
|
||||||
return Ok(CounterStyleOrNone::Name(name));
|
return Ok(CounterStyleOrNone::Name(name));
|
||||||
}
|
}
|
||||||
|
@ -95,16 +96,16 @@ impl Parse for CounterStyleOrNone {
|
||||||
// numeric system.
|
// numeric system.
|
||||||
if (symbols_type == SymbolsType::Alphabetic ||
|
if (symbols_type == SymbolsType::Alphabetic ||
|
||||||
symbols_type == SymbolsType::Numeric) && symbols.0.len() < 2 {
|
symbols_type == SymbolsType::Numeric) && symbols.0.len() < 2 {
|
||||||
return Err(());
|
return Err(StyleParseError::UnspecifiedError.into());
|
||||||
}
|
}
|
||||||
// Identifier is not allowed in symbols() function.
|
// Identifier is not allowed in symbols() function.
|
||||||
if symbols.0.iter().any(|sym| !sym.is_allowed_in_symbols()) {
|
if symbols.0.iter().any(|sym| !sym.is_allowed_in_symbols()) {
|
||||||
return Err(());
|
return Err(StyleParseError::UnspecifiedError.into());
|
||||||
}
|
}
|
||||||
Ok(CounterStyleOrNone::Symbols(symbols_type, symbols))
|
Ok(CounterStyleOrNone::Symbols(symbols_type, symbols))
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
Err(())
|
Err(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,7 +160,7 @@ impl<T: Parse> Parse for FontSettingTag<T> {
|
||||||
/// settings-control-the-font-variation-settings-property
|
/// settings-control-the-font-variation-settings-property
|
||||||
/// <string> [ on | off | <integer> ]
|
/// <string> [ on | off | <integer> ]
|
||||||
/// <string> <number>
|
/// <string> <number>
|
||||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
use byteorder::{ReadBytesExt, BigEndian};
|
use byteorder::{ReadBytesExt, BigEndian};
|
||||||
use std::io::Cursor;
|
use std::io::Cursor;
|
||||||
|
|
||||||
|
@ -169,7 +170,7 @@ impl<T: Parse> Parse for FontSettingTag<T> {
|
||||||
if tag.len() != 4 ||
|
if tag.len() != 4 ||
|
||||||
tag.chars().any(|c| c < ' ' || c > '~')
|
tag.chars().any(|c| c < ' ' || c > '~')
|
||||||
{
|
{
|
||||||
return Err(())
|
return Err(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut raw = Cursor::new(tag.as_bytes());
|
let mut raw = Cursor::new(tag.as_bytes());
|
||||||
|
@ -192,7 +193,7 @@ pub enum FontSettings<T> {
|
||||||
|
|
||||||
impl<T: Parse> Parse for FontSettings<T> {
|
impl<T: Parse> Parse for FontSettings<T> {
|
||||||
/// https://www.w3.org/TR/css-fonts-3/#propdef-font-feature-settings
|
/// https://www.w3.org/TR/css-fonts-3/#propdef-font-feature-settings
|
||||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
if input.try(|i| i.expect_ident_matching("normal")).is_ok() {
|
if input.try(|i| i.expect_ident_matching("normal")).is_ok() {
|
||||||
return Ok(FontSettings::Normal);
|
return Ok(FontSettings::Normal);
|
||||||
}
|
}
|
||||||
|
@ -227,13 +228,13 @@ impl ToCss for FontSettingTagInt {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for FontSettingTagInt {
|
impl Parse for FontSettingTagInt {
|
||||||
fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
if let Ok(value) = input.try(|input| input.expect_integer()) {
|
if let Ok(value) = input.try(|input| input.expect_integer()) {
|
||||||
// handle integer, throw if it is negative
|
// handle integer, throw if it is negative
|
||||||
if value >= 0 {
|
if value >= 0 {
|
||||||
Ok(FontSettingTagInt(value as u32))
|
Ok(FontSettingTagInt(value as u32))
|
||||||
} else {
|
} else {
|
||||||
Err(())
|
Err(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
} else if let Ok(_) = input.try(|input| input.expect_ident_matching("on")) {
|
} else if let Ok(_) = input.try(|input| input.expect_ident_matching("on")) {
|
||||||
// on is an alias for '1'
|
// on is an alias for '1'
|
||||||
|
@ -250,8 +251,8 @@ impl Parse for FontSettingTagInt {
|
||||||
|
|
||||||
|
|
||||||
impl Parse for FontSettingTagFloat {
|
impl Parse for FontSettingTagFloat {
|
||||||
fn parse(_: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
input.expect_number().map(FontSettingTagFloat)
|
input.expect_number().map(FontSettingTagFloat).map_err(|e| e.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -326,18 +327,19 @@ impl<ColorType> SVGPaint<ColorType> {
|
||||||
|
|
||||||
impl<ColorType> SVGPaintKind<ColorType> {
|
impl<ColorType> SVGPaintKind<ColorType> {
|
||||||
/// Parse a keyword value only
|
/// Parse a keyword value only
|
||||||
fn parse_ident(input: &mut Parser) -> Result<Self, ()> {
|
fn parse_ident<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
Ok(match_ignore_ascii_case! { &input.expect_ident()?,
|
let ident = input.expect_ident()?;
|
||||||
"none" => SVGPaintKind::None,
|
(match_ignore_ascii_case! { &ident,
|
||||||
"context-fill" => SVGPaintKind::ContextFill,
|
"none" => Ok(SVGPaintKind::None),
|
||||||
"context-stroke" => SVGPaintKind::ContextStroke,
|
"context-fill" => Ok(SVGPaintKind::ContextFill),
|
||||||
_ => return Err(())
|
"context-stroke" => Ok(SVGPaintKind::ContextStroke),
|
||||||
})
|
_ => Err(())
|
||||||
|
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<ColorType: Parse> Parse for SVGPaint<ColorType> {
|
impl<ColorType: Parse> Parse for SVGPaint<ColorType> {
|
||||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
if let Ok(url) = input.try(|i| SpecifiedUrl::parse(context, i)) {
|
if let Ok(url) = input.try(|i| SpecifiedUrl::parse(context, i)) {
|
||||||
let fallback = input.try(|i| ColorType::parse(context, i));
|
let fallback = input.try(|i| ColorType::parse(context, i));
|
||||||
Ok(SVGPaint {
|
Ok(SVGPaint {
|
||||||
|
@ -363,7 +365,7 @@ impl<ColorType: Parse> Parse for SVGPaint<ColorType> {
|
||||||
fallback: None,
|
fallback: None,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
Err(())
|
Err(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
use cssparser::Parser;
|
use cssparser::Parser;
|
||||||
use parser::{Parse, ParserContext};
|
use parser::{Parse, ParserContext};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use style_traits::ToCss;
|
use style_traits::{ToCss, ParseError};
|
||||||
|
|
||||||
/// A CSS value made of four components, where its `ToCss` impl will try to
|
/// A CSS value made of four components, where its `ToCss` impl will try to
|
||||||
/// serialize as few components as possible, like for example in `border-width`.
|
/// serialize as few components as possible, like for example in `border-width`.
|
||||||
|
@ -26,12 +26,12 @@ impl<T> Rect<T>
|
||||||
where T: Clone
|
where T: Clone
|
||||||
{
|
{
|
||||||
/// Parses a new `Rect<T>` value with the given parse function.
|
/// Parses a new `Rect<T>` value with the given parse function.
|
||||||
pub fn parse_with<Parse>(
|
pub fn parse_with<'i, 't, Parse>(
|
||||||
context: &ParserContext,
|
context: &ParserContext,
|
||||||
input: &mut Parser,
|
input: &mut Parser<'i, 't>,
|
||||||
parse: Parse)
|
parse: Parse)
|
||||||
-> Result<Self, ()>
|
-> Result<Self, ParseError<'i>>
|
||||||
where Parse: Fn(&ParserContext, &mut Parser) -> Result<T, ()>
|
where Parse: Fn(&ParserContext, &mut Parser<'i, 't>) -> Result<T, ParseError<'i>>
|
||||||
{
|
{
|
||||||
let first = parse(context, input)?;
|
let first = parse(context, input)?;
|
||||||
let second = if let Ok(second) = input.try(|i| parse(context, i)) { second } else {
|
let second = if let Ok(second) = input.try(|i| parse(context, i)) { second } else {
|
||||||
|
@ -64,7 +64,7 @@ impl<T> Parse for Rect<T>
|
||||||
where T: Clone + Parse
|
where T: Clone + Parse
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
Self::parse_with(context, input, T::parse)
|
Self::parse_with(context, input, T::parse)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ use cssparser::Parser;
|
||||||
use parser::ParserContext;
|
use parser::ParserContext;
|
||||||
use properties::animated_properties::Animatable;
|
use properties::animated_properties::Animatable;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use style_traits::ToCss;
|
use style_traits::{ToCss, ParseError};
|
||||||
|
|
||||||
/// A generic value for the `initial-letter` property.
|
/// A generic value for the `initial-letter` property.
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
|
@ -71,12 +71,12 @@ impl<Value> Spacing<Value> {
|
||||||
|
|
||||||
/// Parses.
|
/// Parses.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn parse_with<F>(
|
pub fn parse_with<'i, 't, F>(
|
||||||
context: &ParserContext,
|
context: &ParserContext,
|
||||||
input: &mut Parser,
|
input: &mut Parser<'i, 't>,
|
||||||
parse: F)
|
parse: F)
|
||||||
-> Result<Self, ()>
|
-> Result<Self, ParseError<'i>>
|
||||||
where F: FnOnce(&ParserContext, &mut Parser) -> Result<Value, ()>
|
where F: FnOnce(&ParserContext, &mut Parser<'i, 't>) -> Result<Value, ParseError<'i>>
|
||||||
{
|
{
|
||||||
if input.try(|i| i.expect_ident_matching("normal")).is_ok() {
|
if input.try(|i| i.expect_ident_matching("normal")).is_ok() {
|
||||||
return Ok(Spacing::Normal);
|
return Ok(Spacing::Normal);
|
||||||
|
|
|
@ -9,13 +9,14 @@
|
||||||
#![deny(missing_docs)]
|
#![deny(missing_docs)]
|
||||||
|
|
||||||
use Atom;
|
use Atom;
|
||||||
pub use cssparser::{RGBA, Token, Parser, serialize_identifier};
|
pub use cssparser::{RGBA, Token, Parser, serialize_identifier, BasicParseError};
|
||||||
use parser::{Parse, ParserContext};
|
use parser::{Parse, ParserContext};
|
||||||
|
use selectors::parser::SelectorParseError;
|
||||||
use std::ascii::AsciiExt;
|
use std::ascii::AsciiExt;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::fmt::{self, Debug};
|
use std::fmt::{self, Debug};
|
||||||
use std::hash;
|
use std::hash;
|
||||||
use style_traits::ToCss;
|
use style_traits::{ToCss, ParseError, StyleParseError};
|
||||||
|
|
||||||
pub mod computed;
|
pub mod computed;
|
||||||
pub mod generics;
|
pub mod generics;
|
||||||
|
@ -54,7 +55,8 @@ impl<A: Debug, B: Debug> Debug for Either<A, B> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<A: Parse, B: Parse> Parse for Either<A, B> {
|
impl<A: Parse, B: Parse> Parse for Either<A, B> {
|
||||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Either<A, B>, ()> {
|
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<Either<A, B>, ParseError<'i>> {
|
||||||
if let Ok(v) = input.try(|i| A::parse(context, i)) {
|
if let Ok(v) = input.try(|i| A::parse(context, i)) {
|
||||||
Ok(Either::First(v))
|
Ok(Either::First(v))
|
||||||
} else {
|
} else {
|
||||||
|
@ -91,13 +93,16 @@ pub struct CustomIdent(pub Atom);
|
||||||
|
|
||||||
impl CustomIdent {
|
impl CustomIdent {
|
||||||
/// Parse an already-tokenizer identifier
|
/// Parse an already-tokenizer identifier
|
||||||
pub fn from_ident(ident: Cow<str>, excluding: &[&str]) -> Result<Self, ()> {
|
pub fn from_ident<'i>(ident: Cow<'i, str>, excluding: &[&str]) -> Result<Self, ParseError<'i>> {
|
||||||
match_ignore_ascii_case! { &ident,
|
let valid = match_ignore_ascii_case! { &ident,
|
||||||
"initial" | "inherit" | "unset" | "default" => return Err(()),
|
"initial" | "inherit" | "unset" | "default" => false,
|
||||||
_ => {}
|
_ => true
|
||||||
};
|
};
|
||||||
|
if !valid {
|
||||||
|
return Err(SelectorParseError::UnexpectedIdent(ident).into());
|
||||||
|
}
|
||||||
if excluding.iter().any(|s| ident.eq_ignore_ascii_case(s)) {
|
if excluding.iter().any(|s| ident.eq_ignore_ascii_case(s)) {
|
||||||
Err(())
|
Err(StyleParseError::UnspecifiedError.into())
|
||||||
} else {
|
} else {
|
||||||
Ok(CustomIdent(ident.into()))
|
Ok(CustomIdent(ident.into()))
|
||||||
}
|
}
|
||||||
|
@ -125,7 +130,7 @@ impl KeyframesName {
|
||||||
pub fn from_ident(value: String) -> Self {
|
pub fn from_ident(value: String) -> Self {
|
||||||
match CustomIdent::from_ident((&*value).into(), &["none"]) {
|
match CustomIdent::from_ident((&*value).into(), &["none"]) {
|
||||||
Ok(ident) => KeyframesName::Ident(ident),
|
Ok(ident) => KeyframesName::Ident(ident),
|
||||||
Err(()) => KeyframesName::QuotedString(value.into()),
|
Err(_) => KeyframesName::QuotedString(value.into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,11 +158,12 @@ impl hash::Hash for KeyframesName {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for KeyframesName {
|
impl Parse for KeyframesName {
|
||||||
fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
match input.next() {
|
match input.next() {
|
||||||
Ok(Token::Ident(s)) => Ok(KeyframesName::Ident(CustomIdent::from_ident(s, &["none"])?)),
|
Ok(Token::Ident(s)) => Ok(KeyframesName::Ident(CustomIdent::from_ident(s, &["none"])?)),
|
||||||
Ok(Token::QuotedString(s)) => Ok(KeyframesName::QuotedString(s.into())),
|
Ok(Token::QuotedString(s)) => Ok(KeyframesName::QuotedString(s.into())),
|
||||||
_ => Err(())
|
Ok(t) => Err(BasicParseError::UnexpectedToken(t).into()),
|
||||||
|
Err(e) => Err(e.into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,9 +9,10 @@
|
||||||
use cssparser::Parser;
|
use cssparser::Parser;
|
||||||
use gecko_bindings::structs;
|
use gecko_bindings::structs;
|
||||||
use parser::{Parse, ParserContext};
|
use parser::{Parse, ParserContext};
|
||||||
|
use selectors::parser::SelectorParseError;
|
||||||
use std::ascii::AsciiExt;
|
use std::ascii::AsciiExt;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use style_traits::ToCss;
|
use style_traits::{ToCss, ParseError, StyleParseError};
|
||||||
|
|
||||||
bitflags! {
|
bitflags! {
|
||||||
/// Constants shared by multiple CSS Box Alignment properties
|
/// Constants shared by multiple CSS Box Alignment properties
|
||||||
|
@ -181,7 +182,7 @@ no_viewport_percentage!(AlignJustifyContent);
|
||||||
impl Parse for AlignJustifyContent {
|
impl Parse for AlignJustifyContent {
|
||||||
// normal | <baseline-position> |
|
// normal | <baseline-position> |
|
||||||
// [ <content-distribution> || [ <overflow-position>? && <content-position> ] ]
|
// [ <content-distribution> || [ <overflow-position>? && <content-position> ] ]
|
||||||
fn parse(_: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
// normal | <baseline-position>
|
// normal | <baseline-position>
|
||||||
if let Ok(value) = input.try(|input| parse_normal_or_baseline(input)) {
|
if let Ok(value) = input.try(|input| parse_normal_or_baseline(input)) {
|
||||||
return Ok(AlignJustifyContent::new(value))
|
return Ok(AlignJustifyContent::new(value))
|
||||||
|
@ -202,7 +203,7 @@ impl Parse for AlignJustifyContent {
|
||||||
}
|
}
|
||||||
return Ok(AlignJustifyContent::new(fallback))
|
return Ok(AlignJustifyContent::new(fallback))
|
||||||
}
|
}
|
||||||
Err(())
|
Err(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -231,7 +232,7 @@ no_viewport_percentage!(AlignJustifySelf);
|
||||||
impl Parse for AlignJustifySelf {
|
impl Parse for AlignJustifySelf {
|
||||||
// auto | normal | stretch | <baseline-position> |
|
// auto | normal | stretch | <baseline-position> |
|
||||||
// [ <overflow-position>? && <self-position> ]
|
// [ <overflow-position>? && <self-position> ]
|
||||||
fn parse(_: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
// auto | normal | stretch | <baseline-position>
|
// auto | normal | stretch | <baseline-position>
|
||||||
if let Ok(value) = input.try(parse_auto_normal_stretch_baseline) {
|
if let Ok(value) = input.try(parse_auto_normal_stretch_baseline) {
|
||||||
return Ok(AlignJustifySelf(value))
|
return Ok(AlignJustifySelf(value))
|
||||||
|
@ -240,7 +241,7 @@ impl Parse for AlignJustifySelf {
|
||||||
if let Ok(value) = input.try(parse_overflow_self_position) {
|
if let Ok(value) = input.try(parse_overflow_self_position) {
|
||||||
return Ok(AlignJustifySelf(value))
|
return Ok(AlignJustifySelf(value))
|
||||||
}
|
}
|
||||||
Err(())
|
Err(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -269,7 +270,7 @@ no_viewport_percentage!(AlignItems);
|
||||||
impl Parse for AlignItems {
|
impl Parse for AlignItems {
|
||||||
// normal | stretch | <baseline-position> |
|
// normal | stretch | <baseline-position> |
|
||||||
// [ <overflow-position>? && <self-position> ]
|
// [ <overflow-position>? && <self-position> ]
|
||||||
fn parse(_: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
// normal | stretch | <baseline-position>
|
// normal | stretch | <baseline-position>
|
||||||
if let Ok(value) = input.try(parse_normal_stretch_baseline) {
|
if let Ok(value) = input.try(parse_normal_stretch_baseline) {
|
||||||
return Ok(AlignItems(value))
|
return Ok(AlignItems(value))
|
||||||
|
@ -278,7 +279,7 @@ impl Parse for AlignItems {
|
||||||
if let Ok(value) = input.try(parse_overflow_self_position) {
|
if let Ok(value) = input.try(parse_overflow_self_position) {
|
||||||
return Ok(AlignItems(value))
|
return Ok(AlignItems(value))
|
||||||
}
|
}
|
||||||
Err(())
|
Err(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -308,7 +309,7 @@ impl Parse for JustifyItems {
|
||||||
// auto | normal | stretch | <baseline-position> |
|
// auto | normal | stretch | <baseline-position> |
|
||||||
// [ <overflow-position>? && <self-position> ]
|
// [ <overflow-position>? && <self-position> ]
|
||||||
// [ legacy && [ left | right | center ] ]
|
// [ legacy && [ left | right | center ] ]
|
||||||
fn parse(_: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
// auto | normal | stretch | <baseline-position>
|
// auto | normal | stretch | <baseline-position>
|
||||||
if let Ok(value) = input.try(parse_auto_normal_stretch_baseline) {
|
if let Ok(value) = input.try(parse_auto_normal_stretch_baseline) {
|
||||||
return Ok(JustifyItems(value))
|
return Ok(JustifyItems(value))
|
||||||
|
@ -321,77 +322,78 @@ impl Parse for JustifyItems {
|
||||||
if let Ok(value) = parse_overflow_self_position(input) {
|
if let Ok(value) = parse_overflow_self_position(input) {
|
||||||
return Ok(JustifyItems(value))
|
return Ok(JustifyItems(value))
|
||||||
}
|
}
|
||||||
Err(())
|
Err(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// auto | normal | stretch | <baseline-position>
|
// auto | normal | stretch | <baseline-position>
|
||||||
fn parse_auto_normal_stretch_baseline(input: &mut Parser) -> Result<AlignFlags, ()> {
|
fn parse_auto_normal_stretch_baseline<'i, 't>(input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<AlignFlags, ParseError<'i>> {
|
||||||
if let Ok(baseline) = input.try(parse_baseline) {
|
if let Ok(baseline) = input.try(parse_baseline) {
|
||||||
return Ok(baseline);
|
return Ok(baseline);
|
||||||
}
|
}
|
||||||
|
|
||||||
let ident = input.expect_ident()?;
|
let ident = input.expect_ident()?;
|
||||||
match_ignore_ascii_case! { &ident,
|
(match_ignore_ascii_case! { &ident,
|
||||||
"auto" => Ok(ALIGN_AUTO),
|
"auto" => Ok(ALIGN_AUTO),
|
||||||
"normal" => Ok(ALIGN_NORMAL),
|
"normal" => Ok(ALIGN_NORMAL),
|
||||||
"stretch" => Ok(ALIGN_STRETCH),
|
"stretch" => Ok(ALIGN_STRETCH),
|
||||||
_ => Err(())
|
_ => Err(())
|
||||||
}
|
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
// normal | stretch | <baseline-position>
|
// normal | stretch | <baseline-position>
|
||||||
fn parse_normal_stretch_baseline(input: &mut Parser) -> Result<AlignFlags, ()> {
|
fn parse_normal_stretch_baseline<'i, 't>(input: &mut Parser<'i, 't>) -> Result<AlignFlags, ParseError<'i>> {
|
||||||
if let Ok(baseline) = input.try(parse_baseline) {
|
if let Ok(baseline) = input.try(parse_baseline) {
|
||||||
return Ok(baseline);
|
return Ok(baseline);
|
||||||
}
|
}
|
||||||
|
|
||||||
let ident = input.expect_ident()?;
|
let ident = input.expect_ident()?;
|
||||||
match_ignore_ascii_case! { &ident,
|
(match_ignore_ascii_case! { &ident,
|
||||||
"normal" => Ok(ALIGN_NORMAL),
|
"normal" => Ok(ALIGN_NORMAL),
|
||||||
"stretch" => Ok(ALIGN_STRETCH),
|
"stretch" => Ok(ALIGN_STRETCH),
|
||||||
_ => Err(())
|
_ => Err(())
|
||||||
}
|
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
// normal | <baseline-position>
|
// normal | <baseline-position>
|
||||||
fn parse_normal_or_baseline(input: &mut Parser) -> Result<AlignFlags, ()> {
|
fn parse_normal_or_baseline<'i, 't>(input: &mut Parser<'i, 't>) -> Result<AlignFlags, ParseError<'i>> {
|
||||||
if let Ok(baseline) = input.try(parse_baseline) {
|
if let Ok(baseline) = input.try(parse_baseline) {
|
||||||
return Ok(baseline);
|
return Ok(baseline);
|
||||||
}
|
}
|
||||||
|
|
||||||
let ident = input.expect_ident()?;
|
let ident = input.expect_ident()?;
|
||||||
match_ignore_ascii_case! { &ident,
|
(match_ignore_ascii_case! { &ident,
|
||||||
"normal" => Ok(ALIGN_NORMAL),
|
"normal" => Ok(ALIGN_NORMAL),
|
||||||
_ => Err(())
|
_ => Err(())
|
||||||
}
|
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
// <baseline-position>
|
// <baseline-position>
|
||||||
fn parse_baseline(input: &mut Parser) -> Result<AlignFlags, ()> {
|
fn parse_baseline<'i, 't>(input: &mut Parser<'i, 't>) -> Result<AlignFlags, ParseError<'i>> {
|
||||||
let ident = input.expect_ident()?;
|
let ident = input.expect_ident()?;
|
||||||
match_ignore_ascii_case! { &ident,
|
(match_ignore_ascii_case! { &ident,
|
||||||
"baseline" => Ok(ALIGN_BASELINE),
|
"baseline" => Ok(ALIGN_BASELINE),
|
||||||
"first" => input.expect_ident_matching("baseline").map(|_| ALIGN_BASELINE),
|
"first" => return input.expect_ident_matching("baseline").map(|_| ALIGN_BASELINE).map_err(|e| e.into()),
|
||||||
"last" => input.expect_ident_matching("baseline").map(|_| ALIGN_LAST_BASELINE),
|
"last" => return input.expect_ident_matching("baseline").map(|_| ALIGN_LAST_BASELINE).map_err(|e| e.into()),
|
||||||
_ => Err(())
|
_ => Err(())
|
||||||
}
|
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
// <content-distribution>
|
// <content-distribution>
|
||||||
fn parse_content_distribution(input: &mut Parser) -> Result<AlignFlags, ()> {
|
fn parse_content_distribution<'i, 't>(input: &mut Parser<'i, 't>) -> Result<AlignFlags, ParseError<'i>> {
|
||||||
let ident = input.expect_ident()?;
|
let ident = input.expect_ident()?;
|
||||||
match_ignore_ascii_case! { &ident,
|
(match_ignore_ascii_case! { &ident,
|
||||||
"stretch" => Ok(ALIGN_STRETCH),
|
"stretch" => Ok(ALIGN_STRETCH),
|
||||||
"space-between" => Ok(ALIGN_SPACE_BETWEEN),
|
"space-between" => Ok(ALIGN_SPACE_BETWEEN),
|
||||||
"space-around" => Ok(ALIGN_SPACE_AROUND),
|
"space-around" => Ok(ALIGN_SPACE_AROUND),
|
||||||
"space-evenly" => Ok(ALIGN_SPACE_EVENLY),
|
"space-evenly" => Ok(ALIGN_SPACE_EVENLY),
|
||||||
_ => Err(())
|
_ => Err(())
|
||||||
}
|
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
// [ <overflow-position>? && <content-position> ]
|
// [ <overflow-position>? && <content-position> ]
|
||||||
fn parse_overflow_content_position(input: &mut Parser) -> Result<AlignFlags, ()> {
|
fn parse_overflow_content_position<'i, 't>(input: &mut Parser<'i, 't>) -> Result<AlignFlags, ParseError<'i>> {
|
||||||
// <content-position> followed by optional <overflow-position>
|
// <content-position> followed by optional <overflow-position>
|
||||||
if let Ok(mut content) = input.try(parse_content_position) {
|
if let Ok(mut content) = input.try(parse_content_position) {
|
||||||
if let Ok(overflow) = input.try(parse_overflow_position) {
|
if let Ok(overflow) = input.try(parse_overflow_position) {
|
||||||
|
@ -405,13 +407,13 @@ fn parse_overflow_content_position(input: &mut Parser) -> Result<AlignFlags, ()>
|
||||||
return Ok(overflow | content)
|
return Ok(overflow | content)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Err(())
|
return Err(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
// <content-position>
|
// <content-position>
|
||||||
fn parse_content_position(input: &mut Parser) -> Result<AlignFlags, ()> {
|
fn parse_content_position<'i, 't>(input: &mut Parser<'i, 't>) -> Result<AlignFlags, ParseError<'i>> {
|
||||||
let ident = input.expect_ident()?;
|
let ident = input.expect_ident()?;
|
||||||
match_ignore_ascii_case! { &ident,
|
(match_ignore_ascii_case! { &ident,
|
||||||
"start" => Ok(ALIGN_START),
|
"start" => Ok(ALIGN_START),
|
||||||
"end" => Ok(ALIGN_END),
|
"end" => Ok(ALIGN_END),
|
||||||
"flex-start" => Ok(ALIGN_FLEX_START),
|
"flex-start" => Ok(ALIGN_FLEX_START),
|
||||||
|
@ -420,21 +422,21 @@ fn parse_content_position(input: &mut Parser) -> Result<AlignFlags, ()> {
|
||||||
"left" => Ok(ALIGN_LEFT),
|
"left" => Ok(ALIGN_LEFT),
|
||||||
"right" => Ok(ALIGN_RIGHT),
|
"right" => Ok(ALIGN_RIGHT),
|
||||||
_ => Err(())
|
_ => Err(())
|
||||||
}
|
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
// <overflow-position>
|
// <overflow-position>
|
||||||
fn parse_overflow_position(input: &mut Parser) -> Result<AlignFlags, ()> {
|
fn parse_overflow_position<'i, 't>(input: &mut Parser<'i, 't>) -> Result<AlignFlags, ParseError<'i>> {
|
||||||
let ident = input.expect_ident()?;
|
let ident = input.expect_ident()?;
|
||||||
match_ignore_ascii_case! { &ident,
|
(match_ignore_ascii_case! { &ident,
|
||||||
"safe" => Ok(ALIGN_SAFE),
|
"safe" => Ok(ALIGN_SAFE),
|
||||||
"unsafe" => Ok(ALIGN_UNSAFE),
|
"unsafe" => Ok(ALIGN_UNSAFE),
|
||||||
_ => Err(())
|
_ => Err(())
|
||||||
}
|
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
// [ <overflow-position>? && <self-position> ]
|
// [ <overflow-position>? && <self-position> ]
|
||||||
fn parse_overflow_self_position(input: &mut Parser) -> Result<AlignFlags, ()> {
|
fn parse_overflow_self_position<'i, 't>(input: &mut Parser<'i, 't>) -> Result<AlignFlags, ParseError<'i>> {
|
||||||
// <self-position> followed by optional <overflow-position>
|
// <self-position> followed by optional <overflow-position>
|
||||||
if let Ok(mut self_position) = input.try(parse_self_position) {
|
if let Ok(mut self_position) = input.try(parse_self_position) {
|
||||||
if let Ok(overflow) = input.try(parse_overflow_position) {
|
if let Ok(overflow) = input.try(parse_overflow_position) {
|
||||||
|
@ -448,13 +450,13 @@ fn parse_overflow_self_position(input: &mut Parser) -> Result<AlignFlags, ()> {
|
||||||
return Ok(overflow | self_position)
|
return Ok(overflow | self_position)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Err(())
|
return Err(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
// <self-position>
|
// <self-position>
|
||||||
fn parse_self_position(input: &mut Parser) -> Result<AlignFlags, ()> {
|
fn parse_self_position<'i, 't>(input: &mut Parser<'i, 't>) -> Result<AlignFlags, ParseError<'i>> {
|
||||||
let ident = input.expect_ident()?;
|
let ident = input.expect_ident()?;
|
||||||
match_ignore_ascii_case! { &ident,
|
(match_ignore_ascii_case! { &ident,
|
||||||
"start" => Ok(ALIGN_START),
|
"start" => Ok(ALIGN_START),
|
||||||
"end" => Ok(ALIGN_END),
|
"end" => Ok(ALIGN_END),
|
||||||
"flex-start" => Ok(ALIGN_FLEX_START),
|
"flex-start" => Ok(ALIGN_FLEX_START),
|
||||||
|
@ -465,28 +467,28 @@ fn parse_self_position(input: &mut Parser) -> Result<AlignFlags, ()> {
|
||||||
"self-start" => Ok(ALIGN_SELF_START),
|
"self-start" => Ok(ALIGN_SELF_START),
|
||||||
"self-end" => Ok(ALIGN_SELF_END),
|
"self-end" => Ok(ALIGN_SELF_END),
|
||||||
_ => Err(())
|
_ => Err(())
|
||||||
}
|
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
// [ legacy && [ left | right | center ] ]
|
// [ legacy && [ left | right | center ] ]
|
||||||
fn parse_legacy(input: &mut Parser) -> Result<AlignFlags, ()> {
|
fn parse_legacy<'i, 't>(input: &mut Parser<'i, 't>) -> Result<AlignFlags, ParseError<'i>> {
|
||||||
let a = input.expect_ident()?;
|
let a = input.expect_ident()?;
|
||||||
let b = input.expect_ident()?;
|
let b = input.expect_ident()?;
|
||||||
if a.eq_ignore_ascii_case("legacy") {
|
if a.eq_ignore_ascii_case("legacy") {
|
||||||
match_ignore_ascii_case! { &b,
|
(match_ignore_ascii_case! { &b,
|
||||||
"left" => Ok(ALIGN_LEGACY | ALIGN_LEFT),
|
"left" => Ok(ALIGN_LEGACY | ALIGN_LEFT),
|
||||||
"right" => Ok(ALIGN_LEGACY | ALIGN_RIGHT),
|
"right" => Ok(ALIGN_LEGACY | ALIGN_RIGHT),
|
||||||
"center" => Ok(ALIGN_LEGACY | ALIGN_CENTER),
|
"center" => Ok(ALIGN_LEGACY | ALIGN_CENTER),
|
||||||
_ => Err(())
|
_ => Err(())
|
||||||
}
|
}).map_err(|()| SelectorParseError::UnexpectedIdent(b).into())
|
||||||
} else if b.eq_ignore_ascii_case("legacy") {
|
} else if b.eq_ignore_ascii_case("legacy") {
|
||||||
match_ignore_ascii_case! { &a,
|
(match_ignore_ascii_case! { &a,
|
||||||
"left" => Ok(ALIGN_LEGACY | ALIGN_LEFT),
|
"left" => Ok(ALIGN_LEGACY | ALIGN_LEFT),
|
||||||
"right" => Ok(ALIGN_LEGACY | ALIGN_RIGHT),
|
"right" => Ok(ALIGN_LEGACY | ALIGN_RIGHT),
|
||||||
"center" => Ok(ALIGN_LEGACY | ALIGN_CENTER),
|
"center" => Ok(ALIGN_LEGACY | ALIGN_CENTER),
|
||||||
_ => Err(())
|
_ => Err(())
|
||||||
}
|
}).map_err(|()| SelectorParseError::UnexpectedIdent(a).into())
|
||||||
} else {
|
} else {
|
||||||
Err(())
|
Err(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
|
|
||||||
use cssparser::Parser;
|
use cssparser::Parser;
|
||||||
use parser::{Parse, ParserContext};
|
use parser::{Parse, ParserContext};
|
||||||
|
use selectors::parser::SelectorParseError;
|
||||||
|
use style_traits::ParseError;
|
||||||
use values::generics::background::BackgroundSize as GenericBackgroundSize;
|
use values::generics::background::BackgroundSize as GenericBackgroundSize;
|
||||||
use values::specified::length::LengthOrPercentageOrAuto;
|
use values::specified::length::LengthOrPercentageOrAuto;
|
||||||
|
|
||||||
|
@ -13,17 +15,18 @@ use values::specified::length::LengthOrPercentageOrAuto;
|
||||||
pub type BackgroundSize = GenericBackgroundSize<LengthOrPercentageOrAuto>;
|
pub type BackgroundSize = GenericBackgroundSize<LengthOrPercentageOrAuto>;
|
||||||
|
|
||||||
impl Parse for BackgroundSize {
|
impl Parse for BackgroundSize {
|
||||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
if let Ok(width) = input.try(|i| LengthOrPercentageOrAuto::parse_non_negative(context, i)) {
|
if let Ok(width) = input.try(|i| LengthOrPercentageOrAuto::parse_non_negative(context, i)) {
|
||||||
let height = input
|
let height = input
|
||||||
.try(|i| LengthOrPercentageOrAuto::parse_non_negative(context, i))
|
.try(|i| LengthOrPercentageOrAuto::parse_non_negative(context, i))
|
||||||
.unwrap_or(LengthOrPercentageOrAuto::Auto);
|
.unwrap_or(LengthOrPercentageOrAuto::Auto);
|
||||||
return Ok(GenericBackgroundSize::Explicit { width: width, height: height });
|
return Ok(GenericBackgroundSize::Explicit { width: width, height: height });
|
||||||
}
|
}
|
||||||
match_ignore_ascii_case! { &input.expect_ident()?,
|
let ident = input.expect_ident()?;
|
||||||
|
(match_ignore_ascii_case! { &ident,
|
||||||
"cover" => Ok(GenericBackgroundSize::Cover),
|
"cover" => Ok(GenericBackgroundSize::Cover),
|
||||||
"contain" => Ok(GenericBackgroundSize::Contain),
|
"contain" => Ok(GenericBackgroundSize::Contain),
|
||||||
_ => Err(()),
|
_ => Err(()),
|
||||||
}
|
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,9 +9,10 @@
|
||||||
|
|
||||||
use cssparser::Parser;
|
use cssparser::Parser;
|
||||||
use parser::{Parse, ParserContext};
|
use parser::{Parse, ParserContext};
|
||||||
|
use selectors::parser::SelectorParseError;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use style_traits::ToCss;
|
use style_traits::{ToCss, ParseError, StyleParseError};
|
||||||
use values::generics::basic_shape::{Circle as GenericCircle};
|
use values::generics::basic_shape::{Circle as GenericCircle};
|
||||||
use values::generics::basic_shape::{ClippingShape as GenericClippingShape, Ellipse as GenericEllipse};
|
use values::generics::basic_shape::{ClippingShape as GenericClippingShape, Ellipse as GenericEllipse};
|
||||||
use values::generics::basic_shape::{FillRule, BasicShape as GenericBasicShape};
|
use values::generics::basic_shape::{FillRule, BasicShape as GenericBasicShape};
|
||||||
|
@ -49,7 +50,7 @@ pub type ShapeRadius = GenericShapeRadius<LengthOrPercentage>;
|
||||||
pub type Polygon = GenericPolygon<LengthOrPercentage>;
|
pub type Polygon = GenericPolygon<LengthOrPercentage>;
|
||||||
|
|
||||||
impl<ReferenceBox: Parse> Parse for ShapeSource<BasicShape, ReferenceBox> {
|
impl<ReferenceBox: Parse> Parse for ShapeSource<BasicShape, ReferenceBox> {
|
||||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
if input.try(|i| i.expect_ident_matching("none")).is_ok() {
|
if input.try(|i| i.expect_ident_matching("none")).is_ok() {
|
||||||
return Ok(ShapeSource::None)
|
return Ok(ShapeSource::None)
|
||||||
}
|
}
|
||||||
|
@ -80,42 +81,43 @@ impl<ReferenceBox: Parse> Parse for ShapeSource<BasicShape, ReferenceBox> {
|
||||||
return Ok(ShapeSource::Shape(shp, ref_box))
|
return Ok(ShapeSource::Shape(shp, ref_box))
|
||||||
}
|
}
|
||||||
|
|
||||||
ref_box.map(|v| ShapeSource::Box(v)).ok_or(())
|
ref_box.map(|v| ShapeSource::Box(v)).ok_or(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for GeometryBox {
|
impl Parse for GeometryBox {
|
||||||
fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
if let Ok(shape_box) = input.try(|i| ShapeBox::parse(i)) {
|
if let Ok(shape_box) = input.try(|i| ShapeBox::parse(i)) {
|
||||||
return Ok(GeometryBox::ShapeBox(shape_box))
|
return Ok(GeometryBox::ShapeBox(shape_box))
|
||||||
}
|
}
|
||||||
|
|
||||||
match_ignore_ascii_case! { &input.expect_ident()?,
|
let ident = input.expect_ident()?;
|
||||||
|
(match_ignore_ascii_case! { &ident,
|
||||||
"fill-box" => Ok(GeometryBox::FillBox),
|
"fill-box" => Ok(GeometryBox::FillBox),
|
||||||
"stroke-box" => Ok(GeometryBox::StrokeBox),
|
"stroke-box" => Ok(GeometryBox::StrokeBox),
|
||||||
"view-box" => Ok(GeometryBox::ViewBox),
|
"view-box" => Ok(GeometryBox::ViewBox),
|
||||||
_ => Err(())
|
_ => Err(())
|
||||||
}
|
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for BasicShape {
|
impl Parse for BasicShape {
|
||||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
let function = input.expect_function()?;
|
let function = input.expect_function()?;
|
||||||
input.parse_nested_block(|i| {
|
input.parse_nested_block(move |i| {
|
||||||
match_ignore_ascii_case! { &function,
|
(match_ignore_ascii_case! { &function,
|
||||||
"inset" => InsetRect::parse_function_arguments(context, i).map(GenericBasicShape::Inset),
|
"inset" => return InsetRect::parse_function_arguments(context, i).map(GenericBasicShape::Inset),
|
||||||
"circle" => Circle::parse_function_arguments(context, i).map(GenericBasicShape::Circle),
|
"circle" => return Circle::parse_function_arguments(context, i).map(GenericBasicShape::Circle),
|
||||||
"ellipse" => Ellipse::parse_function_arguments(context, i).map(GenericBasicShape::Ellipse),
|
"ellipse" => return Ellipse::parse_function_arguments(context, i).map(GenericBasicShape::Ellipse),
|
||||||
"polygon" => Polygon::parse_function_arguments(context, i).map(GenericBasicShape::Polygon),
|
"polygon" => return Polygon::parse_function_arguments(context, i).map(GenericBasicShape::Polygon),
|
||||||
_ => Err(())
|
_ => Err(())
|
||||||
}
|
}).map_err(|()| StyleParseError::UnexpectedFunction(function).into())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for InsetRect {
|
impl Parse for InsetRect {
|
||||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
input.expect_function_matching("inset")?;
|
input.expect_function_matching("inset")?;
|
||||||
input.parse_nested_block(|i| Self::parse_function_arguments(context, i))
|
input.parse_nested_block(|i| Self::parse_function_arguments(context, i))
|
||||||
}
|
}
|
||||||
|
@ -123,7 +125,8 @@ impl Parse for InsetRect {
|
||||||
|
|
||||||
impl InsetRect {
|
impl InsetRect {
|
||||||
/// Parse the inner function arguments of `inset()`
|
/// Parse the inner function arguments of `inset()`
|
||||||
pub fn parse_function_arguments(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
pub fn parse_function_arguments<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<Self, ParseError<'i>> {
|
||||||
let rect = Rect::parse_with(context, input, LengthOrPercentage::parse)?;
|
let rect = Rect::parse_with(context, input, LengthOrPercentage::parse)?;
|
||||||
let round = if input.try(|i| i.expect_ident_matching("round")).is_ok() {
|
let round = if input.try(|i| i.expect_ident_matching("round")).is_ok() {
|
||||||
Some(BorderRadius::parse(context, input)?)
|
Some(BorderRadius::parse(context, input)?)
|
||||||
|
@ -138,7 +141,8 @@ impl InsetRect {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for Circle {
|
impl Parse for Circle {
|
||||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<Self, ParseError<'i>> {
|
||||||
input.expect_function_matching("circle")?;
|
input.expect_function_matching("circle")?;
|
||||||
input.parse_nested_block(|i| Self::parse_function_arguments(context, i))
|
input.parse_nested_block(|i| Self::parse_function_arguments(context, i))
|
||||||
}
|
}
|
||||||
|
@ -146,7 +150,8 @@ impl Parse for Circle {
|
||||||
|
|
||||||
impl Circle {
|
impl Circle {
|
||||||
#[allow(missing_docs)]
|
#[allow(missing_docs)]
|
||||||
pub fn parse_function_arguments(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
pub fn parse_function_arguments<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<Self, ParseError<'i>> {
|
||||||
let radius = input.try(|i| ShapeRadius::parse(context, i)).ok().unwrap_or_default();
|
let radius = input.try(|i| ShapeRadius::parse(context, i)).ok().unwrap_or_default();
|
||||||
let position = if input.try(|i| i.expect_ident_matching("at")).is_ok() {
|
let position = if input.try(|i| i.expect_ident_matching("at")).is_ok() {
|
||||||
Position::parse(context, input)?
|
Position::parse(context, input)?
|
||||||
|
@ -176,7 +181,7 @@ impl ToCss for Circle {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for Ellipse {
|
impl Parse for Ellipse {
|
||||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
input.expect_function_matching("ellipse")?;
|
input.expect_function_matching("ellipse")?;
|
||||||
input.parse_nested_block(|i| Self::parse_function_arguments(context, i))
|
input.parse_nested_block(|i| Self::parse_function_arguments(context, i))
|
||||||
}
|
}
|
||||||
|
@ -184,8 +189,9 @@ impl Parse for Ellipse {
|
||||||
|
|
||||||
impl Ellipse {
|
impl Ellipse {
|
||||||
#[allow(missing_docs)]
|
#[allow(missing_docs)]
|
||||||
pub fn parse_function_arguments(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
pub fn parse_function_arguments<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
let (a, b) = input.try(|i| -> Result<_, ()> {
|
-> Result<Self, ParseError<'i>> {
|
||||||
|
let (a, b) = input.try(|i| -> Result<_, ParseError> {
|
||||||
Ok((ShapeRadius::parse(context, i)?, ShapeRadius::parse(context, i)?))
|
Ok((ShapeRadius::parse(context, i)?, ShapeRadius::parse(context, i)?))
|
||||||
}).ok().unwrap_or_default();
|
}).ok().unwrap_or_default();
|
||||||
let position = if input.try(|i| i.expect_ident_matching("at")).is_ok() {
|
let position = if input.try(|i| i.expect_ident_matching("at")).is_ok() {
|
||||||
|
@ -219,16 +225,18 @@ impl ToCss for Ellipse {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for ShapeRadius {
|
impl Parse for ShapeRadius {
|
||||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<Self, ParseError<'i>> {
|
||||||
if let Ok(lop) = input.try(|i| LengthOrPercentage::parse_non_negative(context, i)) {
|
if let Ok(lop) = input.try(|i| LengthOrPercentage::parse_non_negative(context, i)) {
|
||||||
return Ok(GenericShapeRadius::Length(lop))
|
return Ok(GenericShapeRadius::Length(lop))
|
||||||
}
|
}
|
||||||
|
|
||||||
match_ignore_ascii_case! { &input.expect_ident()?,
|
let ident = input.expect_ident()?;
|
||||||
|
(match_ignore_ascii_case! { &ident,
|
||||||
"closest-side" => Ok(GenericShapeRadius::ClosestSide),
|
"closest-side" => Ok(GenericShapeRadius::ClosestSide),
|
||||||
"farthest-side" => Ok(GenericShapeRadius::FarthestSide),
|
"farthest-side" => Ok(GenericShapeRadius::FarthestSide),
|
||||||
_ => Err(())
|
_ => Err(())
|
||||||
}
|
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -300,7 +308,7 @@ fn serialize_basicshape_position<W>(position: &Position, dest: &mut W) -> fmt::R
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for Polygon {
|
impl Parse for Polygon {
|
||||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
input.expect_function_matching("polygon")?;
|
input.expect_function_matching("polygon")?;
|
||||||
input.parse_nested_block(|i| Self::parse_function_arguments(context, i))
|
input.parse_nested_block(|i| Self::parse_function_arguments(context, i))
|
||||||
}
|
}
|
||||||
|
@ -308,8 +316,9 @@ impl Parse for Polygon {
|
||||||
|
|
||||||
impl Polygon {
|
impl Polygon {
|
||||||
/// Parse the inner arguments of a `polygon` function.
|
/// Parse the inner arguments of a `polygon` function.
|
||||||
pub fn parse_function_arguments(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
pub fn parse_function_arguments<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
let fill = input.try(|i| -> Result<_, ()> {
|
-> Result<Self, ParseError<'i>> {
|
||||||
|
let fill = input.try(|i| -> Result<_, ParseError> {
|
||||||
let fill = FillRule::parse(i)?;
|
let fill = FillRule::parse(i)?;
|
||||||
i.expect_comma()?; // only eat the comma if there is something before it
|
i.expect_comma()?; // only eat the comma if there is something before it
|
||||||
Ok(fill)
|
Ok(fill)
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
use cssparser::Parser;
|
use cssparser::Parser;
|
||||||
use parser::{Parse, ParserContext};
|
use parser::{Parse, ParserContext};
|
||||||
|
use selectors::parser::SelectorParseError;
|
||||||
|
use style_traits::ParseError;
|
||||||
use values::computed::{Context, ToComputedValue};
|
use values::computed::{Context, ToComputedValue};
|
||||||
use values::generics::border::BorderCornerRadius as GenericBorderCornerRadius;
|
use values::generics::border::BorderCornerRadius as GenericBorderCornerRadius;
|
||||||
use values::generics::border::BorderImageSideWidth as GenericBorderImageSideWidth;
|
use values::generics::border::BorderImageSideWidth as GenericBorderImageSideWidth;
|
||||||
|
@ -47,26 +49,27 @@ pub type BorderCornerRadius = GenericBorderCornerRadius<LengthOrPercentage>;
|
||||||
|
|
||||||
impl BorderSideWidth {
|
impl BorderSideWidth {
|
||||||
/// Parses, with quirks.
|
/// Parses, with quirks.
|
||||||
pub fn parse_quirky(
|
pub fn parse_quirky<'i, 't>(
|
||||||
context: &ParserContext,
|
context: &ParserContext,
|
||||||
input: &mut Parser,
|
input: &mut Parser<'i, 't>,
|
||||||
allow_quirks: AllowQuirks)
|
allow_quirks: AllowQuirks)
|
||||||
-> Result<Self, ()>
|
-> Result<Self, ParseError<'i>>
|
||||||
{
|
{
|
||||||
if let Ok(length) = input.try(|i| Length::parse_non_negative_quirky(context, i, allow_quirks)) {
|
if let Ok(length) = input.try(|i| Length::parse_non_negative_quirky(context, i, allow_quirks)) {
|
||||||
return Ok(BorderSideWidth::Length(length));
|
return Ok(BorderSideWidth::Length(length));
|
||||||
}
|
}
|
||||||
match_ignore_ascii_case! { &input.expect_ident()?,
|
let ident = input.expect_ident()?;
|
||||||
|
(match_ignore_ascii_case! { &ident,
|
||||||
"thin" => Ok(BorderSideWidth::Thin),
|
"thin" => Ok(BorderSideWidth::Thin),
|
||||||
"medium" => Ok(BorderSideWidth::Medium),
|
"medium" => Ok(BorderSideWidth::Medium),
|
||||||
"thick" => Ok(BorderSideWidth::Thick),
|
"thick" => Ok(BorderSideWidth::Thick),
|
||||||
_ => Err(())
|
_ => Err(())
|
||||||
}
|
}).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for BorderSideWidth {
|
impl Parse for BorderSideWidth {
|
||||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
Self::parse_quirky(context, input, AllowQuirks::No)
|
Self::parse_quirky(context, input, AllowQuirks::No)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -102,7 +105,7 @@ impl BorderImageSideWidth {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for BorderImageSideWidth {
|
impl Parse for BorderImageSideWidth {
|
||||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
if input.try(|i| i.expect_ident_matching("auto")).is_ok() {
|
if input.try(|i| i.expect_ident_matching("auto")).is_ok() {
|
||||||
return Ok(GenericBorderImageSideWidth::Auto);
|
return Ok(GenericBorderImageSideWidth::Auto);
|
||||||
}
|
}
|
||||||
|
@ -117,7 +120,7 @@ impl Parse for BorderImageSideWidth {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for BorderImageSlice {
|
impl Parse for BorderImageSlice {
|
||||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
let mut fill = input.try(|i| i.expect_ident_matching("fill")).is_ok();
|
let mut fill = input.try(|i| i.expect_ident_matching("fill")).is_ok();
|
||||||
let offsets = Rect::parse_with(context, input, NumberOrPercentage::parse_non_negative)?;
|
let offsets = Rect::parse_with(context, input, NumberOrPercentage::parse_non_negative)?;
|
||||||
if !fill {
|
if !fill {
|
||||||
|
@ -131,7 +134,7 @@ impl Parse for BorderImageSlice {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for BorderRadius {
|
impl Parse for BorderRadius {
|
||||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
let widths = Rect::parse_with(context, input, LengthOrPercentage::parse_non_negative)?;
|
let widths = Rect::parse_with(context, input, LengthOrPercentage::parse_non_negative)?;
|
||||||
let heights = if input.try(|i| i.expect_delim('/')).is_ok() {
|
let heights = if input.try(|i| i.expect_delim('/')).is_ok() {
|
||||||
Rect::parse_with(context, input, LengthOrPercentage::parse_non_negative)?
|
Rect::parse_with(context, input, LengthOrPercentage::parse_non_negative)?
|
||||||
|
@ -149,11 +152,11 @@ impl Parse for BorderRadius {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for BorderCornerRadius {
|
impl Parse for BorderCornerRadius {
|
||||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
let first = LengthOrPercentage::parse_non_negative(context, input)?;
|
let first = LengthOrPercentage::parse_non_negative(context, input)?;
|
||||||
let second = input
|
let second = input
|
||||||
.try(|i| LengthOrPercentage::parse_non_negative(context, i))
|
.try(|i| LengthOrPercentage::parse_non_negative(context, i))
|
||||||
.unwrap_or_else(|()| first.clone());
|
.unwrap_or_else(|_| first.clone());
|
||||||
Ok(Self::new(first, second))
|
Ok(Self::new(first, second))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,11 +7,11 @@
|
||||||
//! [calc]: https://drafts.csswg.org/css-values/#calc-notation
|
//! [calc]: https://drafts.csswg.org/css-values/#calc-notation
|
||||||
|
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
use cssparser::{Parser, Token};
|
use cssparser::{Parser, Token, BasicParseError};
|
||||||
use parser::ParserContext;
|
use parser::ParserContext;
|
||||||
use std::ascii::AsciiExt;
|
use std::ascii::AsciiExt;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use style_traits::{HasViewportPercentage, ToCss};
|
use style_traits::{HasViewportPercentage, ToCss, ParseError, StyleParseError};
|
||||||
use style_traits::values::specified::AllowedLengthType;
|
use style_traits::values::specified::AllowedLengthType;
|
||||||
use values::{CSSInteger, CSSFloat};
|
use values::{CSSInteger, CSSFloat};
|
||||||
use values::specified::{Angle, Time};
|
use values::specified::{Angle, Time};
|
||||||
|
@ -142,11 +142,11 @@ impl CalcNode {
|
||||||
///
|
///
|
||||||
/// May return a "complex" `CalcNode`, in the presence of a parenthesized
|
/// May return a "complex" `CalcNode`, in the presence of a parenthesized
|
||||||
/// expression, for example.
|
/// expression, for example.
|
||||||
fn parse_one(
|
fn parse_one<'i, 't>(
|
||||||
context: &ParserContext,
|
context: &ParserContext,
|
||||||
input: &mut Parser,
|
input: &mut Parser<'i, 't>,
|
||||||
expected_unit: CalcUnit)
|
expected_unit: CalcUnit)
|
||||||
-> Result<Self, ()>
|
-> Result<Self, ParseError<'i>>
|
||||||
{
|
{
|
||||||
match (try!(input.next()), expected_unit) {
|
match (try!(input.next()), expected_unit) {
|
||||||
(Token::Number(ref value), _) => Ok(CalcNode::Number(value.value)),
|
(Token::Number(ref value), _) => Ok(CalcNode::Number(value.value)),
|
||||||
|
@ -154,18 +154,21 @@ impl CalcNode {
|
||||||
(Token::Dimension(ref value, ref unit), CalcUnit::LengthOrPercentage) => {
|
(Token::Dimension(ref value, ref unit), CalcUnit::LengthOrPercentage) => {
|
||||||
NoCalcLength::parse_dimension(context, value.value, unit)
|
NoCalcLength::parse_dimension(context, value.value, unit)
|
||||||
.map(CalcNode::Length)
|
.map(CalcNode::Length)
|
||||||
|
.map_err(|()| StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
(Token::Dimension(ref value, ref unit), CalcUnit::Angle) => {
|
(Token::Dimension(ref value, ref unit), CalcUnit::Angle) => {
|
||||||
Angle::parse_dimension(value.value,
|
Angle::parse_dimension(value.value,
|
||||||
unit,
|
unit,
|
||||||
/* from_calc = */ true)
|
/* from_calc = */ true)
|
||||||
.map(CalcNode::Angle)
|
.map(CalcNode::Angle)
|
||||||
|
.map_err(|()| StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
(Token::Dimension(ref value, ref unit), CalcUnit::Time) => {
|
(Token::Dimension(ref value, ref unit), CalcUnit::Time) => {
|
||||||
Time::parse_dimension(value.value,
|
Time::parse_dimension(value.value,
|
||||||
unit,
|
unit,
|
||||||
/* from_calc = */ true)
|
/* from_calc = */ true)
|
||||||
.map(CalcNode::Time)
|
.map(CalcNode::Time)
|
||||||
|
.map_err(|()| StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
(Token::Percentage(ref value), CalcUnit::LengthOrPercentage) => {
|
(Token::Percentage(ref value), CalcUnit::LengthOrPercentage) => {
|
||||||
Ok(CalcNode::Percentage(value.unit_value))
|
Ok(CalcNode::Percentage(value.unit_value))
|
||||||
|
@ -180,18 +183,18 @@ impl CalcNode {
|
||||||
CalcNode::parse(context, i, expected_unit)
|
CalcNode::parse(context, i, expected_unit)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
_ => Err(())
|
(t, _) => Err(BasicParseError::UnexpectedToken(t).into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a top-level `calc` expression, with all nested sub-expressions.
|
/// Parse a top-level `calc` expression, with all nested sub-expressions.
|
||||||
///
|
///
|
||||||
/// This is in charge of parsing, for example, `2 + 3 * 100%`.
|
/// This is in charge of parsing, for example, `2 + 3 * 100%`.
|
||||||
fn parse(
|
fn parse<'i, 't>(
|
||||||
context: &ParserContext,
|
context: &ParserContext,
|
||||||
input: &mut Parser,
|
input: &mut Parser<'i, 't>,
|
||||||
expected_unit: CalcUnit)
|
expected_unit: CalcUnit)
|
||||||
-> Result<Self, ()>
|
-> Result<Self, ParseError<'i>>
|
||||||
{
|
{
|
||||||
let mut root = Self::parse_product(context, input, expected_unit)?;
|
let mut root = Self::parse_product(context, input, expected_unit)?;
|
||||||
|
|
||||||
|
@ -217,7 +220,7 @@ impl CalcNode {
|
||||||
CalcNode::Sub(Box::new(root), Box::new(rhs));
|
CalcNode::Sub(Box::new(root), Box::new(rhs));
|
||||||
root = new_root;
|
root = new_root;
|
||||||
}
|
}
|
||||||
_ => return Err(()),
|
t => return Err(BasicParseError::UnexpectedToken(t).into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
|
@ -239,11 +242,11 @@ impl CalcNode {
|
||||||
/// * `2 * 2`
|
/// * `2 * 2`
|
||||||
/// * `2 * 2 + 2` (but will leave the `+ 2` unparsed).
|
/// * `2 * 2 + 2` (but will leave the `+ 2` unparsed).
|
||||||
///
|
///
|
||||||
fn parse_product(
|
fn parse_product<'i, 't>(
|
||||||
context: &ParserContext,
|
context: &ParserContext,
|
||||||
input: &mut Parser,
|
input: &mut Parser<'i, 't>,
|
||||||
expected_unit: CalcUnit)
|
expected_unit: CalcUnit)
|
||||||
-> Result<Self, ()>
|
-> Result<Self, ParseError<'i>>
|
||||||
{
|
{
|
||||||
let mut root = Self::parse_one(context, input, expected_unit)?;
|
let mut root = Self::parse_one(context, input, expected_unit)?;
|
||||||
|
|
||||||
|
@ -491,65 +494,71 @@ impl CalcNode {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convenience parsing function for integers.
|
/// Convenience parsing function for integers.
|
||||||
pub fn parse_integer(
|
pub fn parse_integer<'i, 't>(
|
||||||
context: &ParserContext,
|
context: &ParserContext,
|
||||||
input: &mut Parser)
|
input: &mut Parser<'i, 't>)
|
||||||
-> Result<CSSInteger, ()>
|
-> Result<CSSInteger, ParseError<'i>>
|
||||||
{
|
{
|
||||||
Self::parse(context, input, CalcUnit::Integer)?
|
Self::parse(context, input, CalcUnit::Integer)?
|
||||||
.to_number()
|
.to_number()
|
||||||
.map(|n| n as CSSInteger)
|
.map(|n| n as CSSInteger)
|
||||||
|
.map_err(|()| StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convenience parsing function for `<length> | <percentage>`.
|
/// Convenience parsing function for `<length> | <percentage>`.
|
||||||
pub fn parse_length_or_percentage(
|
pub fn parse_length_or_percentage<'i, 't>(
|
||||||
context: &ParserContext,
|
context: &ParserContext,
|
||||||
input: &mut Parser,
|
input: &mut Parser<'i, 't>,
|
||||||
clamping_mode: AllowedLengthType)
|
clamping_mode: AllowedLengthType)
|
||||||
-> Result<CalcLengthOrPercentage, ()>
|
-> Result<CalcLengthOrPercentage, ParseError<'i>>
|
||||||
{
|
{
|
||||||
Self::parse(context, input, CalcUnit::LengthOrPercentage)?
|
Self::parse(context, input, CalcUnit::LengthOrPercentage)?
|
||||||
.to_length_or_percentage(clamping_mode)
|
.to_length_or_percentage(clamping_mode)
|
||||||
|
.map_err(|()| StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convenience parsing function for `<length>`.
|
/// Convenience parsing function for `<length>`.
|
||||||
pub fn parse_length(
|
pub fn parse_length<'i, 't>(
|
||||||
context: &ParserContext,
|
context: &ParserContext,
|
||||||
input: &mut Parser,
|
input: &mut Parser<'i, 't>,
|
||||||
clamping_mode: AllowedLengthType)
|
clamping_mode: AllowedLengthType)
|
||||||
-> Result<CalcLengthOrPercentage, ()>
|
-> Result<CalcLengthOrPercentage, ParseError<'i>>
|
||||||
{
|
{
|
||||||
Self::parse(context, input, CalcUnit::Length)?
|
Self::parse(context, input, CalcUnit::Length)?
|
||||||
.to_length_or_percentage(clamping_mode)
|
.to_length_or_percentage(clamping_mode)
|
||||||
|
.map_err(|()| StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convenience parsing function for `<number>`.
|
/// Convenience parsing function for `<number>`.
|
||||||
pub fn parse_number(
|
pub fn parse_number<'i, 't>(
|
||||||
context: &ParserContext,
|
context: &ParserContext,
|
||||||
input: &mut Parser)
|
input: &mut Parser<'i, 't>)
|
||||||
-> Result<CSSFloat, ()>
|
-> Result<CSSFloat, ParseError<'i>>
|
||||||
{
|
{
|
||||||
Self::parse(context, input, CalcUnit::Number)?
|
Self::parse(context, input, CalcUnit::Number)?
|
||||||
.to_number()
|
.to_number()
|
||||||
|
.map_err(|()| StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convenience parsing function for `<angle>`.
|
/// Convenience parsing function for `<angle>`.
|
||||||
pub fn parse_angle(
|
pub fn parse_angle<'i, 't>(
|
||||||
context: &ParserContext,
|
context: &ParserContext,
|
||||||
input: &mut Parser)
|
input: &mut Parser<'i, 't>)
|
||||||
-> Result<Angle, ()>
|
-> Result<Angle, ParseError<'i>>
|
||||||
{
|
{
|
||||||
Self::parse(context, input, CalcUnit::Angle)?
|
Self::parse(context, input, CalcUnit::Angle)?
|
||||||
.to_angle()
|
.to_angle()
|
||||||
|
.map_err(|()| StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convenience parsing function for `<time>`.
|
/// Convenience parsing function for `<time>`.
|
||||||
pub fn parse_time(
|
pub fn parse_time<'i, 't>(
|
||||||
context: &ParserContext,
|
context: &ParserContext,
|
||||||
input: &mut Parser)
|
input: &mut Parser<'i, 't>)
|
||||||
-> Result<Time, ()>
|
-> Result<Time, ParseError<'i>>
|
||||||
{
|
{
|
||||||
Self::parse(context, input, CalcUnit::Time)?
|
Self::parse(context, input, CalcUnit::Time)?
|
||||||
.to_time()
|
.to_time()
|
||||||
|
.map_err(|()| StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
//! Specified color values.
|
//! Specified color values.
|
||||||
|
|
||||||
use cssparser::{Color as CSSParserColor, Parser, RGBA, Token};
|
use cssparser::{Color as CSSParserColor, Parser, RGBA, Token, BasicParseError};
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
use gecko_bindings::structs::nscolor;
|
use gecko_bindings::structs::nscolor;
|
||||||
use itoa;
|
use itoa;
|
||||||
|
@ -13,7 +13,7 @@ use parser::{ParserContext, Parse};
|
||||||
use properties::longhands::color::SystemColor;
|
use properties::longhands::color::SystemColor;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use style_traits::ToCss;
|
use style_traits::{ToCss, ParseError, StyleParseError};
|
||||||
use super::AllowQuirks;
|
use super::AllowQuirks;
|
||||||
use values::computed::{Color as ComputedColor, Context, ToComputedValue};
|
use values::computed::{Color as ComputedColor, Context, ToComputedValue};
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@ impl From<RGBA> for Color {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for Color {
|
impl Parse for Color {
|
||||||
fn parse(_: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
// Currently we only store authored value for color keywords,
|
// Currently we only store authored value for color keywords,
|
||||||
// because all browsers serialize those values as keywords for
|
// because all browsers serialize those values as keywords for
|
||||||
// specified value.
|
// specified value.
|
||||||
|
@ -93,7 +93,7 @@ impl Parse for Color {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[cfg(not(feature = "gecko"))] {
|
#[cfg(not(feature = "gecko"))] {
|
||||||
Err(())
|
Err(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -157,13 +157,13 @@ impl Color {
|
||||||
/// Parse a color, with quirks.
|
/// Parse a color, with quirks.
|
||||||
///
|
///
|
||||||
/// https://quirks.spec.whatwg.org/#the-hashless-hex-color-quirk
|
/// https://quirks.spec.whatwg.org/#the-hashless-hex-color-quirk
|
||||||
pub fn parse_quirky(context: &ParserContext,
|
pub fn parse_quirky<'i, 't>(context: &ParserContext,
|
||||||
input: &mut Parser,
|
input: &mut Parser<'i, 't>,
|
||||||
allow_quirks: AllowQuirks)
|
allow_quirks: AllowQuirks)
|
||||||
-> Result<Self, ()> {
|
-> Result<Self, ParseError<'i>> {
|
||||||
input.try(|i| Self::parse(context, i)).or_else(|_| {
|
input.try(|i| Self::parse(context, i)).or_else(|_| {
|
||||||
if !allow_quirks.allowed(context.quirks_mode) {
|
if !allow_quirks.allowed(context.quirks_mode) {
|
||||||
return Err(());
|
return Err(StyleParseError::UnspecifiedError.into());
|
||||||
}
|
}
|
||||||
Color::parse_quirky_color(input).map(|rgba| Color::rgba(rgba))
|
Color::parse_quirky_color(input).map(|rgba| Color::rgba(rgba))
|
||||||
})
|
})
|
||||||
|
@ -172,7 +172,7 @@ impl Color {
|
||||||
/// Parse a <quirky-color> value.
|
/// Parse a <quirky-color> value.
|
||||||
///
|
///
|
||||||
/// https://quirks.spec.whatwg.org/#the-hashless-hex-color-quirk
|
/// https://quirks.spec.whatwg.org/#the-hashless-hex-color-quirk
|
||||||
fn parse_quirky_color(input: &mut Parser) -> Result<RGBA, ()> {
|
fn parse_quirky_color<'i, 't>(input: &mut Parser<'i, 't>) -> Result<RGBA, ParseError<'i>> {
|
||||||
let (number, dimension) = match input.next()? {
|
let (number, dimension) = match input.next()? {
|
||||||
Token::Number(number) => {
|
Token::Number(number) => {
|
||||||
(number, None)
|
(number, None)
|
||||||
|
@ -182,17 +182,18 @@ impl Color {
|
||||||
},
|
},
|
||||||
Token::Ident(ident) => {
|
Token::Ident(ident) => {
|
||||||
if ident.len() != 3 && ident.len() != 6 {
|
if ident.len() != 3 && ident.len() != 6 {
|
||||||
return Err(());
|
return Err(StyleParseError::UnspecifiedError.into());
|
||||||
}
|
}
|
||||||
return parse_hash_color(ident.as_bytes());
|
return parse_hash_color(ident.as_bytes())
|
||||||
|
.map_err(|()| StyleParseError::UnspecifiedError.into());
|
||||||
}
|
}
|
||||||
_ => {
|
t => {
|
||||||
return Err(());
|
return Err(BasicParseError::UnexpectedToken(t).into());
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
let value = number.int_value.ok_or(())?;
|
let value = number.int_value.ok_or(StyleParseError::UnspecifiedError)?;
|
||||||
if value < 0 {
|
if value < 0 {
|
||||||
return Err(());
|
return Err(StyleParseError::UnspecifiedError.into());
|
||||||
}
|
}
|
||||||
let length = if value <= 9 {
|
let length = if value <= 9 {
|
||||||
1
|
1
|
||||||
|
@ -207,11 +208,11 @@ impl Color {
|
||||||
} else if value <= 999999 {
|
} else if value <= 999999 {
|
||||||
6
|
6
|
||||||
} else {
|
} else {
|
||||||
return Err(())
|
return Err(StyleParseError::UnspecifiedError.into())
|
||||||
};
|
};
|
||||||
let total = length + dimension.as_ref().map_or(0, |d| d.len());
|
let total = length + dimension.as_ref().map_or(0, |d| d.len());
|
||||||
if total > 6 {
|
if total > 6 {
|
||||||
return Err(());
|
return Err(StyleParseError::UnspecifiedError.into());
|
||||||
}
|
}
|
||||||
let mut serialization = [b'0'; 6];
|
let mut serialization = [b'0'; 6];
|
||||||
let space_padding = 6 - total;
|
let space_padding = 6 - total;
|
||||||
|
@ -221,7 +222,7 @@ impl Color {
|
||||||
written += (&mut serialization[written..]).write(dimension.as_bytes()).unwrap();
|
written += (&mut serialization[written..]).write(dimension.as_bytes()).unwrap();
|
||||||
}
|
}
|
||||||
debug_assert!(written == 6);
|
debug_assert!(written == 6);
|
||||||
parse_hash_color(&serialization)
|
parse_hash_color(&serialization).map_err(|()| StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns false if the color is completely transparent, and
|
/// Returns false if the color is completely transparent, and
|
||||||
|
@ -306,7 +307,7 @@ pub struct RGBAColor(pub Color);
|
||||||
no_viewport_percentage!(RGBAColor);
|
no_viewport_percentage!(RGBAColor);
|
||||||
|
|
||||||
impl Parse for RGBAColor {
|
impl Parse for RGBAColor {
|
||||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
Color::parse(context, input).map(RGBAColor)
|
Color::parse(context, input).map(RGBAColor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
use cssparser::Parser;
|
use cssparser::Parser;
|
||||||
use parser::{Parse, ParserContext};
|
use parser::{Parse, ParserContext};
|
||||||
|
use style_traits::ParseError;
|
||||||
use values::generics::gecko::ScrollSnapPoint as GenericScrollSnapPoint;
|
use values::generics::gecko::ScrollSnapPoint as GenericScrollSnapPoint;
|
||||||
use values::specified::length::LengthOrPercentage;
|
use values::specified::length::LengthOrPercentage;
|
||||||
|
|
||||||
|
@ -13,7 +14,7 @@ use values::specified::length::LengthOrPercentage;
|
||||||
pub type ScrollSnapPoint = GenericScrollSnapPoint<LengthOrPercentage>;
|
pub type ScrollSnapPoint = GenericScrollSnapPoint<LengthOrPercentage>;
|
||||||
|
|
||||||
impl Parse for ScrollSnapPoint {
|
impl Parse for ScrollSnapPoint {
|
||||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
if input.try(|i| i.expect_ident_matching("none")).is_ok() {
|
if input.try(|i| i.expect_ident_matching("none")).is_ok() {
|
||||||
return Ok(GenericScrollSnapPoint::None);
|
return Ok(GenericScrollSnapPoint::None);
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,11 +5,11 @@
|
||||||
//! CSS handling for the computed value of
|
//! CSS handling for the computed value of
|
||||||
//! [grids](https://drafts.csswg.org/css-grid/)
|
//! [grids](https://drafts.csswg.org/css-grid/)
|
||||||
|
|
||||||
use cssparser::{Parser, Token};
|
use cssparser::{Parser, Token, BasicParseError};
|
||||||
use parser::{Parse, ParserContext};
|
use parser::{Parse, ParserContext};
|
||||||
use std::{mem, usize};
|
use std::{mem, usize};
|
||||||
use std::ascii::AsciiExt;
|
use std::ascii::AsciiExt;
|
||||||
use style_traits::HasViewportPercentage;
|
use style_traits::{HasViewportPercentage, ParseError, StyleParseError};
|
||||||
use values::{CSSFloat, CustomIdent, Either};
|
use values::{CSSFloat, CustomIdent, Either};
|
||||||
use values::computed::{self, Context, ToComputedValue};
|
use values::computed::{self, Context, ToComputedValue};
|
||||||
use values::generics::grid::{RepeatCount, TrackBreadth, TrackKeyword, TrackRepeat};
|
use values::generics::grid::{RepeatCount, TrackBreadth, TrackKeyword, TrackRepeat};
|
||||||
|
@ -17,16 +17,16 @@ use values::generics::grid::{TrackSize, TrackList, TrackListType};
|
||||||
use values::specified::LengthOrPercentage;
|
use values::specified::LengthOrPercentage;
|
||||||
|
|
||||||
/// Parse a single flexible length.
|
/// Parse a single flexible length.
|
||||||
pub fn parse_flex(input: &mut Parser) -> Result<CSSFloat, ()> {
|
pub fn parse_flex<'i, 't>(input: &mut Parser<'i, 't>) -> Result<CSSFloat, ParseError<'i>> {
|
||||||
match input.next()? {
|
match input.next()? {
|
||||||
Token::Dimension(ref value, ref unit) if unit.eq_ignore_ascii_case("fr") && value.value.is_sign_positive()
|
Token::Dimension(ref value, ref unit) if unit.eq_ignore_ascii_case("fr") && value.value.is_sign_positive()
|
||||||
=> Ok(value.value),
|
=> Ok(value.value),
|
||||||
_ => Err(()),
|
t => Err(BasicParseError::UnexpectedToken(t).into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for TrackBreadth<LengthOrPercentage> {
|
impl Parse for TrackBreadth<LengthOrPercentage> {
|
||||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
if let Ok(lop) = input.try(|i| LengthOrPercentage::parse_non_negative(context, i)) {
|
if let Ok(lop) = input.try(|i| LengthOrPercentage::parse_non_negative(context, i)) {
|
||||||
return Ok(TrackBreadth::Breadth(lop))
|
return Ok(TrackBreadth::Breadth(lop))
|
||||||
}
|
}
|
||||||
|
@ -51,7 +51,7 @@ impl HasViewportPercentage for TrackBreadth<LengthOrPercentage> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for TrackSize<LengthOrPercentage> {
|
impl Parse for TrackSize<LengthOrPercentage> {
|
||||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
if let Ok(b) = input.try(|i| TrackBreadth::parse(context, i)) {
|
if let Ok(b) = input.try(|i| TrackBreadth::parse(context, i)) {
|
||||||
return Ok(TrackSize::Breadth(b))
|
return Ok(TrackSize::Breadth(b))
|
||||||
}
|
}
|
||||||
|
@ -81,13 +81,13 @@ impl Parse for TrackSize<LengthOrPercentage> {
|
||||||
/// Parse the grid line names into a vector of owned strings.
|
/// Parse the grid line names into a vector of owned strings.
|
||||||
///
|
///
|
||||||
/// https://drafts.csswg.org/css-grid/#typedef-line-names
|
/// https://drafts.csswg.org/css-grid/#typedef-line-names
|
||||||
pub fn parse_line_names(input: &mut Parser) -> Result<Vec<String>, ()> {
|
pub fn parse_line_names<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Vec<String>, ParseError<'i>> {
|
||||||
input.expect_square_bracket_block()?;
|
input.expect_square_bracket_block()?;
|
||||||
input.parse_nested_block(|input| {
|
input.parse_nested_block(|input| {
|
||||||
let mut values = vec![];
|
let mut values = vec![];
|
||||||
while let Ok(ident) = input.try(|i| i.expect_ident()) {
|
while let Ok(ident) = input.try(|i| i.expect_ident()) {
|
||||||
if CustomIdent::from_ident((&*ident).into(), &["span"]).is_err() {
|
if CustomIdent::from_ident((&*ident).into(), &["span"]).is_err() {
|
||||||
return Err(())
|
return Err(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
values.push(ident.into_owned());
|
values.push(ident.into_owned());
|
||||||
|
@ -112,9 +112,10 @@ enum RepeatType {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TrackRepeat<LengthOrPercentage> {
|
impl TrackRepeat<LengthOrPercentage> {
|
||||||
fn parse_with_repeat_type(context: &ParserContext, input: &mut Parser)
|
fn parse_with_repeat_type<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
-> Result<(TrackRepeat<LengthOrPercentage>, RepeatType), ()> {
|
-> Result<(TrackRepeat<LengthOrPercentage>, RepeatType),
|
||||||
input.try(|i| i.expect_function_matching("repeat")).and_then(|_| {
|
ParseError<'i>> {
|
||||||
|
input.try(|i| i.expect_function_matching("repeat").map_err(|e| e.into())).and_then(|_| {
|
||||||
input.parse_nested_block(|input| {
|
input.parse_nested_block(|input| {
|
||||||
let count = RepeatCount::parse(context, input)?;
|
let count = RepeatCount::parse(context, input)?;
|
||||||
input.expect_comma()?;
|
input.expect_comma()?;
|
||||||
|
@ -135,7 +136,8 @@ impl TrackRepeat<LengthOrPercentage> {
|
||||||
if let Ok(track_size) = input.try(|i| TrackSize::parse(context, i)) {
|
if let Ok(track_size) = input.try(|i| TrackSize::parse(context, i)) {
|
||||||
if !track_size.is_fixed() {
|
if !track_size.is_fixed() {
|
||||||
if is_auto {
|
if is_auto {
|
||||||
return Err(()) // should be <fixed-size> for <auto-repeat>
|
// should be <fixed-size> for <auto-repeat>
|
||||||
|
return Err(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
if repeat_type == RepeatType::Fixed {
|
if repeat_type == RepeatType::Fixed {
|
||||||
|
@ -147,7 +149,8 @@ impl TrackRepeat<LengthOrPercentage> {
|
||||||
names.push(current_names);
|
names.push(current_names);
|
||||||
} else {
|
} else {
|
||||||
if values.is_empty() {
|
if values.is_empty() {
|
||||||
return Err(()) // expecting at least one <track-size>
|
// expecting at least one <track-size>
|
||||||
|
return Err(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
names.push(current_names); // final `<line-names>`
|
names.push(current_names); // final `<line-names>`
|
||||||
|
@ -181,7 +184,7 @@ impl HasViewportPercentage for TrackRepeat<LengthOrPercentage> {
|
||||||
pub type TrackSizeOrRepeat = Either<TrackSize<LengthOrPercentage>, TrackRepeat<LengthOrPercentage>>;
|
pub type TrackSizeOrRepeat = Either<TrackSize<LengthOrPercentage>, TrackRepeat<LengthOrPercentage>>;
|
||||||
|
|
||||||
impl Parse for TrackList<TrackSizeOrRepeat> {
|
impl Parse for TrackList<TrackSizeOrRepeat> {
|
||||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
let mut current_names;
|
let mut current_names;
|
||||||
let mut names = vec![];
|
let mut names = vec![];
|
||||||
let mut values = vec![];
|
let mut values = vec![];
|
||||||
|
@ -198,7 +201,8 @@ impl Parse for TrackList<TrackSizeOrRepeat> {
|
||||||
if !track_size.is_fixed() {
|
if !track_size.is_fixed() {
|
||||||
atleast_one_not_fixed = true;
|
atleast_one_not_fixed = true;
|
||||||
if is_auto {
|
if is_auto {
|
||||||
return Err(()) // <auto-track-list> only accepts <fixed-size> and <fixed-repeat>
|
// <auto-track-list> only accepts <fixed-size> and <fixed-repeat>
|
||||||
|
return Err(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -213,13 +217,13 @@ impl Parse for TrackList<TrackSizeOrRepeat> {
|
||||||
RepeatType::Normal => {
|
RepeatType::Normal => {
|
||||||
atleast_one_not_fixed = true;
|
atleast_one_not_fixed = true;
|
||||||
if is_auto { // only <fixed-repeat>
|
if is_auto { // only <fixed-repeat>
|
||||||
return Err(())
|
return Err(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
RepeatType::Auto => {
|
RepeatType::Auto => {
|
||||||
if is_auto || atleast_one_not_fixed {
|
if is_auto || atleast_one_not_fixed {
|
||||||
// We've either seen <auto-repeat> earlier, or there's at least one non-fixed value
|
// We've either seen <auto-repeat> earlier, or there's at least one non-fixed value
|
||||||
return Err(())
|
return Err(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
is_auto = true;
|
is_auto = true;
|
||||||
|
@ -232,7 +236,7 @@ impl Parse for TrackList<TrackSizeOrRepeat> {
|
||||||
values.push(Either::Second(repeat));
|
values.push(Either::Second(repeat));
|
||||||
} else {
|
} else {
|
||||||
if values.is_empty() {
|
if values.is_empty() {
|
||||||
return Err(())
|
return Err(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
names.push(current_names);
|
names.push(current_names);
|
||||||
|
|
|
@ -8,14 +8,15 @@
|
||||||
//! [image]: https://drafts.csswg.org/css-images/#image-values
|
//! [image]: https://drafts.csswg.org/css-images/#image-values
|
||||||
|
|
||||||
use Atom;
|
use Atom;
|
||||||
use cssparser::{Parser, Token};
|
use cssparser::{Parser, Token, BasicParseError};
|
||||||
use parser::{Parse, ParserContext};
|
use parser::{Parse, ParserContext};
|
||||||
|
use selectors::parser::SelectorParseError;
|
||||||
#[cfg(feature = "servo")]
|
#[cfg(feature = "servo")]
|
||||||
use servo_url::ServoUrl;
|
use servo_url::ServoUrl;
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::f32::consts::PI;
|
use std::f32::consts::PI;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use style_traits::ToCss;
|
use style_traits::{ToCss, ParseError, StyleParseError};
|
||||||
use values::{Either, None_};
|
use values::{Either, None_};
|
||||||
use values::generics::image::{Circle, CompatMode, Ellipse, ColorStop as GenericColorStop};
|
use values::generics::image::{Circle, CompatMode, Ellipse, ColorStop as GenericColorStop};
|
||||||
use values::generics::image::{EndingShape as GenericEndingShape, Gradient as GenericGradient};
|
use values::generics::image::{EndingShape as GenericEndingShape, Gradient as GenericGradient};
|
||||||
|
@ -82,7 +83,7 @@ pub type ColorStop = GenericColorStop<RGBAColor, LengthOrPercentage>;
|
||||||
pub type ImageRect = GenericImageRect<NumberOrPercentage>;
|
pub type ImageRect = GenericImageRect<NumberOrPercentage>;
|
||||||
|
|
||||||
impl Parse for Image {
|
impl Parse for Image {
|
||||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Image, ()> {
|
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Image, ParseError<'i>> {
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
{
|
{
|
||||||
if let Ok(mut url) = input.try(|input| SpecifiedUrl::parse(context, input)) {
|
if let Ok(mut url) = input.try(|input| SpecifiedUrl::parse(context, input)) {
|
||||||
|
@ -132,53 +133,59 @@ impl Image {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses a `-moz-element(# <element-id>)`.
|
/// Parses a `-moz-element(# <element-id>)`.
|
||||||
fn parse_element(input: &mut Parser) -> Result<Atom, ()> {
|
fn parse_element<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Atom, ParseError<'i>> {
|
||||||
input.try(|i| i.expect_function_matching("-moz-element"))?;
|
input.try(|i| i.expect_function_matching("-moz-element"))?;
|
||||||
input.parse_nested_block(|i| {
|
input.parse_nested_block(|i| {
|
||||||
match i.next()? {
|
match i.next()? {
|
||||||
Token::IDHash(id) => Ok(Atom::from(id)),
|
Token::IDHash(id) => Ok(Atom::from(id)),
|
||||||
_ => Err(()),
|
t => Err(BasicParseError::UnexpectedToken(t).into()),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for Gradient {
|
impl Parse for Gradient {
|
||||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
enum Shape {
|
enum Shape {
|
||||||
Linear,
|
Linear,
|
||||||
Radial,
|
Radial,
|
||||||
}
|
}
|
||||||
|
|
||||||
let (shape, repeating, compat_mode) = match_ignore_ascii_case! { &try!(input.expect_function()),
|
let func = try!(input.expect_function());
|
||||||
|
let result = match_ignore_ascii_case! { &func,
|
||||||
"linear-gradient" => {
|
"linear-gradient" => {
|
||||||
(Shape::Linear, false, CompatMode::Modern)
|
Some((Shape::Linear, false, CompatMode::Modern))
|
||||||
},
|
},
|
||||||
"-webkit-linear-gradient" => {
|
"-webkit-linear-gradient" => {
|
||||||
(Shape::Linear, false, CompatMode::WebKit)
|
Some((Shape::Linear, false, CompatMode::WebKit))
|
||||||
},
|
},
|
||||||
"repeating-linear-gradient" => {
|
"repeating-linear-gradient" => {
|
||||||
(Shape::Linear, true, CompatMode::Modern)
|
Some((Shape::Linear, true, CompatMode::Modern))
|
||||||
},
|
},
|
||||||
"-webkit-repeating-linear-gradient" => {
|
"-webkit-repeating-linear-gradient" => {
|
||||||
(Shape::Linear, true, CompatMode::WebKit)
|
Some((Shape::Linear, true, CompatMode::WebKit))
|
||||||
},
|
},
|
||||||
"radial-gradient" => {
|
"radial-gradient" => {
|
||||||
(Shape::Radial, false, CompatMode::Modern)
|
Some((Shape::Radial, false, CompatMode::Modern))
|
||||||
},
|
},
|
||||||
"-webkit-radial-gradient" => {
|
"-webkit-radial-gradient" => {
|
||||||
(Shape::Radial, false, CompatMode::WebKit)
|
Some((Shape::Radial, false, CompatMode::WebKit))
|
||||||
},
|
},
|
||||||
"repeating-radial-gradient" => {
|
"repeating-radial-gradient" => {
|
||||||
(Shape::Radial, true, CompatMode::Modern)
|
Some((Shape::Radial, true, CompatMode::Modern))
|
||||||
},
|
},
|
||||||
"-webkit-repeating-radial-gradient" => {
|
"-webkit-repeating-radial-gradient" => {
|
||||||
(Shape::Radial, true, CompatMode::WebKit)
|
Some((Shape::Radial, true, CompatMode::WebKit))
|
||||||
},
|
},
|
||||||
"-webkit-gradient" => {
|
"-webkit-gradient" => {
|
||||||
return input.parse_nested_block(|i| Self::parse_webkit_gradient_argument(context, i));
|
return input.parse_nested_block(|i| Self::parse_webkit_gradient_argument(context, i));
|
||||||
},
|
},
|
||||||
_ => { return Err(()); }
|
_ => None,
|
||||||
|
};
|
||||||
|
|
||||||
|
let (shape, repeating, compat_mode) = match result {
|
||||||
|
Some(result) => result,
|
||||||
|
None => return Err(StyleParseError::UnexpectedFunction(func).into()),
|
||||||
};
|
};
|
||||||
|
|
||||||
let (kind, items) = input.parse_nested_block(|i| {
|
let (kind, items) = input.parse_nested_block(|i| {
|
||||||
|
@ -191,7 +198,7 @@ impl Parse for Gradient {
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
if items.len() < 2 {
|
if items.len() < 2 {
|
||||||
return Err(());
|
return Err(StyleParseError::UnspecifiedError.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Gradient {
|
Ok(Gradient {
|
||||||
|
@ -204,7 +211,8 @@ impl Parse for Gradient {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Gradient {
|
impl Gradient {
|
||||||
fn parse_webkit_gradient_argument(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse_webkit_gradient_argument<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<Self, ParseError<'i>> {
|
||||||
type Point = GenericPosition<Component<X>, Component<Y>>;
|
type Point = GenericPosition<Component<X>, Component<Y>>;
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
|
@ -259,7 +267,8 @@ impl Gradient {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for Point {
|
impl Parse for Point {
|
||||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<Self, ParseError<'i>> {
|
||||||
input.try(|i| {
|
input.try(|i| {
|
||||||
let x = Component::parse(context, i)?;
|
let x = Component::parse(context, i)?;
|
||||||
let y = Component::parse(context, i)?;
|
let y = Component::parse(context, i)?;
|
||||||
|
@ -318,7 +327,8 @@ impl Gradient {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S: Parse> Parse for Component<S> {
|
impl<S: Parse> Parse for Component<S> {
|
||||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<Self, ParseError<'i>> {
|
||||||
if let Ok(side) = input.try(|i| S::parse(context, i)) {
|
if let Ok(side) = input.try(|i| S::parse(context, i)) {
|
||||||
return Ok(Component::Side(side));
|
return Ok(Component::Side(side));
|
||||||
}
|
}
|
||||||
|
@ -365,7 +375,7 @@ impl Gradient {
|
||||||
|
|
||||||
(kind, reverse_stops)
|
(kind, reverse_stops)
|
||||||
},
|
},
|
||||||
_ => return Err(()),
|
_ => return Err(SelectorParseError::UnexpectedIdent(ident.clone()).into()),
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut items = input.try(|i| {
|
let mut items = input.try(|i| {
|
||||||
|
@ -384,11 +394,11 @@ impl Gradient {
|
||||||
},
|
},
|
||||||
"from" => 0.,
|
"from" => 0.,
|
||||||
"to" => 1.,
|
"to" => 1.,
|
||||||
_ => return Err(()),
|
_ => return Err(StyleParseError::UnexpectedFunction(function.clone()).into()),
|
||||||
};
|
};
|
||||||
let color = Color::parse(context, i)?;
|
let color = Color::parse(context, i)?;
|
||||||
if color == Color::CurrentColor {
|
if color == Color::CurrentColor {
|
||||||
return Err(());
|
return Err(StyleParseError::UnspecifiedError.into());
|
||||||
}
|
}
|
||||||
Ok((color.into(), p))
|
Ok((color.into(), p))
|
||||||
})?;
|
})?;
|
||||||
|
@ -450,10 +460,10 @@ impl Gradient {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GradientKind {
|
impl GradientKind {
|
||||||
fn parse_linear(context: &ParserContext,
|
fn parse_linear<'i, 't>(context: &ParserContext,
|
||||||
input: &mut Parser,
|
input: &mut Parser<'i, 't>,
|
||||||
compat_mode: CompatMode)
|
compat_mode: CompatMode)
|
||||||
-> Result<Self, ()> {
|
-> Result<Self, ParseError<'i>> {
|
||||||
let direction = if let Ok(d) = input.try(|i| LineDirection::parse(context, i, compat_mode)) {
|
let direction = if let Ok(d) = input.try(|i| LineDirection::parse(context, i, compat_mode)) {
|
||||||
input.expect_comma()?;
|
input.expect_comma()?;
|
||||||
d
|
d
|
||||||
|
@ -463,10 +473,10 @@ impl GradientKind {
|
||||||
Ok(GenericGradientKind::Linear(direction))
|
Ok(GenericGradientKind::Linear(direction))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_radial(context: &ParserContext,
|
fn parse_radial<'i, 't>(context: &ParserContext,
|
||||||
input: &mut Parser,
|
input: &mut Parser<'i, 't>,
|
||||||
compat_mode: CompatMode)
|
compat_mode: CompatMode)
|
||||||
-> Result<Self, ()> {
|
-> Result<Self, ParseError<'i>> {
|
||||||
let (shape, position) = if compat_mode == CompatMode::Modern {
|
let (shape, position) = if compat_mode == CompatMode::Modern {
|
||||||
let shape = input.try(|i| EndingShape::parse(context, i, compat_mode));
|
let shape = input.try(|i| EndingShape::parse(context, i, compat_mode));
|
||||||
let position = input.try(|i| {
|
let position = input.try(|i| {
|
||||||
|
@ -538,10 +548,10 @@ impl GenericsLineDirection for LineDirection {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LineDirection {
|
impl LineDirection {
|
||||||
fn parse(context: &ParserContext,
|
fn parse<'i, 't>(context: &ParserContext,
|
||||||
input: &mut Parser,
|
input: &mut Parser<'i, 't>,
|
||||||
compat_mode: CompatMode)
|
compat_mode: CompatMode)
|
||||||
-> Result<Self, ()> {
|
-> Result<Self, ParseError<'i>> {
|
||||||
if let Ok(angle) = input.try(|i| Angle::parse_with_unitless(context, i)) {
|
if let Ok(angle) = input.try(|i| Angle::parse_with_unitless(context, i)) {
|
||||||
return Ok(LineDirection::Angle(angle));
|
return Ok(LineDirection::Angle(angle));
|
||||||
}
|
}
|
||||||
|
@ -565,10 +575,10 @@ impl LineDirection {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EndingShape {
|
impl EndingShape {
|
||||||
fn parse(context: &ParserContext,
|
fn parse<'i, 't>(context: &ParserContext,
|
||||||
input: &mut Parser,
|
input: &mut Parser<'i, 't>,
|
||||||
compat_mode: CompatMode)
|
compat_mode: CompatMode)
|
||||||
-> Result<Self, ()> {
|
-> Result<Self, ParseError<'i>> {
|
||||||
if let Ok(extent) = input.try(|i| ShapeExtent::parse_with_compat_mode(i, compat_mode)) {
|
if let Ok(extent) = input.try(|i| ShapeExtent::parse_with_compat_mode(i, compat_mode)) {
|
||||||
if input.try(|i| i.expect_ident_matching("circle")).is_ok() {
|
if input.try(|i| i.expect_ident_matching("circle")).is_ok() {
|
||||||
return Ok(GenericEndingShape::Circle(Circle::Extent(extent)));
|
return Ok(GenericEndingShape::Circle(Circle::Extent(extent)));
|
||||||
|
@ -592,7 +602,7 @@ impl EndingShape {
|
||||||
return Ok(GenericEndingShape::Ellipse(Ellipse::Extent(extent)));
|
return Ok(GenericEndingShape::Ellipse(Ellipse::Extent(extent)));
|
||||||
}
|
}
|
||||||
if compat_mode == CompatMode::Modern {
|
if compat_mode == CompatMode::Modern {
|
||||||
let pair: Result<_, ()> = input.try(|i| {
|
let pair: Result<_, ParseError> = input.try(|i| {
|
||||||
let x = LengthOrPercentage::parse(context, i)?;
|
let x = LengthOrPercentage::parse(context, i)?;
|
||||||
let y = LengthOrPercentage::parse(context, i)?;
|
let y = LengthOrPercentage::parse(context, i)?;
|
||||||
Ok((x, y))
|
Ok((x, y))
|
||||||
|
@ -641,18 +651,20 @@ impl EndingShape {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ShapeExtent {
|
impl ShapeExtent {
|
||||||
fn parse_with_compat_mode(input: &mut Parser,
|
fn parse_with_compat_mode<'i, 't>(input: &mut Parser<'i, 't>,
|
||||||
compat_mode: CompatMode)
|
compat_mode: CompatMode)
|
||||||
-> Result<Self, ()> {
|
-> Result<Self, ParseError<'i>> {
|
||||||
match try!(Self::parse(input)) {
|
match try!(Self::parse(input)) {
|
||||||
ShapeExtent::Contain | ShapeExtent::Cover if compat_mode == CompatMode::Modern => Err(()),
|
ShapeExtent::Contain | ShapeExtent::Cover if compat_mode == CompatMode::Modern =>
|
||||||
|
Err(StyleParseError::UnspecifiedError.into()),
|
||||||
keyword => Ok(keyword),
|
keyword => Ok(keyword),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GradientItem {
|
impl GradientItem {
|
||||||
fn parse_comma_separated(context: &ParserContext, input: &mut Parser) -> Result<Vec<Self>, ()> {
|
fn parse_comma_separated<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<Vec<Self>, ParseError<'i>> {
|
||||||
let mut seen_stop = false;
|
let mut seen_stop = false;
|
||||||
let items = try!(input.parse_comma_separated(|input| {
|
let items = try!(input.parse_comma_separated(|input| {
|
||||||
if seen_stop {
|
if seen_stop {
|
||||||
|
@ -665,14 +677,15 @@ impl GradientItem {
|
||||||
ColorStop::parse(context, input).map(GenericGradientItem::ColorStop)
|
ColorStop::parse(context, input).map(GenericGradientItem::ColorStop)
|
||||||
}));
|
}));
|
||||||
if !seen_stop || items.len() < 2 {
|
if !seen_stop || items.len() < 2 {
|
||||||
return Err(());
|
return Err(StyleParseError::UnspecifiedError.into());
|
||||||
}
|
}
|
||||||
Ok(items)
|
Ok(items)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for ColorStop {
|
impl Parse for ColorStop {
|
||||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<Self, ParseError<'i>> {
|
||||||
Ok(ColorStop {
|
Ok(ColorStop {
|
||||||
color: try!(RGBAColor::parse(context, input)),
|
color: try!(RGBAColor::parse(context, input)),
|
||||||
position: input.try(|i| LengthOrPercentage::parse(context, i)).ok(),
|
position: input.try(|i| LengthOrPercentage::parse(context, i)).ok(),
|
||||||
|
@ -681,7 +694,7 @@ impl Parse for ColorStop {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for PaintWorklet {
|
impl Parse for PaintWorklet {
|
||||||
fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
input.expect_function_matching("paint")?;
|
input.expect_function_matching("paint")?;
|
||||||
input.parse_nested_block(|i| {
|
input.parse_nested_block(|i| {
|
||||||
let name = i.expect_ident()?;
|
let name = i.expect_ident()?;
|
||||||
|
@ -693,7 +706,7 @@ impl Parse for PaintWorklet {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for ImageRect {
|
impl Parse for ImageRect {
|
||||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
input.try(|i| i.expect_function_matching("-moz-image-rect"))?;
|
input.try(|i| i.expect_function_matching("-moz-image-rect"))?;
|
||||||
input.parse_nested_block(|i| {
|
input.parse_nested_block(|i| {
|
||||||
let string = i.expect_url_or_string()?;
|
let string = i.expect_url_or_string()?;
|
||||||
|
|
|
@ -7,14 +7,14 @@
|
||||||
//! [length]: https://drafts.csswg.org/css-values/#lengths
|
//! [length]: https://drafts.csswg.org/css-values/#lengths
|
||||||
|
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
use cssparser::{Parser, Token};
|
use cssparser::{Parser, Token, BasicParseError};
|
||||||
use euclid::size::Size2D;
|
use euclid::size::Size2D;
|
||||||
use font_metrics::FontMetricsQueryResult;
|
use font_metrics::FontMetricsQueryResult;
|
||||||
use parser::{Parse, ParserContext};
|
use parser::{Parse, ParserContext};
|
||||||
use std::{cmp, fmt, mem};
|
use std::{cmp, fmt, mem};
|
||||||
use std::ascii::AsciiExt;
|
use std::ascii::AsciiExt;
|
||||||
use std::ops::Mul;
|
use std::ops::Mul;
|
||||||
use style_traits::{HasViewportPercentage, ToCss};
|
use style_traits::{HasViewportPercentage, ToCss, ParseError, StyleParseError};
|
||||||
use style_traits::values::specified::{AllowedLengthType, AllowedNumericType};
|
use style_traits::values::specified::{AllowedLengthType, AllowedNumericType};
|
||||||
use stylesheets::CssRuleType;
|
use stylesheets::CssRuleType;
|
||||||
use super::{AllowQuirks, Number, ToComputedValue};
|
use super::{AllowQuirks, Number, ToComputedValue};
|
||||||
|
@ -451,7 +451,8 @@ impl Mul<CSSFloat> for NoCalcLength {
|
||||||
|
|
||||||
impl NoCalcLength {
|
impl NoCalcLength {
|
||||||
/// Parse a given absolute or relative dimension.
|
/// Parse a given absolute or relative dimension.
|
||||||
pub fn parse_dimension(context: &ParserContext, value: CSSFloat, unit: &str) -> Result<NoCalcLength, ()> {
|
pub fn parse_dimension(context: &ParserContext, value: CSSFloat, unit: &str)
|
||||||
|
-> Result<NoCalcLength, ()> {
|
||||||
let in_page_rule = context.rule_type.map_or(false, |rule_type| rule_type == CssRuleType::Page);
|
let in_page_rule = context.rule_type.map_or(false, |rule_type| rule_type == CssRuleType::Page);
|
||||||
match_ignore_ascii_case! { unit,
|
match_ignore_ascii_case! { unit,
|
||||||
"px" => Ok(NoCalcLength::Absolute(AbsoluteLength::Px(value))),
|
"px" => Ok(NoCalcLength::Absolute(AbsoluteLength::Px(value))),
|
||||||
|
@ -597,47 +598,50 @@ impl Length {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a given absolute or relative dimension.
|
/// Parse a given absolute or relative dimension.
|
||||||
pub fn parse_dimension(context: &ParserContext, value: CSSFloat, unit: &str) -> Result<Length, ()> {
|
pub fn parse_dimension(context: &ParserContext, value: CSSFloat, unit: &str)
|
||||||
|
-> Result<Length, ()> {
|
||||||
NoCalcLength::parse_dimension(context, value, unit).map(Length::NoCalc)
|
NoCalcLength::parse_dimension(context, value, unit).map(Length::NoCalc)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn parse_internal(context: &ParserContext,
|
fn parse_internal<'i, 't>(context: &ParserContext,
|
||||||
input: &mut Parser,
|
input: &mut Parser<'i, 't>,
|
||||||
num_context: AllowedLengthType,
|
num_context: AllowedLengthType,
|
||||||
allow_quirks: AllowQuirks)
|
allow_quirks: AllowQuirks)
|
||||||
-> Result<Length, ()> {
|
-> Result<Length, ParseError<'i>> {
|
||||||
match try!(input.next()) {
|
let token = try!(input.next());
|
||||||
|
match token {
|
||||||
Token::Dimension(ref value, ref unit) if num_context.is_ok(value.value) =>
|
Token::Dimension(ref value, ref unit) if num_context.is_ok(value.value) =>
|
||||||
Length::parse_dimension(context, value.value, unit),
|
Length::parse_dimension(context, value.value, unit),
|
||||||
Token::Number(ref value) if num_context.is_ok(value.value) => {
|
Token::Number(ref value) if num_context.is_ok(value.value) => {
|
||||||
if value.value != 0. &&
|
if value.value != 0. &&
|
||||||
!context.parsing_mode.allows_unitless_lengths() &&
|
!context.parsing_mode.allows_unitless_lengths() &&
|
||||||
!allow_quirks.allowed(context.quirks_mode) {
|
!allow_quirks.allowed(context.quirks_mode) {
|
||||||
return Err(())
|
return Err(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
Ok(Length::NoCalc(NoCalcLength::Absolute(AbsoluteLength::Px(value.value))))
|
Ok(Length::NoCalc(NoCalcLength::Absolute(AbsoluteLength::Px(value.value))))
|
||||||
},
|
},
|
||||||
Token::Function(ref name) if name.eq_ignore_ascii_case("calc") =>
|
Token::Function(ref name) if name.eq_ignore_ascii_case("calc") =>
|
||||||
input.parse_nested_block(|input| {
|
return input.parse_nested_block(|input| {
|
||||||
CalcNode::parse_length(context, input, num_context).map(|calc| Length::Calc(Box::new(calc)))
|
CalcNode::parse_length(context, input, num_context).map(|calc| Length::Calc(Box::new(calc)))
|
||||||
}),
|
}),
|
||||||
_ => Err(())
|
_ => Err(())
|
||||||
}
|
}.map_err(|()| BasicParseError::UnexpectedToken(token).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a non-negative length
|
/// Parse a non-negative length
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn parse_non_negative(context: &ParserContext, input: &mut Parser) -> Result<Length, ()> {
|
pub fn parse_non_negative<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<Length, ParseError<'i>> {
|
||||||
Self::parse_non_negative_quirky(context, input, AllowQuirks::No)
|
Self::parse_non_negative_quirky(context, input, AllowQuirks::No)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a non-negative length, allowing quirks.
|
/// Parse a non-negative length, allowing quirks.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn parse_non_negative_quirky(context: &ParserContext,
|
pub fn parse_non_negative_quirky<'i, 't>(context: &ParserContext,
|
||||||
input: &mut Parser,
|
input: &mut Parser<'i, 't>,
|
||||||
allow_quirks: AllowQuirks)
|
allow_quirks: AllowQuirks)
|
||||||
-> Result<Length, ()> {
|
-> Result<Length, ParseError<'i>> {
|
||||||
Self::parse_internal(context, input, AllowedLengthType::NonNegative, allow_quirks)
|
Self::parse_internal(context, input, AllowedLengthType::NonNegative, allow_quirks)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -657,17 +661,17 @@ impl Length {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for Length {
|
impl Parse for Length {
|
||||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
Self::parse_quirky(context, input, AllowQuirks::No)
|
Self::parse_quirky(context, input, AllowQuirks::No)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Length {
|
impl Length {
|
||||||
/// Parses a length, with quirks.
|
/// Parses a length, with quirks.
|
||||||
pub fn parse_quirky(context: &ParserContext,
|
pub fn parse_quirky<'i, 't>(context: &ParserContext,
|
||||||
input: &mut Parser,
|
input: &mut Parser<'i, 't>,
|
||||||
allow_quirks: AllowQuirks)
|
allow_quirks: AllowQuirks)
|
||||||
-> Result<Self, ()> {
|
-> Result<Self, ParseError<'i>> {
|
||||||
Self::parse_internal(context, input, AllowedLengthType::All, allow_quirks)
|
Self::parse_internal(context, input, AllowedLengthType::All, allow_quirks)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -675,7 +679,8 @@ impl Length {
|
||||||
impl<T: Parse> Either<Length, T> {
|
impl<T: Parse> Either<Length, T> {
|
||||||
/// Parse a non-negative length
|
/// Parse a non-negative length
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn parse_non_negative_length(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
pub fn parse_non_negative_length<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<Self, ParseError<'i>> {
|
||||||
if let Ok(v) = input.try(|input| T::parse(context, input)) {
|
if let Ok(v) = input.try(|input| T::parse(context, input)) {
|
||||||
return Ok(Either::Second(v));
|
return Ok(Either::Second(v));
|
||||||
}
|
}
|
||||||
|
@ -710,19 +715,19 @@ impl ToCss for Percentage {
|
||||||
|
|
||||||
impl Percentage {
|
impl Percentage {
|
||||||
/// Parse a specific kind of percentage.
|
/// Parse a specific kind of percentage.
|
||||||
pub fn parse_with_clamping_mode(input: &mut Parser,
|
pub fn parse_with_clamping_mode<'i, 't>(input: &mut Parser<'i, 't>,
|
||||||
context: AllowedNumericType)
|
context: AllowedNumericType)
|
||||||
-> Result<Self, ()> {
|
-> Result<Self, ParseError<'i>> {
|
||||||
match try!(input.next()) {
|
match try!(input.next()) {
|
||||||
Token::Percentage(ref value) if context.is_ok(value.unit_value) => {
|
Token::Percentage(ref value) if context.is_ok(value.unit_value) => {
|
||||||
Ok(Percentage(value.unit_value))
|
Ok(Percentage(value.unit_value))
|
||||||
}
|
}
|
||||||
_ => Err(())
|
t => Err(BasicParseError::UnexpectedToken(t).into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses a percentage token, but rejects it if it's negative.
|
/// Parses a percentage token, but rejects it if it's negative.
|
||||||
pub fn parse_non_negative(input: &mut Parser) -> Result<Self, ()> {
|
pub fn parse_non_negative<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
Self::parse_with_clamping_mode(input, AllowedNumericType::NonNegative)
|
Self::parse_with_clamping_mode(input, AllowedNumericType::NonNegative)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -741,7 +746,7 @@ impl Percentage {
|
||||||
|
|
||||||
impl Parse for Percentage {
|
impl Parse for Percentage {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
Self::parse_with_clamping_mode(input, AllowedNumericType::All)
|
Self::parse_with_clamping_mode(input, AllowedNumericType::All)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -788,54 +793,58 @@ impl LengthOrPercentage {
|
||||||
LengthOrPercentage::Length(NoCalcLength::zero())
|
LengthOrPercentage::Length(NoCalcLength::zero())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_internal(context: &ParserContext,
|
fn parse_internal<'i, 't>(context: &ParserContext,
|
||||||
input: &mut Parser,
|
input: &mut Parser<'i, 't>,
|
||||||
num_context: AllowedLengthType,
|
num_context: AllowedLengthType,
|
||||||
allow_quirks: AllowQuirks)
|
allow_quirks: AllowQuirks)
|
||||||
-> Result<LengthOrPercentage, ()>
|
-> Result<LengthOrPercentage, ParseError<'i>>
|
||||||
{
|
{
|
||||||
match try!(input.next()) {
|
let token = try!(input.next());
|
||||||
|
match token {
|
||||||
Token::Dimension(ref value, ref unit) if num_context.is_ok(value.value) =>
|
Token::Dimension(ref value, ref unit) if num_context.is_ok(value.value) =>
|
||||||
NoCalcLength::parse_dimension(context, value.value, unit).map(LengthOrPercentage::Length),
|
NoCalcLength::parse_dimension(context, value.value, unit).map(LengthOrPercentage::Length),
|
||||||
Token::Percentage(ref value) if num_context.is_ok(value.unit_value) =>
|
Token::Percentage(ref value) if num_context.is_ok(value.unit_value) =>
|
||||||
Ok(LengthOrPercentage::Percentage(Percentage(value.unit_value))),
|
return Ok(LengthOrPercentage::Percentage(Percentage(value.unit_value))),
|
||||||
Token::Number(value) if num_context.is_ok(value.value) => {
|
Token::Number(value) if num_context.is_ok(value.value) => {
|
||||||
if value.value != 0. &&
|
if value.value != 0. &&
|
||||||
!context.parsing_mode.allows_unitless_lengths() &&
|
!context.parsing_mode.allows_unitless_lengths() &&
|
||||||
!allow_quirks.allowed(context.quirks_mode) {
|
!allow_quirks.allowed(context.quirks_mode) {
|
||||||
return Err(())
|
Err(())
|
||||||
|
} else {
|
||||||
|
return Ok(LengthOrPercentage::Length(NoCalcLength::from_px(value.value)))
|
||||||
}
|
}
|
||||||
Ok(LengthOrPercentage::Length(NoCalcLength::from_px(value.value)))
|
|
||||||
}
|
}
|
||||||
Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => {
|
Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => {
|
||||||
let calc = try!(input.parse_nested_block(|i| {
|
let calc = try!(input.parse_nested_block(|i| {
|
||||||
CalcNode::parse_length_or_percentage(context, i, num_context)
|
CalcNode::parse_length_or_percentage(context, i, num_context)
|
||||||
}));
|
}));
|
||||||
Ok(LengthOrPercentage::Calc(Box::new(calc)))
|
return Ok(LengthOrPercentage::Calc(Box::new(calc)))
|
||||||
},
|
},
|
||||||
_ => Err(())
|
_ => Err(())
|
||||||
}
|
}.map_err(|()| BasicParseError::UnexpectedToken(token).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a non-negative length.
|
/// Parse a non-negative length.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn parse_non_negative(context: &ParserContext, input: &mut Parser) -> Result<LengthOrPercentage, ()> {
|
pub fn parse_non_negative<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<LengthOrPercentage, ParseError<'i>> {
|
||||||
Self::parse_non_negative_quirky(context, input, AllowQuirks::No)
|
Self::parse_non_negative_quirky(context, input, AllowQuirks::No)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a non-negative length, with quirks.
|
/// Parse a non-negative length, with quirks.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn parse_non_negative_quirky(context: &ParserContext,
|
pub fn parse_non_negative_quirky<'i, 't>(context: &ParserContext,
|
||||||
input: &mut Parser,
|
input: &mut Parser<'i, 't>,
|
||||||
allow_quirks: AllowQuirks)
|
allow_quirks: AllowQuirks)
|
||||||
-> Result<LengthOrPercentage, ()> {
|
-> Result<LengthOrPercentage, ParseError<'i>> {
|
||||||
Self::parse_internal(context, input, AllowedLengthType::NonNegative, allow_quirks)
|
Self::parse_internal(context, input, AllowedLengthType::NonNegative, allow_quirks)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a length, treating dimensionless numbers as pixels
|
/// Parse a length, treating dimensionless numbers as pixels
|
||||||
///
|
///
|
||||||
/// https://www.w3.org/TR/SVG2/types.html#presentation-attribute-css-value
|
/// https://www.w3.org/TR/SVG2/types.html#presentation-attribute-css-value
|
||||||
pub fn parse_numbers_are_pixels(context: &ParserContext, input: &mut Parser) -> Result<LengthOrPercentage, ()> {
|
pub fn parse_numbers_are_pixels<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<LengthOrPercentage, ParseError<'i>> {
|
||||||
if let Ok(lop) = input.try(|i| Self::parse(context, i)) {
|
if let Ok(lop) = input.try(|i| Self::parse(context, i)) {
|
||||||
return Ok(lop)
|
return Ok(lop)
|
||||||
}
|
}
|
||||||
|
@ -849,9 +858,9 @@ impl LengthOrPercentage {
|
||||||
/// Parse a non-negative length, treating dimensionless numbers as pixels
|
/// Parse a non-negative length, treating dimensionless numbers as pixels
|
||||||
///
|
///
|
||||||
/// This is nonstandard behavior used by Firefox for SVG
|
/// This is nonstandard behavior used by Firefox for SVG
|
||||||
pub fn parse_numbers_are_pixels_non_negative(context: &ParserContext,
|
pub fn parse_numbers_are_pixels_non_negative<'i, 't>(context: &ParserContext,
|
||||||
input: &mut Parser)
|
input: &mut Parser<'i, 't>)
|
||||||
-> Result<LengthOrPercentage, ()> {
|
-> Result<LengthOrPercentage, ParseError<'i>> {
|
||||||
if let Ok(lop) = input.try(|i| Self::parse_non_negative(context, i)) {
|
if let Ok(lop) = input.try(|i| Self::parse_non_negative(context, i)) {
|
||||||
return Ok(lop)
|
return Ok(lop)
|
||||||
}
|
}
|
||||||
|
@ -862,7 +871,7 @@ impl LengthOrPercentage {
|
||||||
if num >= 0. {
|
if num >= 0. {
|
||||||
Ok(LengthOrPercentage::Length(NoCalcLength::Absolute(AbsoluteLength::Px(num))))
|
Ok(LengthOrPercentage::Length(NoCalcLength::Absolute(AbsoluteLength::Px(num))))
|
||||||
} else {
|
} else {
|
||||||
Err(())
|
Err(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -877,7 +886,7 @@ impl LengthOrPercentage {
|
||||||
|
|
||||||
impl Parse for LengthOrPercentage {
|
impl Parse for LengthOrPercentage {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
Self::parse_quirky(context, input, AllowQuirks::No)
|
Self::parse_quirky(context, input, AllowQuirks::No)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -886,9 +895,9 @@ impl LengthOrPercentage {
|
||||||
/// Parses a length or a percentage, allowing the unitless length quirk.
|
/// Parses a length or a percentage, allowing the unitless length quirk.
|
||||||
/// https://quirks.spec.whatwg.org/#the-unitless-length-quirk
|
/// https://quirks.spec.whatwg.org/#the-unitless-length-quirk
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn parse_quirky(context: &ParserContext,
|
pub fn parse_quirky<'i, 't>(context: &ParserContext,
|
||||||
input: &mut Parser,
|
input: &mut Parser<'i, 't>,
|
||||||
allow_quirks: AllowQuirks) -> Result<Self, ()> {
|
allow_quirks: AllowQuirks) -> Result<Self, ParseError<'i>> {
|
||||||
Self::parse_internal(context, input, AllowedLengthType::All, allow_quirks)
|
Self::parse_internal(context, input, AllowedLengthType::All, allow_quirks)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -919,12 +928,13 @@ impl From<Percentage> for LengthOrPercentageOrAuto {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LengthOrPercentageOrAuto {
|
impl LengthOrPercentageOrAuto {
|
||||||
fn parse_internal(context: &ParserContext,
|
fn parse_internal<'i, 't>(context: &ParserContext,
|
||||||
input: &mut Parser,
|
input: &mut Parser<'i, 't>,
|
||||||
num_context: AllowedLengthType,
|
num_context: AllowedLengthType,
|
||||||
allow_quirks: AllowQuirks)
|
allow_quirks: AllowQuirks)
|
||||||
-> Result<Self, ()> {
|
-> Result<Self, ParseError<'i>> {
|
||||||
match try!(input.next()) {
|
let token = try!(input.next());
|
||||||
|
match token {
|
||||||
Token::Dimension(ref value, ref unit) if num_context.is_ok(value.value) =>
|
Token::Dimension(ref value, ref unit) if num_context.is_ok(value.value) =>
|
||||||
NoCalcLength::parse_dimension(context, value.value, unit).map(LengthOrPercentageOrAuto::Length),
|
NoCalcLength::parse_dimension(context, value.value, unit).map(LengthOrPercentageOrAuto::Length),
|
||||||
Token::Percentage(ref value) if num_context.is_ok(value.unit_value) =>
|
Token::Percentage(ref value) if num_context.is_ok(value.unit_value) =>
|
||||||
|
@ -933,7 +943,7 @@ impl LengthOrPercentageOrAuto {
|
||||||
if value.value != 0. &&
|
if value.value != 0. &&
|
||||||
!context.parsing_mode.allows_unitless_lengths() &&
|
!context.parsing_mode.allows_unitless_lengths() &&
|
||||||
!allow_quirks.allowed(context.quirks_mode) {
|
!allow_quirks.allowed(context.quirks_mode) {
|
||||||
return Err(())
|
return Err(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
Ok(LengthOrPercentageOrAuto::Length(
|
Ok(LengthOrPercentageOrAuto::Length(
|
||||||
NoCalcLength::Absolute(AbsoluteLength::Px(value.value))
|
NoCalcLength::Absolute(AbsoluteLength::Px(value.value))
|
||||||
|
@ -948,21 +958,22 @@ impl LengthOrPercentageOrAuto {
|
||||||
Ok(LengthOrPercentageOrAuto::Calc(Box::new(calc)))
|
Ok(LengthOrPercentageOrAuto::Calc(Box::new(calc)))
|
||||||
},
|
},
|
||||||
_ => Err(())
|
_ => Err(())
|
||||||
}
|
}.map_err(|()| BasicParseError::UnexpectedToken(token).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a non-negative length, percentage, or auto.
|
/// Parse a non-negative length, percentage, or auto.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn parse_non_negative(context: &ParserContext, input: &mut Parser) -> Result<LengthOrPercentageOrAuto, ()> {
|
pub fn parse_non_negative<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<LengthOrPercentageOrAuto, ParseError<'i>> {
|
||||||
Self::parse_non_negative_quirky(context, input, AllowQuirks::No)
|
Self::parse_non_negative_quirky(context, input, AllowQuirks::No)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a non-negative length, percentage, or auto.
|
/// Parse a non-negative length, percentage, or auto.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn parse_non_negative_quirky(context: &ParserContext,
|
pub fn parse_non_negative_quirky<'i, 't>(context: &ParserContext,
|
||||||
input: &mut Parser,
|
input: &mut Parser<'i, 't>,
|
||||||
allow_quirks: AllowQuirks)
|
allow_quirks: AllowQuirks)
|
||||||
-> Result<Self, ()> {
|
-> Result<Self, ParseError<'i>> {
|
||||||
Self::parse_internal(context, input, AllowedLengthType::NonNegative, allow_quirks)
|
Self::parse_internal(context, input, AllowedLengthType::NonNegative, allow_quirks)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -984,7 +995,7 @@ impl LengthOrPercentageOrAuto {
|
||||||
|
|
||||||
impl Parse for LengthOrPercentageOrAuto {
|
impl Parse for LengthOrPercentageOrAuto {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
Self::parse_quirky(context, input, AllowQuirks::No)
|
Self::parse_quirky(context, input, AllowQuirks::No)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -992,10 +1003,10 @@ impl Parse for LengthOrPercentageOrAuto {
|
||||||
impl LengthOrPercentageOrAuto {
|
impl LengthOrPercentageOrAuto {
|
||||||
/// Parses, with quirks.
|
/// Parses, with quirks.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn parse_quirky(context: &ParserContext,
|
pub fn parse_quirky<'i, 't>(context: &ParserContext,
|
||||||
input: &mut Parser,
|
input: &mut Parser<'i, 't>,
|
||||||
allow_quirks: AllowQuirks)
|
allow_quirks: AllowQuirks)
|
||||||
-> Result<Self, ()> {
|
-> Result<Self, ParseError<'i>> {
|
||||||
Self::parse_internal(context, input, AllowedLengthType::All, allow_quirks)
|
Self::parse_internal(context, input, AllowedLengthType::All, allow_quirks)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1012,13 +1023,14 @@ pub enum LengthOrPercentageOrNone {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LengthOrPercentageOrNone {
|
impl LengthOrPercentageOrNone {
|
||||||
fn parse_internal(context: &ParserContext,
|
fn parse_internal<'i, 't>(context: &ParserContext,
|
||||||
input: &mut Parser,
|
input: &mut Parser<'i, 't>,
|
||||||
num_context: AllowedLengthType,
|
num_context: AllowedLengthType,
|
||||||
allow_quirks: AllowQuirks)
|
allow_quirks: AllowQuirks)
|
||||||
-> Result<LengthOrPercentageOrNone, ()>
|
-> Result<LengthOrPercentageOrNone, ParseError<'i>>
|
||||||
{
|
{
|
||||||
match try!(input.next()) {
|
let token = try!(input.next());
|
||||||
|
match token {
|
||||||
Token::Dimension(ref value, ref unit) if num_context.is_ok(value.value) =>
|
Token::Dimension(ref value, ref unit) if num_context.is_ok(value.value) =>
|
||||||
NoCalcLength::parse_dimension(context, value.value, unit).map(LengthOrPercentageOrNone::Length),
|
NoCalcLength::parse_dimension(context, value.value, unit).map(LengthOrPercentageOrNone::Length),
|
||||||
Token::Percentage(ref value) if num_context.is_ok(value.unit_value) =>
|
Token::Percentage(ref value) if num_context.is_ok(value.unit_value) =>
|
||||||
|
@ -1026,7 +1038,7 @@ impl LengthOrPercentageOrNone {
|
||||||
Token::Number(value) if num_context.is_ok(value.value) => {
|
Token::Number(value) if num_context.is_ok(value.value) => {
|
||||||
if value.value != 0. && !context.parsing_mode.allows_unitless_lengths() &&
|
if value.value != 0. && !context.parsing_mode.allows_unitless_lengths() &&
|
||||||
!allow_quirks.allowed(context.quirks_mode) {
|
!allow_quirks.allowed(context.quirks_mode) {
|
||||||
return Err(())
|
return Err(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
Ok(LengthOrPercentageOrNone::Length(
|
Ok(LengthOrPercentageOrNone::Length(
|
||||||
NoCalcLength::Absolute(AbsoluteLength::Px(value.value))
|
NoCalcLength::Absolute(AbsoluteLength::Px(value.value))
|
||||||
|
@ -1041,28 +1053,29 @@ impl LengthOrPercentageOrNone {
|
||||||
Token::Ident(ref value) if value.eq_ignore_ascii_case("none") =>
|
Token::Ident(ref value) if value.eq_ignore_ascii_case("none") =>
|
||||||
Ok(LengthOrPercentageOrNone::None),
|
Ok(LengthOrPercentageOrNone::None),
|
||||||
_ => Err(())
|
_ => Err(())
|
||||||
}
|
}.map_err(|()| BasicParseError::UnexpectedToken(token).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a non-negative LengthOrPercentageOrNone.
|
/// Parse a non-negative LengthOrPercentageOrNone.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn parse_non_negative(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
pub fn parse_non_negative<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<Self, ParseError<'i>> {
|
||||||
Self::parse_non_negative_quirky(context, input, AllowQuirks::No)
|
Self::parse_non_negative_quirky(context, input, AllowQuirks::No)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a non-negative LengthOrPercentageOrNone, with quirks.
|
/// Parse a non-negative LengthOrPercentageOrNone, with quirks.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn parse_non_negative_quirky(context: &ParserContext,
|
pub fn parse_non_negative_quirky<'i, 't>(context: &ParserContext,
|
||||||
input: &mut Parser,
|
input: &mut Parser<'i, 't>,
|
||||||
allow_quirks: AllowQuirks)
|
allow_quirks: AllowQuirks)
|
||||||
-> Result<Self, ()> {
|
-> Result<Self, ParseError<'i>> {
|
||||||
Self::parse_internal(context, input, AllowedLengthType::NonNegative, allow_quirks)
|
Self::parse_internal(context, input, AllowedLengthType::NonNegative, allow_quirks)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for LengthOrPercentageOrNone {
|
impl Parse for LengthOrPercentageOrNone {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
Self::parse_internal(context, input, AllowedLengthType::All, AllowQuirks::No)
|
Self::parse_internal(context, input, AllowedLengthType::All, AllowQuirks::No)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1095,9 +1108,11 @@ pub enum LengthOrPercentageOrAutoOrContent {
|
||||||
|
|
||||||
impl LengthOrPercentageOrAutoOrContent {
|
impl LengthOrPercentageOrAutoOrContent {
|
||||||
/// Parse a non-negative LengthOrPercentageOrAutoOrContent.
|
/// Parse a non-negative LengthOrPercentageOrAutoOrContent.
|
||||||
pub fn parse_non_negative(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
pub fn parse_non_negative<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<Self, ParseError<'i>> {
|
||||||
let num_context = AllowedLengthType::NonNegative;
|
let num_context = AllowedLengthType::NonNegative;
|
||||||
match try!(input.next()) {
|
let token = try!(input.next());
|
||||||
|
match token {
|
||||||
Token::Dimension(ref value, ref unit) if num_context.is_ok(value.value) =>
|
Token::Dimension(ref value, ref unit) if num_context.is_ok(value.value) =>
|
||||||
NoCalcLength::parse_dimension(context, value.value, unit)
|
NoCalcLength::parse_dimension(context, value.value, unit)
|
||||||
.map(LengthOrPercentageOrAutoOrContent::Length),
|
.map(LengthOrPercentageOrAutoOrContent::Length),
|
||||||
|
@ -1116,7 +1131,7 @@ impl LengthOrPercentageOrAutoOrContent {
|
||||||
Ok(LengthOrPercentageOrAutoOrContent::Calc(Box::new(calc)))
|
Ok(LengthOrPercentageOrAutoOrContent::Calc(Box::new(calc)))
|
||||||
},
|
},
|
||||||
_ => Err(())
|
_ => Err(())
|
||||||
}
|
}.map_err(|()| BasicParseError::UnexpectedToken(token).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the `auto` value.
|
/// Returns the `auto` value.
|
||||||
|
@ -1140,7 +1155,8 @@ pub type LengthOrNumber = Either<Length, Number>;
|
||||||
|
|
||||||
impl LengthOrNumber {
|
impl LengthOrNumber {
|
||||||
/// Parse a non-negative LengthOrNumber.
|
/// Parse a non-negative LengthOrNumber.
|
||||||
pub fn parse_non_negative(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
pub fn parse_non_negative<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<Self, ParseError<'i>> {
|
||||||
// We try to parse as a Number first because, for cases like
|
// We try to parse as a Number first because, for cases like
|
||||||
// LengthOrNumber, we want "0" to be parsed as a plain Number rather
|
// LengthOrNumber, we want "0" to be parsed as a plain Number rather
|
||||||
// than a Length (0px); this matches the behaviour of all major browsers
|
// than a Length (0px); this matches the behaviour of all major browsers
|
||||||
|
@ -1170,18 +1186,18 @@ pub enum MozLength {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for MozLength {
|
impl Parse for MozLength {
|
||||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
MozLength::parse_quirky(context, input, AllowQuirks::No)
|
MozLength::parse_quirky(context, input, AllowQuirks::No)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MozLength {
|
impl MozLength {
|
||||||
/// Parses, with quirks.
|
/// Parses, with quirks.
|
||||||
pub fn parse_quirky(context: &ParserContext,
|
pub fn parse_quirky<'i, 't>(context: &ParserContext,
|
||||||
input: &mut Parser,
|
input: &mut Parser<'i, 't>,
|
||||||
allow_quirks: AllowQuirks) -> Result<Self, ()> {
|
allow_quirks: AllowQuirks) -> Result<Self, ParseError<'i>> {
|
||||||
input.try(ExtremumLength::parse).map(MozLength::ExtremumLength)
|
input.try(ExtremumLength::parse).map(MozLength::ExtremumLength)
|
||||||
.or_else(|()| input.try(|i| LengthOrPercentageOrAuto::parse_non_negative_quirky(context, i, allow_quirks))
|
.or_else(|_| input.try(|i| LengthOrPercentageOrAuto::parse_non_negative_quirky(context, i, allow_quirks))
|
||||||
.map(MozLength::LengthOrPercentageOrAuto))
|
.map(MozLength::LengthOrPercentageOrAuto))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1196,18 +1212,18 @@ pub enum MaxLength {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for MaxLength {
|
impl Parse for MaxLength {
|
||||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
MaxLength::parse_quirky(context, input, AllowQuirks::No)
|
MaxLength::parse_quirky(context, input, AllowQuirks::No)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MaxLength {
|
impl MaxLength {
|
||||||
/// Parses, with quirks.
|
/// Parses, with quirks.
|
||||||
pub fn parse_quirky(context: &ParserContext,
|
pub fn parse_quirky<'i, 't>(context: &ParserContext,
|
||||||
input: &mut Parser,
|
input: &mut Parser<'i, 't>,
|
||||||
allow_quirks: AllowQuirks) -> Result<Self, ()> {
|
allow_quirks: AllowQuirks) -> Result<Self, ParseError<'i>> {
|
||||||
input.try(ExtremumLength::parse).map(MaxLength::ExtremumLength)
|
input.try(ExtremumLength::parse).map(MaxLength::ExtremumLength)
|
||||||
.or_else(|()| input.try(|i| LengthOrPercentageOrNone::parse_non_negative_quirky(context, i, allow_quirks))
|
.or_else(|_| input.try(|i| LengthOrPercentageOrNone::parse_non_negative_quirky(context, i, allow_quirks))
|
||||||
.map(MaxLength::LengthOrPercentageOrNone))
|
.map(MaxLength::LengthOrPercentageOrNone))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,14 +8,14 @@
|
||||||
|
|
||||||
use Namespace;
|
use Namespace;
|
||||||
use context::QuirksMode;
|
use context::QuirksMode;
|
||||||
use cssparser::{Parser, Token, serialize_identifier};
|
use cssparser::{Parser, Token, serialize_identifier, BasicParseError};
|
||||||
use parser::{ParserContext, Parse};
|
use parser::{ParserContext, Parse};
|
||||||
use self::grid::TrackSizeOrRepeat;
|
use self::grid::TrackSizeOrRepeat;
|
||||||
use self::url::SpecifiedUrl;
|
use self::url::SpecifiedUrl;
|
||||||
use std::ascii::AsciiExt;
|
use std::ascii::AsciiExt;
|
||||||
use std::f32;
|
use std::f32;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use style_traits::ToCss;
|
use style_traits::{ToCss, ParseError, StyleParseError};
|
||||||
use style_traits::values::specified::AllowedNumericType;
|
use style_traits::values::specified::AllowedNumericType;
|
||||||
use super::{Auto, CSSFloat, CSSInteger, Either, None_};
|
use super::{Auto, CSSFloat, CSSInteger, Either, None_};
|
||||||
use super::computed::{self, Context};
|
use super::computed::{self, Context};
|
||||||
|
@ -68,6 +68,7 @@ pub mod transform;
|
||||||
pub mod url {
|
pub mod url {
|
||||||
use cssparser::Parser;
|
use cssparser::Parser;
|
||||||
use parser::{Parse, ParserContext};
|
use parser::{Parse, ParserContext};
|
||||||
|
use style_traits::ParseError;
|
||||||
use values::computed::ComputedValueAsSpecified;
|
use values::computed::ComputedValueAsSpecified;
|
||||||
|
|
||||||
#[cfg(feature = "servo")]
|
#[cfg(feature = "servo")]
|
||||||
|
@ -76,7 +77,7 @@ pub use ::servo::url::*;
|
||||||
pub use ::gecko::url::*;
|
pub use ::gecko::url::*;
|
||||||
|
|
||||||
impl Parse for SpecifiedUrl {
|
impl Parse for SpecifiedUrl {
|
||||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
let url = try!(input.expect_url());
|
let url = try!(input.expect_url());
|
||||||
Self::parse_from_string(url, context)
|
Self::parse_from_string(url, context)
|
||||||
}
|
}
|
||||||
|
@ -91,9 +92,10 @@ no_viewport_percentage!(SpecifiedUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse an `<integer>` value, handling `calc()` correctly.
|
/// Parse an `<integer>` value, handling `calc()` correctly.
|
||||||
pub fn parse_integer(context: &ParserContext, input: &mut Parser) -> Result<Integer, ()> {
|
pub fn parse_integer<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<Integer, ParseError<'i>> {
|
||||||
match try!(input.next()) {
|
match try!(input.next()) {
|
||||||
Token::Number(ref value) => value.int_value.ok_or(()).map(Integer::new),
|
Token::Number(ref value) => value.int_value.ok_or(StyleParseError::UnspecifiedError.into()).map(Integer::new),
|
||||||
Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => {
|
Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => {
|
||||||
let result = try!(input.parse_nested_block(|i| {
|
let result = try!(input.parse_nested_block(|i| {
|
||||||
CalcNode::parse_integer(context, i)
|
CalcNode::parse_integer(context, i)
|
||||||
|
@ -101,21 +103,22 @@ pub fn parse_integer(context: &ParserContext, input: &mut Parser) -> Result<Inte
|
||||||
|
|
||||||
Ok(Integer::from_calc(result))
|
Ok(Integer::from_calc(result))
|
||||||
}
|
}
|
||||||
_ => Err(())
|
t => Err(BasicParseError::UnexpectedToken(t).into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a `<number>` value, handling `calc()` correctly, and without length
|
/// Parse a `<number>` value, handling `calc()` correctly, and without length
|
||||||
/// limitations.
|
/// limitations.
|
||||||
pub fn parse_number(context: &ParserContext, input: &mut Parser) -> Result<Number, ()> {
|
pub fn parse_number<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<Number, ParseError<'i>> {
|
||||||
parse_number_with_clamping_mode(context, input, AllowedNumericType::All)
|
parse_number_with_clamping_mode(context, input, AllowedNumericType::All)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a `<number>` value, with a given clamping mode.
|
/// Parse a `<number>` value, with a given clamping mode.
|
||||||
pub fn parse_number_with_clamping_mode(context: &ParserContext,
|
pub fn parse_number_with_clamping_mode<'i, 't>(context: &ParserContext,
|
||||||
input: &mut Parser,
|
input: &mut Parser<'i, 't>,
|
||||||
clamping_mode: AllowedNumericType)
|
clamping_mode: AllowedNumericType)
|
||||||
-> Result<Number, ()> {
|
-> Result<Number, ParseError<'i>> {
|
||||||
match try!(input.next()) {
|
match try!(input.next()) {
|
||||||
Token::Number(ref value) if clamping_mode.is_ok(value.value) => {
|
Token::Number(ref value) if clamping_mode.is_ok(value.value) => {
|
||||||
Ok(Number {
|
Ok(Number {
|
||||||
|
@ -133,7 +136,7 @@ pub fn parse_number_with_clamping_mode(context: &ParserContext,
|
||||||
calc_clamping_mode: Some(clamping_mode),
|
calc_clamping_mode: Some(clamping_mode),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
_ => Err(())
|
t => Err(BasicParseError::UnexpectedToken(t).into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -220,18 +223,19 @@ impl Angle {
|
||||||
|
|
||||||
impl Parse for Angle {
|
impl Parse for Angle {
|
||||||
/// Parses an angle according to CSS-VALUES § 6.1.
|
/// Parses an angle according to CSS-VALUES § 6.1.
|
||||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
match try!(input.next()) {
|
let token = try!(input.next());
|
||||||
|
match token {
|
||||||
Token::Dimension(ref value, ref unit) => {
|
Token::Dimension(ref value, ref unit) => {
|
||||||
Angle::parse_dimension(value.value,
|
Angle::parse_dimension(value.value,
|
||||||
unit,
|
unit,
|
||||||
/* from_calc = */ false)
|
/* from_calc = */ false)
|
||||||
}
|
}
|
||||||
Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => {
|
Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => {
|
||||||
input.parse_nested_block(|i| CalcNode::parse_angle(context, i))
|
return input.parse_nested_block(|i| CalcNode::parse_angle(context, i))
|
||||||
}
|
}
|
||||||
_ => Err(())
|
_ => Err(())
|
||||||
}
|
}.map_err(|()| BasicParseError::UnexpectedToken(token).into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -260,8 +264,10 @@ impl Angle {
|
||||||
///
|
///
|
||||||
/// We can remove this and get back to the unified version Angle::parse once
|
/// We can remove this and get back to the unified version Angle::parse once
|
||||||
/// https://github.com/w3c/csswg-drafts/issues/1162 is resolved.
|
/// https://github.com/w3c/csswg-drafts/issues/1162 is resolved.
|
||||||
pub fn parse_with_unitless(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
pub fn parse_with_unitless<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
match try!(input.next()) {
|
-> Result<Self, ParseError<'i>> {
|
||||||
|
let token = try!(input.next());
|
||||||
|
match token {
|
||||||
Token::Dimension(ref value, ref unit) => {
|
Token::Dimension(ref value, ref unit) => {
|
||||||
Angle::parse_dimension(value.value,
|
Angle::parse_dimension(value.value,
|
||||||
unit,
|
unit,
|
||||||
|
@ -269,10 +275,10 @@ impl Angle {
|
||||||
}
|
}
|
||||||
Token::Number(ref value) if value.value == 0. => Ok(Angle::zero()),
|
Token::Number(ref value) if value.value == 0. => Ok(Angle::zero()),
|
||||||
Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => {
|
Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => {
|
||||||
input.parse_nested_block(|i| CalcNode::parse_angle(context, i))
|
return input.parse_nested_block(|i| CalcNode::parse_angle(context, i))
|
||||||
}
|
}
|
||||||
_ => Err(())
|
_ => Err(())
|
||||||
}
|
}.map_err(|()| BasicParseError::UnexpectedToken(token).into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -337,7 +343,7 @@ impl Time {
|
||||||
let seconds = match_ignore_ascii_case! { unit,
|
let seconds = match_ignore_ascii_case! { unit,
|
||||||
"s" => value,
|
"s" => value,
|
||||||
"ms" => value / 1000.0,
|
"ms" => value / 1000.0,
|
||||||
_ => return Err(()),
|
_ => return Err(())
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(Time {
|
Ok(Time {
|
||||||
|
@ -354,25 +360,29 @@ impl Time {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_with_clamping_mode(context: &ParserContext,
|
fn parse_with_clamping_mode<'i, 't>(context: &ParserContext,
|
||||||
input: &mut Parser,
|
input: &mut Parser<'i, 't>,
|
||||||
clamping_mode: AllowedNumericType) -> Result<Self, ()> {
|
clamping_mode: AllowedNumericType)
|
||||||
|
-> Result<Self, ParseError<'i>> {
|
||||||
match input.next() {
|
match input.next() {
|
||||||
Ok(Token::Dimension(ref value, ref unit)) if clamping_mode.is_ok(value.value) => {
|
Ok(Token::Dimension(ref value, ref unit)) if clamping_mode.is_ok(value.value) => {
|
||||||
Time::parse_dimension(value.value, &unit, /* from_calc = */ false)
|
Time::parse_dimension(value.value, &unit, /* from_calc = */ false)
|
||||||
|
.map_err(|()| StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
Ok(Token::Function(ref name)) if name.eq_ignore_ascii_case("calc") => {
|
Ok(Token::Function(ref name)) if name.eq_ignore_ascii_case("calc") => {
|
||||||
match input.parse_nested_block(|i| CalcNode::parse_time(context, i)) {
|
match input.parse_nested_block(|i| CalcNode::parse_time(context, i)) {
|
||||||
Ok(time) if clamping_mode.is_ok(time.seconds) => Ok(time),
|
Ok(time) if clamping_mode.is_ok(time.seconds) => Ok(time),
|
||||||
_ => Err(()),
|
_ => Err(StyleParseError::UnspecifiedError.into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => Err(())
|
Ok(t) => Err(BasicParseError::UnexpectedToken(t).into()),
|
||||||
|
Err(e) => Err(e.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse <time> that values are non-negative.
|
/// Parse <time> that values are non-negative.
|
||||||
pub fn parse_non_negative(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
pub fn parse_non_negative<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<Self, ParseError<'i>> {
|
||||||
Self::parse_with_clamping_mode(context, input, AllowedNumericType::NonNegative)
|
Self::parse_with_clamping_mode(context, input, AllowedNumericType::NonNegative)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -393,7 +403,7 @@ impl ToComputedValue for Time {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for Time {
|
impl Parse for Time {
|
||||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
Self::parse_with_clamping_mode(context, input, AllowedNumericType::All)
|
Self::parse_with_clamping_mode(context, input, AllowedNumericType::All)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -425,7 +435,7 @@ pub struct Number {
|
||||||
no_viewport_percentage!(Number);
|
no_viewport_percentage!(Number);
|
||||||
|
|
||||||
impl Parse for Number {
|
impl Parse for Number {
|
||||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
parse_number(context, input)
|
parse_number(context, input)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -445,7 +455,8 @@ impl Number {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(missing_docs)]
|
#[allow(missing_docs)]
|
||||||
pub fn parse_non_negative(context: &ParserContext, input: &mut Parser) -> Result<Number, ()> {
|
pub fn parse_non_negative<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<Number, ParseError<'i>> {
|
||||||
if context.parsing_mode.allows_all_numeric_values() {
|
if context.parsing_mode.allows_all_numeric_values() {
|
||||||
parse_number(context, input)
|
parse_number(context, input)
|
||||||
} else {
|
} else {
|
||||||
|
@ -454,7 +465,8 @@ impl Number {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(missing_docs)]
|
#[allow(missing_docs)]
|
||||||
pub fn parse_at_least_one(context: &ParserContext, input: &mut Parser) -> Result<Number, ()> {
|
pub fn parse_at_least_one<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<Number, ParseError<'i>> {
|
||||||
if context.parsing_mode.allows_all_numeric_values() {
|
if context.parsing_mode.allows_all_numeric_values() {
|
||||||
parse_number(context, input)
|
parse_number(context, input)
|
||||||
} else {
|
} else {
|
||||||
|
@ -506,10 +518,10 @@ pub enum NumberOrPercentage {
|
||||||
no_viewport_percentage!(NumberOrPercentage);
|
no_viewport_percentage!(NumberOrPercentage);
|
||||||
|
|
||||||
impl NumberOrPercentage {
|
impl NumberOrPercentage {
|
||||||
fn parse_with_clamping_mode(context: &ParserContext,
|
fn parse_with_clamping_mode<'i, 't>(context: &ParserContext,
|
||||||
input: &mut Parser,
|
input: &mut Parser<'i, 't>,
|
||||||
type_: AllowedNumericType)
|
type_: AllowedNumericType)
|
||||||
-> Result<Self, ()> {
|
-> Result<Self, ParseError<'i>> {
|
||||||
if let Ok(per) = input.try(|i| Percentage::parse_with_clamping_mode(i, type_)) {
|
if let Ok(per) = input.try(|i| Percentage::parse_with_clamping_mode(i, type_)) {
|
||||||
return Ok(NumberOrPercentage::Percentage(per));
|
return Ok(NumberOrPercentage::Percentage(per));
|
||||||
}
|
}
|
||||||
|
@ -518,13 +530,14 @@ impl NumberOrPercentage {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a non-negative number or percentage.
|
/// Parse a non-negative number or percentage.
|
||||||
pub fn parse_non_negative(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
pub fn parse_non_negative<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<Self, ParseError<'i>> {
|
||||||
Self::parse_with_clamping_mode(context, input, AllowedNumericType::NonNegative)
|
Self::parse_with_clamping_mode(context, input, AllowedNumericType::NonNegative)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for NumberOrPercentage {
|
impl Parse for NumberOrPercentage {
|
||||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
Self::parse_with_clamping_mode(context, input, AllowedNumericType::All)
|
Self::parse_with_clamping_mode(context, input, AllowedNumericType::All)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -537,7 +550,7 @@ pub struct Opacity(Number);
|
||||||
no_viewport_percentage!(Opacity);
|
no_viewport_percentage!(Opacity);
|
||||||
|
|
||||||
impl Parse for Opacity {
|
impl Parse for Opacity {
|
||||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
parse_number(context, input).map(Opacity)
|
parse_number(context, input).map(Opacity)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -590,27 +603,31 @@ impl Integer {
|
||||||
no_viewport_percentage!(Integer);
|
no_viewport_percentage!(Integer);
|
||||||
|
|
||||||
impl Parse for Integer {
|
impl Parse for Integer {
|
||||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
parse_integer(context, input)
|
parse_integer(context, input)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Integer {
|
impl Integer {
|
||||||
#[allow(missing_docs)]
|
#[allow(missing_docs)]
|
||||||
pub fn parse_with_minimum(context: &ParserContext, input: &mut Parser, min: i32) -> Result<Integer, ()> {
|
pub fn parse_with_minimum<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>, min: i32)
|
||||||
|
-> Result<Integer, ParseError<'i>> {
|
||||||
match parse_integer(context, input) {
|
match parse_integer(context, input) {
|
||||||
Ok(value) if value.value() >= min => Ok(value),
|
Ok(value) if value.value() >= min => Ok(value),
|
||||||
_ => Err(()),
|
Ok(_value) => Err(StyleParseError::UnspecifiedError.into()),
|
||||||
|
Err(e) => Err(e),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(missing_docs)]
|
#[allow(missing_docs)]
|
||||||
pub fn parse_non_negative(context: &ParserContext, input: &mut Parser) -> Result<Integer, ()> {
|
pub fn parse_non_negative<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<Integer, ParseError<'i>> {
|
||||||
Integer::parse_with_minimum(context, input, 0)
|
Integer::parse_with_minimum(context, input, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(missing_docs)]
|
#[allow(missing_docs)]
|
||||||
pub fn parse_positive(context: &ParserContext, input: &mut Parser) -> Result<Integer, ()> {
|
pub fn parse_positive<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<Integer, ParseError<'i>> {
|
||||||
Integer::parse_with_minimum(context, input, 1)
|
Integer::parse_with_minimum(context, input, 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -647,11 +664,11 @@ pub type IntegerOrAuto = Either<Integer, Auto>;
|
||||||
|
|
||||||
impl IntegerOrAuto {
|
impl IntegerOrAuto {
|
||||||
#[allow(missing_docs)]
|
#[allow(missing_docs)]
|
||||||
pub fn parse_positive(context: &ParserContext,
|
pub fn parse_positive<'i, 't>(context: &ParserContext,
|
||||||
input: &mut Parser)
|
input: &mut Parser<'i, 't>)
|
||||||
-> Result<IntegerOrAuto, ()> {
|
-> Result<IntegerOrAuto, ParseError<'i>> {
|
||||||
match IntegerOrAuto::parse(context, input) {
|
match IntegerOrAuto::parse(context, input) {
|
||||||
Ok(Either::First(integer)) if integer.value() <= 0 => Err(()),
|
Ok(Either::First(integer)) if integer.value() <= 0 => Err(StyleParseError::UnspecifiedError.into()),
|
||||||
result => result,
|
result => result,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -739,7 +756,10 @@ impl ToCss for Shadow {
|
||||||
impl Shadow {
|
impl Shadow {
|
||||||
// disable_spread_and_inset is for filter: drop-shadow(...)
|
// disable_spread_and_inset is for filter: drop-shadow(...)
|
||||||
#[allow(missing_docs)]
|
#[allow(missing_docs)]
|
||||||
pub fn parse(context: &ParserContext, input: &mut Parser, disable_spread_and_inset: bool) -> Result<Shadow, ()> {
|
pub fn parse<'i, 't>(context: &ParserContext,
|
||||||
|
input: &mut Parser<'i, 't>,
|
||||||
|
disable_spread_and_inset: bool)
|
||||||
|
-> Result<Shadow, ParseError<'i>> {
|
||||||
let mut lengths = [Length::zero(), Length::zero(), Length::zero(), Length::zero()];
|
let mut lengths = [Length::zero(), Length::zero(), Length::zero(), Length::zero()];
|
||||||
let mut lengths_parsed = false;
|
let mut lengths_parsed = false;
|
||||||
let mut color = None;
|
let mut color = None;
|
||||||
|
@ -779,7 +799,7 @@ impl Shadow {
|
||||||
|
|
||||||
// Lengths must be specified.
|
// Lengths must be specified.
|
||||||
if !lengths_parsed {
|
if !lengths_parsed {
|
||||||
return Err(())
|
return Err(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
debug_assert!(!disable_spread_and_inset || lengths[3] == Length::zero());
|
debug_assert!(!disable_spread_and_inset || lengths[3] == Length::zero());
|
||||||
|
@ -841,7 +861,8 @@ pub type LengthOrPercentageOrNumber = Either<Number, LengthOrPercentage>;
|
||||||
|
|
||||||
impl LengthOrPercentageOrNumber {
|
impl LengthOrPercentageOrNumber {
|
||||||
/// parse a <length-percentage> | <number> enforcing that the contents aren't negative
|
/// parse a <length-percentage> | <number> enforcing that the contents aren't negative
|
||||||
pub fn parse_non_negative(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
pub fn parse_non_negative<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<Self, ParseError<'i>> {
|
||||||
// NB: Parse numbers before Lengths so we are consistent about how to
|
// NB: Parse numbers before Lengths so we are consistent about how to
|
||||||
// recognize and serialize "0".
|
// recognize and serialize "0".
|
||||||
if let Ok(num) = input.try(|i| Number::parse_non_negative(context, i)) {
|
if let Ok(num) = input.try(|i| Number::parse_non_negative(context, i)) {
|
||||||
|
@ -928,19 +949,19 @@ impl ToComputedValue for ClipRect {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for ClipRect {
|
impl Parse for ClipRect {
|
||||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
Self::parse_quirky(context, input, AllowQuirks::No)
|
Self::parse_quirky(context, input, AllowQuirks::No)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ClipRect {
|
impl ClipRect {
|
||||||
/// Parses a rect(<top>, <left>, <bottom>, <right>), allowing quirks.
|
/// Parses a rect(<top>, <left>, <bottom>, <right>), allowing quirks.
|
||||||
pub fn parse_quirky(context: &ParserContext, input: &mut Parser,
|
pub fn parse_quirky<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>,
|
||||||
allow_quirks: AllowQuirks) -> Result<Self, ()> {
|
allow_quirks: AllowQuirks) -> Result<Self, ParseError<'i>> {
|
||||||
use values::specified::Length;
|
use values::specified::Length;
|
||||||
|
|
||||||
fn parse_argument(context: &ParserContext, input: &mut Parser,
|
fn parse_argument<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>,
|
||||||
allow_quirks: AllowQuirks) -> Result<Option<Length>, ()> {
|
allow_quirks: AllowQuirks) -> Result<Option<Length>, ParseError<'i>> {
|
||||||
if input.try(|input| input.expect_ident_matching("auto")).is_ok() {
|
if input.try(|input| input.expect_ident_matching("auto")).is_ok() {
|
||||||
Ok(None)
|
Ok(None)
|
||||||
} else {
|
} else {
|
||||||
|
@ -948,8 +969,9 @@ impl ClipRect {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !try!(input.expect_function()).eq_ignore_ascii_case("rect") {
|
let func = try!(input.expect_function());
|
||||||
return Err(())
|
if !func.eq_ignore_ascii_case("rect") {
|
||||||
|
return Err(StyleParseError::UnexpectedFunction(func).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
input.parse_nested_block(|input| {
|
input.parse_nested_block(|input| {
|
||||||
|
@ -984,8 +1006,8 @@ pub type ClipRectOrAuto = Either<ClipRect, Auto>;
|
||||||
|
|
||||||
impl ClipRectOrAuto {
|
impl ClipRectOrAuto {
|
||||||
/// Parses a ClipRect or Auto, allowing quirks.
|
/// Parses a ClipRect or Auto, allowing quirks.
|
||||||
pub fn parse_quirky(context: &ParserContext, input: &mut Parser,
|
pub fn parse_quirky<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>,
|
||||||
allow_quirks: AllowQuirks) -> Result<Self, ()> {
|
allow_quirks: AllowQuirks) -> Result<Self, ParseError<'i>> {
|
||||||
if let Ok(v) = input.try(|i| ClipRect::parse_quirky(context, i, allow_quirks)) {
|
if let Ok(v) = input.try(|i| ClipRect::parse_quirky(context, i, allow_quirks)) {
|
||||||
Ok(Either::First(v))
|
Ok(Either::First(v))
|
||||||
} else {
|
} else {
|
||||||
|
@ -1035,7 +1057,7 @@ pub struct Attr {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for Attr {
|
impl Parse for Attr {
|
||||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Attr, ()> {
|
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Attr, ParseError<'i>> {
|
||||||
input.expect_function_matching("attr")?;
|
input.expect_function_matching("attr")?;
|
||||||
input.parse_nested_block(|i| Attr::parse_function(context, i))
|
input.parse_nested_block(|i| Attr::parse_function(context, i))
|
||||||
}
|
}
|
||||||
|
@ -1068,25 +1090,28 @@ fn get_id_for_namespace(_: &Namespace, _: &ParserContext) -> Result<NamespaceId,
|
||||||
impl Attr {
|
impl Attr {
|
||||||
/// Parse contents of attr() assuming we have already parsed `attr` and are
|
/// Parse contents of attr() assuming we have already parsed `attr` and are
|
||||||
/// within a parse_nested_block()
|
/// within a parse_nested_block()
|
||||||
pub fn parse_function(context: &ParserContext, input: &mut Parser) -> Result<Attr, ()> {
|
pub fn parse_function<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<Attr, ParseError<'i>> {
|
||||||
// Syntax is `[namespace? `|`]? ident`
|
// Syntax is `[namespace? `|`]? ident`
|
||||||
// no spaces allowed
|
// no spaces allowed
|
||||||
let first = input.try(|i| i.expect_ident()).ok();
|
let first = input.try(|i| i.expect_ident()).ok();
|
||||||
if let Ok(token) = input.try(|i| i.next_including_whitespace()) {
|
if let Ok(token) = input.try(|i| i.next_including_whitespace()) {
|
||||||
match token {
|
match token {
|
||||||
Token::Delim('|') => {}
|
Token::Delim('|') => {}
|
||||||
_ => return Err(()),
|
t => return Err(BasicParseError::UnexpectedToken(t).into()),
|
||||||
}
|
}
|
||||||
// must be followed by an ident
|
// must be followed by an ident
|
||||||
let second_token = match input.next_including_whitespace()? {
|
let second_token = match input.next_including_whitespace()? {
|
||||||
Token::Ident(second) => second,
|
Token::Ident(second) => second,
|
||||||
_ => return Err(()),
|
t => return Err(BasicParseError::UnexpectedToken(t).into()),
|
||||||
};
|
};
|
||||||
|
|
||||||
let ns_with_id = if let Some(ns) = first {
|
let ns_with_id = if let Some(ns) = first {
|
||||||
let ns: Namespace = ns.into();
|
let ns: Namespace = ns.into();
|
||||||
let id = get_id_for_namespace(&ns, context)?;
|
let id: Result<_, ParseError> =
|
||||||
Some((ns, id))
|
get_id_for_namespace(&ns, context)
|
||||||
|
.map_err(|()| StyleParseError::UnspecifiedError.into());
|
||||||
|
Some((ns, id?))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
@ -1102,7 +1127,7 @@ impl Attr {
|
||||||
attribute: first.into_owned(),
|
attribute: first.into_owned(),
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
Err(())
|
Err(StyleParseError::UnspecifiedError.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
use cssparser::Parser;
|
use cssparser::Parser;
|
||||||
use parser::{Parse, ParserContext};
|
use parser::{Parse, ParserContext};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use style_traits::{HasViewportPercentage, ToCss};
|
use style_traits::{HasViewportPercentage, ToCss, ParseError};
|
||||||
use values::computed::{CalcLengthOrPercentage, LengthOrPercentage as ComputedLengthOrPercentage};
|
use values::computed::{CalcLengthOrPercentage, LengthOrPercentage as ComputedLengthOrPercentage};
|
||||||
use values::computed::{Context, ToComputedValue};
|
use values::computed::{Context, ToComputedValue};
|
||||||
use values::generics::position::Position as GenericPosition;
|
use values::generics::position::Position as GenericPosition;
|
||||||
|
@ -50,17 +50,17 @@ define_css_keyword_enum! { Y:
|
||||||
add_impls_for_keyword_enum!(Y);
|
add_impls_for_keyword_enum!(Y);
|
||||||
|
|
||||||
impl Parse for Position {
|
impl Parse for Position {
|
||||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
Self::parse_quirky(context, input, AllowQuirks::No)
|
Self::parse_quirky(context, input, AllowQuirks::No)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Position {
|
impl Position {
|
||||||
/// Parses a `<position>`, with quirks.
|
/// Parses a `<position>`, with quirks.
|
||||||
pub fn parse_quirky(context: &ParserContext,
|
pub fn parse_quirky<'i, 't>(context: &ParserContext,
|
||||||
input: &mut Parser,
|
input: &mut Parser<'i, 't>,
|
||||||
allow_quirks: AllowQuirks)
|
allow_quirks: AllowQuirks)
|
||||||
-> Result<Self, ()> {
|
-> Result<Self, ParseError<'i>> {
|
||||||
match input.try(|i| PositionComponent::parse_quirky(context, i, allow_quirks)) {
|
match input.try(|i| PositionComponent::parse_quirky(context, i, allow_quirks)) {
|
||||||
Ok(x_pos @ PositionComponent::Center) => {
|
Ok(x_pos @ PositionComponent::Center) => {
|
||||||
if let Ok(y_pos) = input.try(|i| PositionComponent::parse_quirky(context, i, allow_quirks)) {
|
if let Ok(y_pos) = input.try(|i| PositionComponent::parse_quirky(context, i, allow_quirks)) {
|
||||||
|
@ -104,7 +104,7 @@ impl Position {
|
||||||
Err(_) => {},
|
Err(_) => {},
|
||||||
}
|
}
|
||||||
let y_keyword = Y::parse(input)?;
|
let y_keyword = Y::parse(input)?;
|
||||||
let lop_and_x_pos: Result<_, ()> = input.try(|i| {
|
let lop_and_x_pos: Result<_, ParseError> = input.try(|i| {
|
||||||
let y_lop = i.try(|i| LengthOrPercentage::parse_quirky(context, i, allow_quirks)).ok();
|
let y_lop = i.try(|i| LengthOrPercentage::parse_quirky(context, i, allow_quirks)).ok();
|
||||||
if let Ok(x_keyword) = i.try(X::parse) {
|
if let Ok(x_keyword) = i.try(X::parse) {
|
||||||
let x_lop = i.try(|i| LengthOrPercentage::parse_quirky(context, i, allow_quirks)).ok();
|
let x_lop = i.try(|i| LengthOrPercentage::parse_quirky(context, i, allow_quirks)).ok();
|
||||||
|
@ -167,17 +167,17 @@ impl<S> HasViewportPercentage for PositionComponent<S> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S: Parse> Parse for PositionComponent<S> {
|
impl<S: Parse> Parse for PositionComponent<S> {
|
||||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
Self::parse_quirky(context, input, AllowQuirks::No)
|
Self::parse_quirky(context, input, AllowQuirks::No)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S: Parse> PositionComponent<S> {
|
impl<S: Parse> PositionComponent<S> {
|
||||||
/// Parses a component of a CSS position, with quirks.
|
/// Parses a component of a CSS position, with quirks.
|
||||||
pub fn parse_quirky(context: &ParserContext,
|
pub fn parse_quirky<'i, 't>(context: &ParserContext,
|
||||||
input: &mut Parser,
|
input: &mut Parser<'i, 't>,
|
||||||
allow_quirks: AllowQuirks)
|
allow_quirks: AllowQuirks)
|
||||||
-> Result<Self, ()> {
|
-> Result<Self, ParseError<'i>> {
|
||||||
if input.try(|i| i.expect_ident_matching("center")).is_ok() {
|
if input.try(|i| i.expect_ident_matching("center")).is_ok() {
|
||||||
return Ok(PositionComponent::Center);
|
return Ok(PositionComponent::Center);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
use cssparser::Parser;
|
use cssparser::Parser;
|
||||||
use parser::ParserContext;
|
use parser::ParserContext;
|
||||||
|
use style_traits::ParseError;
|
||||||
use values::generics::rect::Rect;
|
use values::generics::rect::Rect;
|
||||||
use values::specified::length::LengthOrNumber;
|
use values::specified::length::LengthOrNumber;
|
||||||
|
|
||||||
|
@ -15,7 +16,8 @@ pub type LengthOrNumberRect = Rect<LengthOrNumber>;
|
||||||
impl LengthOrNumberRect {
|
impl LengthOrNumberRect {
|
||||||
/// Parses a `LengthOrNumberRect`, rejecting negative values.
|
/// Parses a `LengthOrNumberRect`, rejecting negative values.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn parse_non_negative(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
pub fn parse_non_negative<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
|
-> Result<Self, ParseError<'i>> {
|
||||||
Rect::parse_with(context, input, LengthOrNumber::parse_non_negative)
|
Rect::parse_with(context, input, LengthOrNumber::parse_non_negative)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,9 @@
|
||||||
|
|
||||||
use cssparser::Parser;
|
use cssparser::Parser;
|
||||||
use parser::{Parse, ParserContext};
|
use parser::{Parse, ParserContext};
|
||||||
|
use selectors::parser::SelectorParseError;
|
||||||
use std::ascii::AsciiExt;
|
use std::ascii::AsciiExt;
|
||||||
|
use style_traits::ParseError;
|
||||||
use values::computed::{Context, ToComputedValue};
|
use values::computed::{Context, ToComputedValue};
|
||||||
use values::computed::text::LineHeight as ComputedLineHeight;
|
use values::computed::text::LineHeight as ComputedLineHeight;
|
||||||
use values::generics::text::InitialLetter as GenericInitialLetter;
|
use values::generics::text::InitialLetter as GenericInitialLetter;
|
||||||
|
@ -28,7 +30,7 @@ pub type WordSpacing = Spacing<LengthOrPercentage>;
|
||||||
pub type LineHeight = GenericLineHeight<Number, LengthOrPercentage>;
|
pub type LineHeight = GenericLineHeight<Number, LengthOrPercentage>;
|
||||||
|
|
||||||
impl Parse for InitialLetter {
|
impl Parse for InitialLetter {
|
||||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
if input.try(|i| i.expect_ident_matching("normal")).is_ok() {
|
if input.try(|i| i.expect_ident_matching("normal")).is_ok() {
|
||||||
return Ok(GenericInitialLetter::Normal);
|
return Ok(GenericInitialLetter::Normal);
|
||||||
}
|
}
|
||||||
|
@ -39,7 +41,7 @@ impl Parse for InitialLetter {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for LetterSpacing {
|
impl Parse for LetterSpacing {
|
||||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
Spacing::parse_with(context, input, |c, i| {
|
Spacing::parse_with(context, input, |c, i| {
|
||||||
Length::parse_quirky(c, i, AllowQuirks::Yes)
|
Length::parse_quirky(c, i, AllowQuirks::Yes)
|
||||||
})
|
})
|
||||||
|
@ -47,7 +49,7 @@ impl Parse for LetterSpacing {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for WordSpacing {
|
impl Parse for WordSpacing {
|
||||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
Spacing::parse_with(context, input, |c, i| {
|
Spacing::parse_with(context, input, |c, i| {
|
||||||
LengthOrPercentage::parse_quirky(c, i, AllowQuirks::Yes)
|
LengthOrPercentage::parse_quirky(c, i, AllowQuirks::Yes)
|
||||||
})
|
})
|
||||||
|
@ -55,22 +57,23 @@ impl Parse for WordSpacing {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for LineHeight {
|
impl Parse for LineHeight {
|
||||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
if let Ok(number) = input.try(|i| Number::parse_non_negative(context, i)) {
|
if let Ok(number) = input.try(|i| Number::parse_non_negative(context, i)) {
|
||||||
return Ok(GenericLineHeight::Number(number))
|
return Ok(GenericLineHeight::Number(number))
|
||||||
}
|
}
|
||||||
if let Ok(lop) = input.try(|i| LengthOrPercentage::parse_non_negative(context, i)) {
|
if let Ok(lop) = input.try(|i| LengthOrPercentage::parse_non_negative(context, i)) {
|
||||||
return Ok(GenericLineHeight::Length(lop))
|
return Ok(GenericLineHeight::Length(lop))
|
||||||
}
|
}
|
||||||
match &input.expect_ident()? {
|
let ident = input.expect_ident()?;
|
||||||
ident if ident.eq_ignore_ascii_case("normal") => {
|
match ident {
|
||||||
|
ref ident if ident.eq_ignore_ascii_case("normal") => {
|
||||||
Ok(GenericLineHeight::Normal)
|
Ok(GenericLineHeight::Normal)
|
||||||
},
|
},
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
ident if ident.eq_ignore_ascii_case("-moz-block-height") => {
|
ref ident if ident.eq_ignore_ascii_case("-moz-block-height") => {
|
||||||
Ok(GenericLineHeight::MozBlockHeight)
|
Ok(GenericLineHeight::MozBlockHeight)
|
||||||
},
|
},
|
||||||
_ => Err(()),
|
ident => Err(SelectorParseError::UnexpectedIdent(ident).into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
use cssparser::Parser;
|
use cssparser::Parser;
|
||||||
use euclid::Point2D;
|
use euclid::Point2D;
|
||||||
use parser::{Parse, ParserContext};
|
use parser::{Parse, ParserContext};
|
||||||
|
use selectors::parser::SelectorParseError;
|
||||||
|
use style_traits::{ParseError, StyleParseError};
|
||||||
use values::computed::{LengthOrPercentage as ComputedLengthOrPercentage, Context, ToComputedValue};
|
use values::computed::{LengthOrPercentage as ComputedLengthOrPercentage, Context, ToComputedValue};
|
||||||
use values::computed::transform::TimingFunction as ComputedTimingFunction;
|
use values::computed::transform::TimingFunction as ComputedTimingFunction;
|
||||||
use values::generics::transform::{StepPosition, TimingFunction as GenericTimingFunction};
|
use values::generics::transform::{StepPosition, TimingFunction as GenericTimingFunction};
|
||||||
|
@ -34,7 +36,7 @@ pub enum OriginComponent<S> {
|
||||||
pub type TimingFunction = GenericTimingFunction<Integer, Number>;
|
pub type TimingFunction = GenericTimingFunction<Integer, Number>;
|
||||||
|
|
||||||
impl Parse for TransformOrigin {
|
impl Parse for TransformOrigin {
|
||||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
let parse_depth = |input: &mut Parser| {
|
let parse_depth = |input: &mut Parser| {
|
||||||
input.try(|i| Length::parse(context, i)).unwrap_or(Length::from_px(0.))
|
input.try(|i| Length::parse(context, i)).unwrap_or(Length::from_px(0.))
|
||||||
};
|
};
|
||||||
|
@ -85,7 +87,7 @@ impl Parse for TransformOrigin {
|
||||||
impl<S> Parse for OriginComponent<S>
|
impl<S> Parse for OriginComponent<S>
|
||||||
where S: Parse,
|
where S: Parse,
|
||||||
{
|
{
|
||||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
if input.try(|i| i.expect_ident_matching("center")).is_ok() {
|
if input.try(|i| i.expect_ident_matching("center")).is_ok() {
|
||||||
return Ok(OriginComponent::Center);
|
return Ok(OriginComponent::Center);
|
||||||
}
|
}
|
||||||
|
@ -123,7 +125,7 @@ impl<S> ToComputedValue for OriginComponent<S>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for TimingFunction {
|
impl Parse for TimingFunction {
|
||||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||||
if let Ok(keyword) = input.try(TimingKeyword::parse) {
|
if let Ok(keyword) = input.try(TimingKeyword::parse) {
|
||||||
return Ok(GenericTimingFunction::Keyword(keyword));
|
return Ok(GenericTimingFunction::Keyword(keyword));
|
||||||
}
|
}
|
||||||
|
@ -131,13 +133,13 @@ impl Parse for TimingFunction {
|
||||||
let position = match_ignore_ascii_case! { &ident,
|
let position = match_ignore_ascii_case! { &ident,
|
||||||
"step-start" => StepPosition::Start,
|
"step-start" => StepPosition::Start,
|
||||||
"step-end" => StepPosition::End,
|
"step-end" => StepPosition::End,
|
||||||
_ => return Err(()),
|
_ => return Err(SelectorParseError::UnexpectedIdent(ident.clone()).into()),
|
||||||
};
|
};
|
||||||
return Ok(GenericTimingFunction::Steps(Integer::new(1), position));
|
return Ok(GenericTimingFunction::Steps(Integer::new(1), position));
|
||||||
}
|
}
|
||||||
let function = input.expect_function()?;
|
let function = input.expect_function()?;
|
||||||
input.parse_nested_block(|i| {
|
input.parse_nested_block(move |i| {
|
||||||
match_ignore_ascii_case! { &function,
|
(match_ignore_ascii_case! { &function,
|
||||||
"cubic-bezier" => {
|
"cubic-bezier" => {
|
||||||
let p1x = Number::parse(context, i)?;
|
let p1x = Number::parse(context, i)?;
|
||||||
i.expect_comma()?;
|
i.expect_comma()?;
|
||||||
|
@ -148,7 +150,7 @@ impl Parse for TimingFunction {
|
||||||
let p2y = Number::parse(context, i)?;
|
let p2y = Number::parse(context, i)?;
|
||||||
|
|
||||||
if p1x.get() < 0.0 || p1x.get() > 1.0 || p2x.get() < 0.0 || p2x.get() > 1.0 {
|
if p1x.get() < 0.0 || p1x.get() > 1.0 || p2x.get() < 0.0 || p2x.get() > 1.0 {
|
||||||
return Err(());
|
return Err(StyleParseError::UnspecifiedError.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
let (p1, p2) = (Point2D::new(p1x, p1y), Point2D::new(p2x, p2y));
|
let (p1, p2) = (Point2D::new(p1x, p1y), Point2D::new(p2x, p2y));
|
||||||
|
@ -167,7 +169,7 @@ impl Parse for TimingFunction {
|
||||||
Ok(GenericTimingFunction::Frames(frames))
|
Ok(GenericTimingFunction::Frames(frames))
|
||||||
},
|
},
|
||||||
_ => Err(()),
|
_ => Err(()),
|
||||||
}
|
}).map_err(|()| StyleParseError::UnexpectedFunction(function).into())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,9 +16,10 @@ gecko = []
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
app_units = "0.4.1"
|
app_units = "0.4.1"
|
||||||
cssparser = "0.13.7"
|
cssparser = "0.14.0"
|
||||||
euclid = "0.13"
|
euclid = "0.13"
|
||||||
heapsize = {version = "0.4", optional = true}
|
heapsize = {version = "0.4", optional = true}
|
||||||
heapsize_derive = {version = "0.1", optional = true}
|
heapsize_derive = {version = "0.1", optional = true}
|
||||||
|
selectors = { path = "../selectors" }
|
||||||
serde = {version = "0.9", optional = true}
|
serde = {version = "0.9", optional = true}
|
||||||
serde_derive = {version = "0.9", optional = true}
|
serde_derive = {version = "0.9", optional = true}
|
||||||
|
|
|
@ -18,8 +18,12 @@ extern crate app_units;
|
||||||
extern crate euclid;
|
extern crate euclid;
|
||||||
#[cfg(feature = "servo")] extern crate heapsize;
|
#[cfg(feature = "servo")] extern crate heapsize;
|
||||||
#[cfg(feature = "servo")] #[macro_use] extern crate heapsize_derive;
|
#[cfg(feature = "servo")] #[macro_use] extern crate heapsize_derive;
|
||||||
|
extern crate selectors;
|
||||||
#[cfg(feature = "servo")] #[macro_use] extern crate serde_derive;
|
#[cfg(feature = "servo")] #[macro_use] extern crate serde_derive;
|
||||||
|
|
||||||
|
use selectors::parser::SelectorParseError;
|
||||||
|
use std::borrow::Cow;
|
||||||
|
|
||||||
/// Opaque type stored in type-unsafe work queues for parallel layout.
|
/// Opaque type stored in type-unsafe work queues for parallel layout.
|
||||||
/// Must be transmutable to and from `TNode`.
|
/// Must be transmutable to and from `TNode`.
|
||||||
pub type UnsafeNode = (usize, usize);
|
pub type UnsafeNode = (usize, usize);
|
||||||
|
@ -68,3 +72,71 @@ pub mod viewport;
|
||||||
|
|
||||||
pub use values::{ToCss, OneOrMoreCommaSeparated};
|
pub use values::{ToCss, OneOrMoreCommaSeparated};
|
||||||
pub use viewport::HasViewportPercentage;
|
pub use viewport::HasViewportPercentage;
|
||||||
|
|
||||||
|
/// The error type for all CSS parsing routines.
|
||||||
|
pub type ParseError<'i> = cssparser::ParseError<'i, SelectorParseError<'i, StyleParseError<'i>>>;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
|
/// Errors that can be encountered while parsing CSS values.
|
||||||
|
pub enum StyleParseError<'i> {
|
||||||
|
/// A bad URL token in a DVB.
|
||||||
|
BadUrlInDeclarationValueBlock,
|
||||||
|
/// A bad string token in a DVB.
|
||||||
|
BadStringInDeclarationValueBlock,
|
||||||
|
/// Unexpected closing parenthesis in a DVB.
|
||||||
|
UnbalancedCloseParenthesisInDeclarationValueBlock,
|
||||||
|
/// Unexpected closing bracket in a DVB.
|
||||||
|
UnbalancedCloseSquareBracketInDeclarationValueBlock,
|
||||||
|
/// Unexpected closing curly bracket in a DVB.
|
||||||
|
UnbalancedCloseCurlyBracketInDeclarationValueBlock,
|
||||||
|
/// A property declaration parsing error.
|
||||||
|
PropertyDeclaration(PropertyDeclarationParseError),
|
||||||
|
/// A property declaration value had input remaining after successfully parsing.
|
||||||
|
PropertyDeclarationValueNotExhausted,
|
||||||
|
/// An unexpected dimension token was encountered.
|
||||||
|
UnexpectedDimension(Cow<'i, str>),
|
||||||
|
/// A media query using a ranged expression with no value was encountered.
|
||||||
|
RangedExpressionWithNoValue,
|
||||||
|
/// A function was encountered that was not expected.
|
||||||
|
UnexpectedFunction(Cow<'i, str>),
|
||||||
|
/// @namespace must be before any rule but @charset and @import
|
||||||
|
UnexpectedNamespaceRule,
|
||||||
|
/// @import must be before any rule but @charset
|
||||||
|
UnexpectedImportRule,
|
||||||
|
/// Unexpected @charset rule encountered.
|
||||||
|
UnexpectedCharsetRule,
|
||||||
|
/// Unsupported @ rule
|
||||||
|
UnsupportedAtRule(Cow<'i, str>),
|
||||||
|
/// A placeholder for many sources of errors that require more specific variants.
|
||||||
|
UnspecifiedError,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The result of parsing a property declaration.
|
||||||
|
#[derive(Eq, PartialEq, Copy, Clone, Debug)]
|
||||||
|
pub enum PropertyDeclarationParseError {
|
||||||
|
/// The property declaration was for an unknown property.
|
||||||
|
UnknownProperty,
|
||||||
|
/// The property declaration was for a disabled experimental property.
|
||||||
|
ExperimentalProperty,
|
||||||
|
/// The property declaration contained an invalid value.
|
||||||
|
InvalidValue,
|
||||||
|
/// The declaration contained an animation property, and we were parsing
|
||||||
|
/// this as a keyframe block (so that property should be ignored).
|
||||||
|
///
|
||||||
|
/// See: https://drafts.csswg.org/css-animations/#keyframes
|
||||||
|
AnimationPropertyInKeyframeBlock,
|
||||||
|
/// The property is not allowed within a page rule.
|
||||||
|
NotAllowedInPageRule,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> From<StyleParseError<'a>> for ParseError<'a> {
|
||||||
|
fn from(this: StyleParseError<'a>) -> Self {
|
||||||
|
cssparser::ParseError::Custom(SelectorParseError::Custom(this))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> From<PropertyDeclarationParseError> for ParseError<'a> {
|
||||||
|
fn from(this: PropertyDeclarationParseError) -> Self {
|
||||||
|
cssparser::ParseError::Custom(SelectorParseError::Custom(StyleParseError::PropertyDeclaration(this)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -171,9 +171,13 @@ macro_rules! __define_css_keyword_enum__actual {
|
||||||
|
|
||||||
impl $name {
|
impl $name {
|
||||||
/// Parse this property from a CSS input stream.
|
/// Parse this property from a CSS input stream.
|
||||||
pub fn parse(input: &mut ::cssparser::Parser) -> Result<$name, ()> {
|
pub fn parse<'i, 't>(input: &mut ::cssparser::Parser<'i, 't>)
|
||||||
|
-> Result<$name, $crate::ParseError<'i>> {
|
||||||
let ident = input.expect_ident()?;
|
let ident = input.expect_ident()?;
|
||||||
Self::from_ident(&ident)
|
Self::from_ident(&ident)
|
||||||
|
.map_err(|()| ::cssparser::ParseError::Basic(
|
||||||
|
::cssparser::BasicParseError::UnexpectedToken(
|
||||||
|
::cssparser::Token::Ident(ident))))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse this property from an already-tokenized identifier.
|
/// Parse this property from an already-tokenized identifier.
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue