Skip to main content

lewp_css/domain/
vendor_prefix.rs

1// This file is part of css. It is subject to the license terms in the COPYRIGHT file found in the top-level directory of this distribution and at https://raw.githubusercontent.com/lemonrock/css/master/COPYRIGHT. No part of predicator, including this file, may be copied, modified, propagated, or distributed except according to the terms contained in the COPYRIGHT file.
2// Copyright © 2017 The developers of css. See the COPYRIGHT file in the top-level directory of this distribution and at https://raw.githubusercontent.com/lemonrock/css/master/COPYRIGHT.
3
4use {cssparser::ToCss, std::fmt};
5
6//noinspection SpellCheckingInspection
7/// Vendor prefixes
8/// Sort order is such that -o- sorts before -webkit- and -ms- sorts after -webkit-, but -epub- (which is only supported by Webkit) sorts before -webkit-
9/// There ae other, now rare prefixes, such as -vx- (for Opera before -o-), -wap- (for WAP; a very defunct standard from 1999), -khtml- (for Webkit's predecessor) and so on.
10/// However, there are hardly ever encountered and so aren't explicitly coded for.
11#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
12pub enum VendorPrefix {
13    /// -o- prefix (legacy Opera Presto prefix).
14    o,
15
16    /// -moz- prefix.
17    moz,
18
19    /// -epub- prefix
20    epub,
21
22    /// -webkit- prefix (Is sometimes also used by IE, Edge and Blink-based browsers (Chrome and Opera)).
23    webkit,
24
25    /// -ms- prefix.
26    ms,
27
28    /// -servo- prefix
29    servo,
30
31    /// An unrecognised prefix, usually implies unusual or mistaken CSS
32    Unrecognised(String),
33}
34
35impl ToCss for VendorPrefix {
36    fn to_css<W: fmt::Write>(&self, dest: &mut W) -> fmt::Result {
37        use self::VendorPrefix::*;
38
39        match *self {
40            o => dest.write_str("-o-"),
41
42            moz => dest.write_str("-moz-"),
43
44            webkit => dest.write_str("-webkit-"),
45
46            ms => dest.write_str("-ms-"),
47
48            servo => dest.write_str("-servo-"),
49
50            epub => dest.write_str("-epub-"),
51
52            Unrecognised(ref prefix) => {
53                dest.write_char('-')?;
54                dest.write_str(prefix.as_str())?;
55                dest.write_char('-')
56            }
57        }
58    }
59}
60
61impl VendorPrefix {
62    /// Finds a prefix for an ascii lower case name, returning the prefix (if any) and the unprefixed name
63    /// Is not confused by CSS custom properties which start `--`
64    #[inline(always)]
65    pub fn findPrefixIfAnyForAsciiLowerCaseName<'i>(
66        asciiLowerCaseName: String,
67    ) -> (Option<VendorPrefix>, String) {
68        if asciiLowerCaseName.len() < 3 {
69            return (None, asciiLowerCaseName);
70        }
71
72        {
73            let (firstCharacter, remainder) = asciiLowerCaseName.split_at(1);
74
75            if firstCharacter == "-" && !remainder.starts_with('-') {
76                let mut split = remainder.splitn(2, '-');
77                let prefix = split.next().unwrap();
78                let unprefixedRemainder = split.next().unwrap();
79
80                use self::VendorPrefix::*;
81
82                return match prefix {
83                    "o" => (Some(o), unprefixedRemainder.to_owned()),
84
85                    "moz" => (Some(moz), unprefixedRemainder.to_owned()),
86
87                    "webkit" => (Some(webkit), unprefixedRemainder.to_owned()),
88
89                    "ms" => (Some(ms), unprefixedRemainder.to_owned()),
90
91                    "servo" => (Some(servo), unprefixedRemainder.to_owned()),
92
93                    _ => (
94                        Some(Unrecognised(prefix.to_owned())),
95                        unprefixedRemainder.to_owned(),
96                    ),
97                };
98            }
99        }
100
101        (None, asciiLowerCaseName)
102    }
103
104    /// Prefixes a name with a vendor prefix, eg 'background' might become '-moz-background' if Self is `moz`
105    #[inline(always)]
106    pub fn prefix(&self, name: &str) -> String {
107        use self::VendorPrefix::*;
108
109        fn knownPrefix(prefix: &str, name: &str) -> String {
110            let mut prefixed = String::with_capacity(prefix.len() + name.len());
111            prefixed.push_str(prefix);
112            prefixed.push_str(name);
113            prefixed
114        }
115
116        match self {
117            &o => knownPrefix("-o-", name),
118
119            &moz => knownPrefix("-moz-", name),
120
121            &epub => knownPrefix("-epub-", name),
122
123            &webkit => knownPrefix("-webkit-", name),
124
125            &ms => knownPrefix("-ms-", name),
126
127            &servo => knownPrefix("-servo-", name),
128
129            &Unrecognised(ref prefix) => {
130                let mut prefixed =
131                    String::with_capacity(1 + prefix.len() + 1 + name.len());
132                prefixed.push('-');
133                prefixed.push_str(prefix);
134                prefixed.push('-');
135                prefixed.push_str(name);
136                prefixed
137            }
138        }
139    }
140}