You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
170 lines
4.8 KiB
170 lines
4.8 KiB
'use strict'; |
|
|
|
const types = require('../tokenizer/types.cjs'); |
|
|
|
const PLUSSIGN = 0x002B; // U+002B PLUS SIGN (+) |
|
const HYPHENMINUS = 0x002D; // U+002D HYPHEN-MINUS (-) |
|
|
|
const code = (type, value) => { |
|
if (type === types.Delim) { |
|
type = value; |
|
} |
|
|
|
if (typeof type === 'string') { |
|
const charCode = type.charCodeAt(0); |
|
return charCode > 0x7F ? 0x8000 : charCode << 8; |
|
} |
|
|
|
return type; |
|
}; |
|
|
|
// https://www.w3.org/TR/css-syntax-3/#serialization |
|
// The only requirement for serialization is that it must "round-trip" with parsing, |
|
// that is, parsing the stylesheet must produce the same data structures as parsing, |
|
// serializing, and parsing again, except for consecutive <whitespace-token>s, |
|
// which may be collapsed into a single token. |
|
|
|
const specPairs = [ |
|
[types.Ident, types.Ident], |
|
[types.Ident, types.Function], |
|
[types.Ident, types.Url], |
|
[types.Ident, types.BadUrl], |
|
[types.Ident, '-'], |
|
[types.Ident, types.Number], |
|
[types.Ident, types.Percentage], |
|
[types.Ident, types.Dimension], |
|
[types.Ident, types.CDC], |
|
[types.Ident, types.LeftParenthesis], |
|
|
|
[types.AtKeyword, types.Ident], |
|
[types.AtKeyword, types.Function], |
|
[types.AtKeyword, types.Url], |
|
[types.AtKeyword, types.BadUrl], |
|
[types.AtKeyword, '-'], |
|
[types.AtKeyword, types.Number], |
|
[types.AtKeyword, types.Percentage], |
|
[types.AtKeyword, types.Dimension], |
|
[types.AtKeyword, types.CDC], |
|
|
|
[types.Hash, types.Ident], |
|
[types.Hash, types.Function], |
|
[types.Hash, types.Url], |
|
[types.Hash, types.BadUrl], |
|
[types.Hash, '-'], |
|
[types.Hash, types.Number], |
|
[types.Hash, types.Percentage], |
|
[types.Hash, types.Dimension], |
|
[types.Hash, types.CDC], |
|
|
|
[types.Dimension, types.Ident], |
|
[types.Dimension, types.Function], |
|
[types.Dimension, types.Url], |
|
[types.Dimension, types.BadUrl], |
|
[types.Dimension, '-'], |
|
[types.Dimension, types.Number], |
|
[types.Dimension, types.Percentage], |
|
[types.Dimension, types.Dimension], |
|
[types.Dimension, types.CDC], |
|
|
|
['#', types.Ident], |
|
['#', types.Function], |
|
['#', types.Url], |
|
['#', types.BadUrl], |
|
['#', '-'], |
|
['#', types.Number], |
|
['#', types.Percentage], |
|
['#', types.Dimension], |
|
['#', types.CDC], // https://github.com/w3c/csswg-drafts/pull/6874 |
|
|
|
['-', types.Ident], |
|
['-', types.Function], |
|
['-', types.Url], |
|
['-', types.BadUrl], |
|
['-', '-'], |
|
['-', types.Number], |
|
['-', types.Percentage], |
|
['-', types.Dimension], |
|
['-', types.CDC], // https://github.com/w3c/csswg-drafts/pull/6874 |
|
|
|
[types.Number, types.Ident], |
|
[types.Number, types.Function], |
|
[types.Number, types.Url], |
|
[types.Number, types.BadUrl], |
|
[types.Number, types.Number], |
|
[types.Number, types.Percentage], |
|
[types.Number, types.Dimension], |
|
[types.Number, '%'], |
|
[types.Number, types.CDC], // https://github.com/w3c/csswg-drafts/pull/6874 |
|
|
|
['@', types.Ident], |
|
['@', types.Function], |
|
['@', types.Url], |
|
['@', types.BadUrl], |
|
['@', '-'], |
|
['@', types.CDC], // https://github.com/w3c/csswg-drafts/pull/6874 |
|
|
|
['.', types.Number], |
|
['.', types.Percentage], |
|
['.', types.Dimension], |
|
|
|
['+', types.Number], |
|
['+', types.Percentage], |
|
['+', types.Dimension], |
|
|
|
['/', '*'] |
|
]; |
|
// validate with scripts/generate-safe |
|
const safePairs = specPairs.concat([ |
|
[types.Ident, types.Hash], |
|
|
|
[types.Dimension, types.Hash], |
|
|
|
[types.Hash, types.Hash], |
|
|
|
[types.AtKeyword, types.LeftParenthesis], |
|
[types.AtKeyword, types.String], |
|
[types.AtKeyword, types.Colon], |
|
|
|
[types.Percentage, types.Percentage], |
|
[types.Percentage, types.Dimension], |
|
[types.Percentage, types.Function], |
|
[types.Percentage, '-'], |
|
|
|
[types.RightParenthesis, types.Ident], |
|
[types.RightParenthesis, types.Function], |
|
[types.RightParenthesis, types.Percentage], |
|
[types.RightParenthesis, types.Dimension], |
|
[types.RightParenthesis, types.Hash], |
|
[types.RightParenthesis, '-'] |
|
]); |
|
|
|
function createMap(pairs) { |
|
const isWhiteSpaceRequired = new Set( |
|
pairs.map(([prev, next]) => (code(prev) << 16 | code(next))) |
|
); |
|
|
|
return function(prevCode, type, value) { |
|
const nextCode = code(type, value); |
|
const nextCharCode = value.charCodeAt(0); |
|
const emitWs = |
|
(nextCharCode === HYPHENMINUS && |
|
type !== types.Ident && |
|
type !== types.Function && |
|
type !== types.CDC) || |
|
(nextCharCode === PLUSSIGN) |
|
? isWhiteSpaceRequired.has(prevCode << 16 | nextCharCode << 8) |
|
: isWhiteSpaceRequired.has(prevCode << 16 | nextCode); |
|
|
|
if (emitWs) { |
|
this.emit(' ', types.WhiteSpace, true); |
|
} |
|
|
|
return nextCode; |
|
}; |
|
} |
|
|
|
const spec = createMap(specPairs); |
|
const safe = createMap(safePairs); |
|
|
|
exports.safe = safe; |
|
exports.spec = spec;
|
|
|