| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170 |
- '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;
|