@dazl/shorthands-opener 4.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -0
- package/dist/compounds/compound-css-data.d.ts +22 -0
- package/dist/compounds/compound-css-data.d.ts.map +1 -0
- package/dist/compounds/compound-css-data.js +2 -0
- package/dist/compounds/compound-css-data.js.map +1 -0
- package/dist/compounds/compound-mapper.d.ts +4 -0
- package/dist/compounds/compound-mapper.d.ts.map +1 -0
- package/dist/compounds/compound-mapper.js +10 -0
- package/dist/compounds/compound-mapper.js.map +1 -0
- package/dist/compounds/compound-parser-utils.d.ts +3 -0
- package/dist/compounds/compound-parser-utils.d.ts.map +1 -0
- package/dist/compounds/compound-parser-utils.js +33 -0
- package/dist/compounds/compound-parser-utils.js.map +1 -0
- package/dist/compounds/compound-types.d.ts +26 -0
- package/dist/compounds/compound-types.d.ts.map +1 -0
- package/dist/compounds/compound-types.js +2 -0
- package/dist/compounds/compound-types.js.map +1 -0
- package/dist/compounds/compound-value-parsers.d.ts +6 -0
- package/dist/compounds/compound-value-parsers.d.ts.map +1 -0
- package/dist/compounds/compound-value-parsers.js +5 -0
- package/dist/compounds/compound-value-parsers.js.map +1 -0
- package/dist/compounds/index.d.ts +6 -0
- package/dist/compounds/index.d.ts.map +1 -0
- package/dist/compounds/index.js +6 -0
- package/dist/compounds/index.js.map +1 -0
- package/dist/compounds/parsers/index.d.ts +2 -0
- package/dist/compounds/parsers/index.d.ts.map +1 -0
- package/dist/compounds/parsers/index.js +2 -0
- package/dist/compounds/parsers/index.js.map +1 -0
- package/dist/compounds/parsers/shadow-compound.d.ts +5 -0
- package/dist/compounds/parsers/shadow-compound.d.ts.map +1 -0
- package/dist/compounds/parsers/shadow-compound.js +39 -0
- package/dist/compounds/parsers/shadow-compound.js.map +1 -0
- package/dist/css-data-types/data-types-consts.d.ts +212 -0
- package/dist/css-data-types/data-types-consts.d.ts.map +1 -0
- package/dist/css-data-types/data-types-consts.js +790 -0
- package/dist/css-data-types/data-types-consts.js.map +1 -0
- package/dist/css-data-types/data-types-predicates.d.ts +32 -0
- package/dist/css-data-types/data-types-predicates.d.ts.map +1 -0
- package/dist/css-data-types/data-types-predicates.js +353 -0
- package/dist/css-data-types/data-types-predicates.js.map +1 -0
- package/dist/css-data-types/data-types-state-machines.d.ts +14 -0
- package/dist/css-data-types/data-types-state-machines.d.ts.map +1 -0
- package/dist/css-data-types/data-types-state-machines.js +129 -0
- package/dist/css-data-types/data-types-state-machines.js.map +1 -0
- package/dist/css-data-types/data-types-types.d.ts +26 -0
- package/dist/css-data-types/data-types-types.d.ts.map +1 -0
- package/dist/css-data-types/data-types-types.js +2 -0
- package/dist/css-data-types/data-types-types.js.map +1 -0
- package/dist/css-data-types/data-types-utils.d.ts +31 -0
- package/dist/css-data-types/data-types-utils.d.ts.map +1 -0
- package/dist/css-data-types/data-types-utils.js +176 -0
- package/dist/css-data-types/data-types-utils.js.map +1 -0
- package/dist/css-data-types/data-types.d.ts +64 -0
- package/dist/css-data-types/data-types.d.ts.map +1 -0
- package/dist/css-data-types/data-types.js +304 -0
- package/dist/css-data-types/data-types.js.map +1 -0
- package/dist/css-data-types/index.d.ts +7 -0
- package/dist/css-data-types/index.d.ts.map +1 -0
- package/dist/css-data-types/index.js +7 -0
- package/dist/css-data-types/index.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/shorthands/index.d.ts +8 -0
- package/dist/shorthands/index.d.ts.map +1 -0
- package/dist/shorthands/index.js +8 -0
- package/dist/shorthands/index.js.map +1 -0
- package/dist/shorthands/openers/background-position-shorthand.d.ts +5 -0
- package/dist/shorthands/openers/background-position-shorthand.d.ts.map +1 -0
- package/dist/shorthands/openers/background-position-shorthand.js +173 -0
- package/dist/shorthands/openers/background-position-shorthand.js.map +1 -0
- package/dist/shorthands/openers/background-shorthand.d.ts +5 -0
- package/dist/shorthands/openers/background-shorthand.d.ts.map +1 -0
- package/dist/shorthands/openers/background-shorthand.js +88 -0
- package/dist/shorthands/openers/background-shorthand.js.map +1 -0
- package/dist/shorthands/openers/border-image-shorthand.d.ts +5 -0
- package/dist/shorthands/openers/border-image-shorthand.d.ts.map +1 -0
- package/dist/shorthands/openers/border-image-shorthand.js +16 -0
- package/dist/shorthands/openers/border-image-shorthand.js.map +1 -0
- package/dist/shorthands/openers/border-radius-shorthand.d.ts +5 -0
- package/dist/shorthands/openers/border-radius-shorthand.d.ts.map +1 -0
- package/dist/shorthands/openers/border-radius-shorthand.js +61 -0
- package/dist/shorthands/openers/border-radius-shorthand.js.map +1 -0
- package/dist/shorthands/openers/border-shorthand.d.ts +20 -0
- package/dist/shorthands/openers/border-shorthand.d.ts.map +1 -0
- package/dist/shorthands/openers/border-shorthand.js +90 -0
- package/dist/shorthands/openers/border-shorthand.js.map +1 -0
- package/dist/shorthands/openers/flex-flow-shorthand.d.ts +5 -0
- package/dist/shorthands/openers/flex-flow-shorthand.d.ts.map +1 -0
- package/dist/shorthands/openers/flex-flow-shorthand.js +13 -0
- package/dist/shorthands/openers/flex-flow-shorthand.js.map +1 -0
- package/dist/shorthands/openers/flex-shorthand.d.ts +5 -0
- package/dist/shorthands/openers/flex-shorthand.d.ts.map +1 -0
- package/dist/shorthands/openers/flex-shorthand.js +55 -0
- package/dist/shorthands/openers/flex-shorthand.js.map +1 -0
- package/dist/shorthands/openers/font-shorthand.d.ts +5 -0
- package/dist/shorthands/openers/font-shorthand.d.ts.map +1 -0
- package/dist/shorthands/openers/font-shorthand.js +60 -0
- package/dist/shorthands/openers/font-shorthand.js.map +1 -0
- package/dist/shorthands/openers/gap-shorthand.d.ts +5 -0
- package/dist/shorthands/openers/gap-shorthand.d.ts.map +1 -0
- package/dist/shorthands/openers/gap-shorthand.js +28 -0
- package/dist/shorthands/openers/gap-shorthand.js.map +1 -0
- package/dist/shorthands/openers/grid-axis-shorthand.d.ts +6 -0
- package/dist/shorthands/openers/grid-axis-shorthand.d.ts.map +1 -0
- package/dist/shorthands/openers/grid-axis-shorthand.js +36 -0
- package/dist/shorthands/openers/grid-axis-shorthand.js.map +1 -0
- package/dist/shorthands/openers/grid-gap-shorthand.d.ts +5 -0
- package/dist/shorthands/openers/grid-gap-shorthand.d.ts.map +1 -0
- package/dist/shorthands/openers/grid-gap-shorthand.js +21 -0
- package/dist/shorthands/openers/grid-gap-shorthand.js.map +1 -0
- package/dist/shorthands/openers/grid-shorthand.d.ts +8 -0
- package/dist/shorthands/openers/grid-shorthand.d.ts.map +1 -0
- package/dist/shorthands/openers/grid-shorthand.js +145 -0
- package/dist/shorthands/openers/grid-shorthand.js.map +1 -0
- package/dist/shorthands/openers/grid-template-shorthand.d.ts +10 -0
- package/dist/shorthands/openers/grid-template-shorthand.d.ts.map +1 -0
- package/dist/shorthands/openers/grid-template-shorthand.js +113 -0
- package/dist/shorthands/openers/grid-template-shorthand.js.map +1 -0
- package/dist/shorthands/openers/index.d.ts +22 -0
- package/dist/shorthands/openers/index.d.ts.map +1 -0
- package/dist/shorthands/openers/index.js +22 -0
- package/dist/shorthands/openers/index.js.map +1 -0
- package/dist/shorthands/openers/list-style-shorthand.d.ts +5 -0
- package/dist/shorthands/openers/list-style-shorthand.d.ts.map +1 -0
- package/dist/shorthands/openers/list-style-shorthand.js +15 -0
- package/dist/shorthands/openers/list-style-shorthand.js.map +1 -0
- package/dist/shorthands/openers/margin-shorthand.d.ts +5 -0
- package/dist/shorthands/openers/margin-shorthand.d.ts.map +1 -0
- package/dist/shorthands/openers/margin-shorthand.js +11 -0
- package/dist/shorthands/openers/margin-shorthand.js.map +1 -0
- package/dist/shorthands/openers/outline-shorthand.d.ts +5 -0
- package/dist/shorthands/openers/outline-shorthand.d.ts.map +1 -0
- package/dist/shorthands/openers/outline-shorthand.js +14 -0
- package/dist/shorthands/openers/outline-shorthand.js.map +1 -0
- package/dist/shorthands/openers/overflow-shorthand.d.ts +5 -0
- package/dist/shorthands/openers/overflow-shorthand.d.ts.map +1 -0
- package/dist/shorthands/openers/overflow-shorthand.js +21 -0
- package/dist/shorthands/openers/overflow-shorthand.js.map +1 -0
- package/dist/shorthands/openers/padding-shorthand.d.ts +5 -0
- package/dist/shorthands/openers/padding-shorthand.d.ts.map +1 -0
- package/dist/shorthands/openers/padding-shorthand.js +11 -0
- package/dist/shorthands/openers/padding-shorthand.js.map +1 -0
- package/dist/shorthands/openers/place-content-shorthand.d.ts +5 -0
- package/dist/shorthands/openers/place-content-shorthand.d.ts.map +1 -0
- package/dist/shorthands/openers/place-content-shorthand.js +29 -0
- package/dist/shorthands/openers/place-content-shorthand.js.map +1 -0
- package/dist/shorthands/openers/place-items-shorthand.d.ts +5 -0
- package/dist/shorthands/openers/place-items-shorthand.d.ts.map +1 -0
- package/dist/shorthands/openers/place-items-shorthand.js +23 -0
- package/dist/shorthands/openers/place-items-shorthand.js.map +1 -0
- package/dist/shorthands/openers/text-decoration-shorthand.d.ts +5 -0
- package/dist/shorthands/openers/text-decoration-shorthand.d.ts.map +1 -0
- package/dist/shorthands/openers/text-decoration-shorthand.js +14 -0
- package/dist/shorthands/openers/text-decoration-shorthand.js.map +1 -0
- package/dist/shorthands/shorthand-css-data.d.ts +120 -0
- package/dist/shorthands/shorthand-css-data.d.ts.map +1 -0
- package/dist/shorthands/shorthand-css-data.js +48 -0
- package/dist/shorthands/shorthand-css-data.js.map +1 -0
- package/dist/shorthands/shorthand-mapper.d.ts +6 -0
- package/dist/shorthands/shorthand-mapper.d.ts.map +1 -0
- package/dist/shorthands/shorthand-mapper.js +72 -0
- package/dist/shorthands/shorthand-mapper.js.map +1 -0
- package/dist/shorthands/shorthand-parser-errors.d.ts +25 -0
- package/dist/shorthands/shorthand-parser-errors.d.ts.map +1 -0
- package/dist/shorthands/shorthand-parser-errors.js +41 -0
- package/dist/shorthands/shorthand-parser-errors.js.map +1 -0
- package/dist/shorthands/shorthand-parser-utils.d.ts +24 -0
- package/dist/shorthands/shorthand-parser-utils.d.ts.map +1 -0
- package/dist/shorthands/shorthand-parser-utils.js +398 -0
- package/dist/shorthands/shorthand-parser-utils.js.map +1 -0
- package/dist/shorthands/shorthand-types.d.ts +64 -0
- package/dist/shorthands/shorthand-types.d.ts.map +1 -0
- package/dist/shorthands/shorthand-types.js +2 -0
- package/dist/shorthands/shorthand-types.js.map +1 -0
- package/dist/shorthands/shorthands-ast-evaluation.d.ts +5 -0
- package/dist/shorthands/shorthands-ast-evaluation.d.ts.map +1 -0
- package/dist/shorthands/shorthands-ast-evaluation.js +19 -0
- package/dist/shorthands/shorthands-ast-evaluation.js.map +1 -0
- package/dist/tokenizers/css-value-tokenizer.d.ts +43 -0
- package/dist/tokenizers/css-value-tokenizer.d.ts.map +1 -0
- package/dist/tokenizers/css-value-tokenizer.js +154 -0
- package/dist/tokenizers/css-value-tokenizer.js.map +1 -0
- package/dist/tokenizers/index.d.ts +2 -0
- package/dist/tokenizers/index.d.ts.map +1 -0
- package/dist/tokenizers/index.js +2 -0
- package/dist/tokenizers/index.js.map +1 -0
- package/package.json +54 -0
- package/src/compounds/compound-css-data.ts +24 -0
- package/src/compounds/compound-mapper.ts +21 -0
- package/src/compounds/compound-parser-utils.ts +47 -0
- package/src/compounds/compound-types.ts +35 -0
- package/src/compounds/compound-value-parsers.ts +12 -0
- package/src/compounds/index.ts +5 -0
- package/src/compounds/parsers/index.ts +1 -0
- package/src/compounds/parsers/shadow-compound.ts +56 -0
- package/src/css-data-types/data-types-consts.ts +877 -0
- package/src/css-data-types/data-types-predicates.ts +477 -0
- package/src/css-data-types/data-types-state-machines.ts +169 -0
- package/src/css-data-types/data-types-types.ts +43 -0
- package/src/css-data-types/data-types-utils.ts +258 -0
- package/src/css-data-types/data-types.ts +435 -0
- package/src/css-data-types/index.ts +6 -0
- package/src/index.ts +4 -0
- package/src/shorthands/index.ts +7 -0
- package/src/shorthands/openers/background-position-shorthand.ts +180 -0
- package/src/shorthands/openers/background-shorthand.ts +161 -0
- package/src/shorthands/openers/border-image-shorthand.ts +35 -0
- package/src/shorthands/openers/border-radius-shorthand.ts +93 -0
- package/src/shorthands/openers/border-shorthand.ts +198 -0
- package/src/shorthands/openers/flex-flow-shorthand.ts +24 -0
- package/src/shorthands/openers/flex-shorthand.ts +79 -0
- package/src/shorthands/openers/font-shorthand.ts +85 -0
- package/src/shorthands/openers/gap-shorthand.ts +47 -0
- package/src/shorthands/openers/grid-axis-shorthand.ts +61 -0
- package/src/shorthands/openers/grid-gap-shorthand.ts +40 -0
- package/src/shorthands/openers/grid-shorthand.ts +260 -0
- package/src/shorthands/openers/grid-template-shorthand.ts +176 -0
- package/src/shorthands/openers/index.ts +21 -0
- package/src/shorthands/openers/list-style-shorthand.ts +33 -0
- package/src/shorthands/openers/margin-shorthand.ts +20 -0
- package/src/shorthands/openers/outline-shorthand.ts +27 -0
- package/src/shorthands/openers/overflow-shorthand.ts +40 -0
- package/src/shorthands/openers/padding-shorthand.ts +21 -0
- package/src/shorthands/openers/place-content-shorthand.ts +49 -0
- package/src/shorthands/openers/place-items-shorthand.ts +43 -0
- package/src/shorthands/openers/text-decoration-shorthand.ts +27 -0
- package/src/shorthands/shorthand-css-data.ts +210 -0
- package/src/shorthands/shorthand-mapper.ts +157 -0
- package/src/shorthands/shorthand-parser-errors.ts +47 -0
- package/src/shorthands/shorthand-parser-utils.ts +602 -0
- package/src/shorthands/shorthand-types.ts +107 -0
- package/src/shorthands/shorthands-ast-evaluation.ts +38 -0
- package/src/tokenizers/css-value-tokenizer.ts +220 -0
- package/src/tokenizers/index.ts +1 -0
|
@@ -0,0 +1,602 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
CSSAstNode,
|
|
3
|
+
ParseShorthandAPI,
|
|
4
|
+
EvaluatedAst,
|
|
5
|
+
DataTypeMatch,
|
|
6
|
+
OpenedShorthandValue,
|
|
7
|
+
OpenedShorthand,
|
|
8
|
+
SimpleOpenedShorthand,
|
|
9
|
+
ShorthandOpener,
|
|
10
|
+
ShorthandOpenerInner,
|
|
11
|
+
SimpleShorthandOpenerInner,
|
|
12
|
+
UnorderedListShorthandOptions,
|
|
13
|
+
BeforeOpenerCheck,
|
|
14
|
+
ShorthandPart,
|
|
15
|
+
ShorthandOpenerData,
|
|
16
|
+
SimpleShorthandOpener,
|
|
17
|
+
ShorthandCloserTemplate,
|
|
18
|
+
ShorthandCloser,
|
|
19
|
+
} from './shorthand-types.js';
|
|
20
|
+
|
|
21
|
+
import {
|
|
22
|
+
type CSSSeparatorTokens,
|
|
23
|
+
type CSSCodeAst,
|
|
24
|
+
isCSSCodeAst,
|
|
25
|
+
createCssValueAST,
|
|
26
|
+
valueTextNode,
|
|
27
|
+
getFullText,
|
|
28
|
+
} from '../tokenizers/index.js';
|
|
29
|
+
import { evaluateAst } from './shorthands-ast-evaluation.js';
|
|
30
|
+
import {
|
|
31
|
+
DataTypeType,
|
|
32
|
+
type DataType,
|
|
33
|
+
unorderedListPredicate,
|
|
34
|
+
universalDataType,
|
|
35
|
+
DEFAULT_LAYER_SEPERATOR,
|
|
36
|
+
} from '../css-data-types/index.js';
|
|
37
|
+
import {
|
|
38
|
+
type CssEdge,
|
|
39
|
+
type CssCorner,
|
|
40
|
+
CSS_PROPERTY_DELIMITER,
|
|
41
|
+
EDGE_SHORTHAND_EDGES,
|
|
42
|
+
CORNER_SHORTHAND_CORNERS,
|
|
43
|
+
EDGE_SHORTHAND_INDICES_BY_LENGTH,
|
|
44
|
+
} from './shorthand-css-data.js';
|
|
45
|
+
import {
|
|
46
|
+
NoDataTypeMatchError,
|
|
47
|
+
NoMandatoryPartMatchError,
|
|
48
|
+
InvalidIntersectionValueError,
|
|
49
|
+
InvalidEdgesInputLengthError,
|
|
50
|
+
} from './shorthand-parser-errors.js';
|
|
51
|
+
|
|
52
|
+
export const matchDataType = <V>(
|
|
53
|
+
dataType: DataType,
|
|
54
|
+
astNodes: EvaluatedAst<V>[],
|
|
55
|
+
index: number,
|
|
56
|
+
prevDataType?: DataTypeType,
|
|
57
|
+
) => dataType.predicate(astNodes[index]!.value, index, astNodes, prevDataType);
|
|
58
|
+
|
|
59
|
+
const getDataTypeMatch = <V>(
|
|
60
|
+
astNodes: EvaluatedAst<V>[],
|
|
61
|
+
index: number,
|
|
62
|
+
parts: ShorthandPart<V>[],
|
|
63
|
+
prevDataType: DataTypeType,
|
|
64
|
+
): DataTypeMatch => {
|
|
65
|
+
for (let i = 0; i < parts.length; i++) {
|
|
66
|
+
let matchAmount = 0;
|
|
67
|
+
if ((matchAmount = Number(matchDataType(parts[i]!.dataType, astNodes, index, prevDataType))) > 0) {
|
|
68
|
+
return { matchAmount, matchIndex: i };
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return { matchAmount: 1, matchIndex: -1 };
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
export const isOpenedInitial = <V, T extends string>(opened: OpenedShorthand<V, T>, prop: T, dataType: DataType) => {
|
|
76
|
+
const openedAst = opened[prop] as EvaluatedAst<V>[];
|
|
77
|
+
return openedAst.length === 1 && openedAst[0]!.value.text === dataType.initial;
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
export const getInitialAst = <V>(value: string): EvaluatedAst<V>[] => {
|
|
81
|
+
return createCssValueAST(value).map((node) => ({ value: node, isImplicit: true }));
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
const setInitialOpenedProps = <V, T extends string>(
|
|
85
|
+
shorthandProp: string,
|
|
86
|
+
parts: ShorthandPart<V>[],
|
|
87
|
+
opened: OpenedShorthand<V>,
|
|
88
|
+
shallow?: boolean,
|
|
89
|
+
): OpenedShorthand<V, T> => {
|
|
90
|
+
for (const part of parts) {
|
|
91
|
+
const props = shallow || !part.openedProps ? [part.prop] : part.openedProps;
|
|
92
|
+
for (const prop of props) {
|
|
93
|
+
if (opened[prop] === undefined) {
|
|
94
|
+
if (!part.mandatory) {
|
|
95
|
+
const initialAst = getInitialAst<V>(part.dataType.initial);
|
|
96
|
+
opened[prop] = part.multipleItems ? initialAst : initialAst[0]!;
|
|
97
|
+
} else {
|
|
98
|
+
throw new NoMandatoryPartMatchError(shorthandProp, prop);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return opened;
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
const setCommonProps = <V, T extends string>(
|
|
108
|
+
parts: ShorthandPart<V>[],
|
|
109
|
+
nodes: EvaluatedAst<V>[],
|
|
110
|
+
opened: OpenedShorthand<V>,
|
|
111
|
+
): OpenedShorthand<V, T> => {
|
|
112
|
+
for (let i = 0; i < parts.length && nodes.length > 0; i++) {
|
|
113
|
+
const { prop } = parts[i]!;
|
|
114
|
+
if (opened[prop] === undefined) {
|
|
115
|
+
let commonNode: EvaluatedAst<V> | undefined;
|
|
116
|
+
if ((commonNode = nodes.shift())) {
|
|
117
|
+
opened[prop] = commonNode;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return opened;
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
export const edgesShorthandOpener =
|
|
126
|
+
<V, T extends string>(prop: string, corners?: boolean): SimpleShorthandOpenerInner<V, T> =>
|
|
127
|
+
(astNodes) => {
|
|
128
|
+
if (astNodes.length < 1 || astNodes.length > 4) {
|
|
129
|
+
throw new InvalidEdgesInputLengthError(prop, astNodes.length);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const [propPrefix, propSuffix] = prop.split(CSS_PROPERTY_DELIMITER);
|
|
133
|
+
const prefix = propPrefix + CSS_PROPERTY_DELIMITER;
|
|
134
|
+
const suffix = propSuffix ? CSS_PROPERTY_DELIMITER + propSuffix : '';
|
|
135
|
+
const edgeIndices = EDGE_SHORTHAND_INDICES_BY_LENGTH[astNodes.length - 1]!;
|
|
136
|
+
const edges = !corners ? EDGE_SHORTHAND_EDGES : CORNER_SHORTHAND_CORNERS;
|
|
137
|
+
|
|
138
|
+
const edgeProp = (edge: CssEdge | CssCorner) => `${prefix}${edge}${suffix}` as T;
|
|
139
|
+
const edgeValue = (index: number) => astNodes[edgeIndices[index]!]!;
|
|
140
|
+
|
|
141
|
+
return {
|
|
142
|
+
[edgeProp(edges[0])]: edgeValue(0),
|
|
143
|
+
[edgeProp(edges[1])]: edgeValue(1),
|
|
144
|
+
[edgeProp(edges[2])]: edgeValue(2),
|
|
145
|
+
[edgeProp(edges[3])]: edgeValue(3),
|
|
146
|
+
} as SimpleOpenedShorthand<V>;
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
export const intersectionBeforeOpenerCheck =
|
|
150
|
+
<V>(prop: string, dataTypes: DataType[]): BeforeOpenerCheck<V> =>
|
|
151
|
+
(astNodes) => {
|
|
152
|
+
const validateValue = (value: CSSCodeAst, dataType: DataType) => {
|
|
153
|
+
if (!dataType.predicate(value)) {
|
|
154
|
+
throw new InvalidIntersectionValueError(prop, value.text);
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
if (astNodes.length === 1) {
|
|
159
|
+
for (const dataType of dataTypes) {
|
|
160
|
+
validateValue(astNodes[0]!.value, dataType);
|
|
161
|
+
}
|
|
162
|
+
} else if (astNodes.length > 1 && dataTypes.length === astNodes.length) {
|
|
163
|
+
for (let i = 0; i < dataTypes.length; i++) {
|
|
164
|
+
validateValue(astNodes[i]!.value, dataTypes[i]!);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
export const splitSimpleShorthandOpener =
|
|
170
|
+
<V, T extends string>(props: string[]): SimpleShorthandOpenerInner<V, T> =>
|
|
171
|
+
(astNodes) => {
|
|
172
|
+
const opened: SimpleOpenedShorthand<V> = {};
|
|
173
|
+
for (const prop of props) {
|
|
174
|
+
opened[prop] = astNodes[0]!;
|
|
175
|
+
}
|
|
176
|
+
return opened;
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
export const splitShorthandOpener =
|
|
180
|
+
<V, T extends string>(props: string[]): ShorthandOpenerInner<V, T> =>
|
|
181
|
+
(astNodes) => {
|
|
182
|
+
const opened: OpenedShorthand<V> = {};
|
|
183
|
+
for (const prop of props) {
|
|
184
|
+
opened[prop] = astNodes;
|
|
185
|
+
}
|
|
186
|
+
return opened;
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
export const singleKeywordShorthandOpener =
|
|
190
|
+
<V, T extends string>(
|
|
191
|
+
keywordValueMap: Record<string, Record<T, string>>,
|
|
192
|
+
multipleItems = false,
|
|
193
|
+
): ShorthandOpenerInner<V, T> =>
|
|
194
|
+
(astNodes) => {
|
|
195
|
+
const opened: OpenedShorthand<V> = {};
|
|
196
|
+
const keywordValues = keywordValueMap[astNodes[0]!.value.text]!;
|
|
197
|
+
const props = Object.keys(keywordValues) as T[];
|
|
198
|
+
for (const prop of props) {
|
|
199
|
+
const initialAst = getInitialAst<V>(keywordValues[prop]);
|
|
200
|
+
opened[prop] = multipleItems ? initialAst : initialAst[0]!;
|
|
201
|
+
}
|
|
202
|
+
return opened;
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
export const unorderedListShorthandOpener =
|
|
206
|
+
<V, T extends string>(
|
|
207
|
+
parts: ShorthandPart<V>[],
|
|
208
|
+
{ shallow, commonValue }: UnorderedListShorthandOptions = {},
|
|
209
|
+
): ShorthandOpenerInner<V, T> =>
|
|
210
|
+
(astNodes, api) => {
|
|
211
|
+
let opened: OpenedShorthand<V> = {};
|
|
212
|
+
|
|
213
|
+
const unfoundParts = [...parts];
|
|
214
|
+
const commonMatch = commonValue ? unorderedListPredicate(commonValue) : () => false;
|
|
215
|
+
const commonNodes: EvaluatedAst<V>[] = [];
|
|
216
|
+
let prevDataType: DataTypeType = DataTypeType.Unknown;
|
|
217
|
+
for (let index = 0; index < astNodes.length; ) {
|
|
218
|
+
let currNode = astNodes[index]!;
|
|
219
|
+
if (commonValue && commonMatch(currNode.value)) {
|
|
220
|
+
commonNodes.push(astNodes[index++]!);
|
|
221
|
+
continue;
|
|
222
|
+
}
|
|
223
|
+
const dataTypeMatch: DataTypeMatch = getDataTypeMatch(astNodes, index, unfoundParts, prevDataType);
|
|
224
|
+
const { matchAmount, matchIndex } = dataTypeMatch;
|
|
225
|
+
const foundPart = unfoundParts[matchIndex];
|
|
226
|
+
if (matchIndex !== -1 && foundPart) {
|
|
227
|
+
let matchLength = matchAmount;
|
|
228
|
+
const { prop, dataType, partOpener, beforeOpenerCheck, multipleItems, multipleSplit } = foundPart;
|
|
229
|
+
beforeOpenerCheck?.(astNodes);
|
|
230
|
+
if (dataType.prefix && currNode.value.text === dataType.prefix.prefixChar) {
|
|
231
|
+
currNode = astNodes[++index]!;
|
|
232
|
+
matchLength--;
|
|
233
|
+
}
|
|
234
|
+
const nodes = matchLength === 1 ? currNode : astNodes.slice(index, index + matchLength);
|
|
235
|
+
if (shallow || !partOpener) {
|
|
236
|
+
opened[prop] = multipleItems
|
|
237
|
+
? ((!multipleSplit ? opened[prop] || [] : []) as EvaluatedAst<V>[]).concat(nodes)
|
|
238
|
+
: nodes;
|
|
239
|
+
} else {
|
|
240
|
+
opened = {
|
|
241
|
+
...opened,
|
|
242
|
+
...partOpener(Array.isArray(nodes) ? nodes : [nodes], api),
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
unfoundParts.splice(matchIndex, 1);
|
|
246
|
+
prevDataType = dataType.dataType;
|
|
247
|
+
index += matchLength;
|
|
248
|
+
} else {
|
|
249
|
+
throw new NoDataTypeMatchError(currNode.value.text);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
if (commonValue) {
|
|
254
|
+
opened = setCommonProps(parts, commonNodes, opened);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
return opened;
|
|
258
|
+
};
|
|
259
|
+
|
|
260
|
+
export const getShorthandLayers = <V>(
|
|
261
|
+
astNodes: EvaluatedAst<V>[],
|
|
262
|
+
seperator = DEFAULT_LAYER_SEPERATOR,
|
|
263
|
+
): EvaluatedAst<V>[][] => {
|
|
264
|
+
const layers: EvaluatedAst<V>[][] = [];
|
|
265
|
+
let layerIndex = 0;
|
|
266
|
+
for (const node of astNodes) {
|
|
267
|
+
if (node.value.text === seperator) {
|
|
268
|
+
layerIndex++;
|
|
269
|
+
continue;
|
|
270
|
+
}
|
|
271
|
+
if (!layers[layerIndex]) {
|
|
272
|
+
layers[layerIndex] = [];
|
|
273
|
+
}
|
|
274
|
+
layers[layerIndex]!.push(node);
|
|
275
|
+
}
|
|
276
|
+
return layers;
|
|
277
|
+
};
|
|
278
|
+
|
|
279
|
+
export const getOpenedLayer = <V, T extends string>(
|
|
280
|
+
opened: OpenedShorthand<V, T>,
|
|
281
|
+
index: number,
|
|
282
|
+
multipleItemProps?: T[],
|
|
283
|
+
): OpenedShorthand<V, T> | undefined => {
|
|
284
|
+
const layer: OpenedShorthand<V> = {};
|
|
285
|
+
const props = Object.keys(opened) as T[];
|
|
286
|
+
let hasValue = false;
|
|
287
|
+
for (const prop of props) {
|
|
288
|
+
const value = opened[prop];
|
|
289
|
+
if (!value) {
|
|
290
|
+
continue;
|
|
291
|
+
}
|
|
292
|
+
if (multipleItemProps && multipleItemProps.includes(prop)) {
|
|
293
|
+
const valueInIndex = (value as EvaluatedAst<V>[])[index];
|
|
294
|
+
if (!Array.isArray(valueInIndex)) {
|
|
295
|
+
if (index === 0) {
|
|
296
|
+
layer[prop] = value;
|
|
297
|
+
}
|
|
298
|
+
} else {
|
|
299
|
+
layer[prop] = valueInIndex;
|
|
300
|
+
}
|
|
301
|
+
} else {
|
|
302
|
+
layer[prop] = index === 0 && !Array.isArray(value) ? value : (value as EvaluatedAst<V>[])[index]!;
|
|
303
|
+
}
|
|
304
|
+
if (layer[prop]) {
|
|
305
|
+
hasValue = true;
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
return hasValue ? layer : undefined;
|
|
309
|
+
};
|
|
310
|
+
|
|
311
|
+
export const layersShorthandOpener =
|
|
312
|
+
<V, T extends string>(
|
|
313
|
+
prop: string,
|
|
314
|
+
singleLayerOpener: ShorthandOpenerInner<V, T>,
|
|
315
|
+
singleLayerParts: ShorthandPart<V>[],
|
|
316
|
+
lastLayerOpener?: ShorthandOpenerInner<V, T>,
|
|
317
|
+
lastLayerParts?: ShorthandPart<V>[],
|
|
318
|
+
): ShorthandOpenerInner<V, T> =>
|
|
319
|
+
(astNodes, api) => {
|
|
320
|
+
const layers = getShorthandLayers(astNodes);
|
|
321
|
+
let openedLayers = (!lastLayerOpener ? layers : layers.slice(0, -1)).map((layer) =>
|
|
322
|
+
setInitialOpenedProps(prop, singleLayerParts, singleLayerOpener(layer, api)),
|
|
323
|
+
);
|
|
324
|
+
if (lastLayerOpener) {
|
|
325
|
+
openedLayers = openedLayers.concat([
|
|
326
|
+
setInitialOpenedProps(prop, lastLayerParts || [], lastLayerOpener(layers[layers.length - 1]!, api)),
|
|
327
|
+
]);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
if (layers.length === 1) {
|
|
331
|
+
return openedLayers[0]!;
|
|
332
|
+
}
|
|
333
|
+
const opened: OpenedShorthand<V> = {};
|
|
334
|
+
for (const layer of openedLayers) {
|
|
335
|
+
const layerProps = Object.keys(layer) as T[];
|
|
336
|
+
for (const prop of layerProps) {
|
|
337
|
+
const existingValue = opened[prop];
|
|
338
|
+
const propValue = layer[prop] as EvaluatedAst<V>;
|
|
339
|
+
if (!existingValue) {
|
|
340
|
+
opened[prop] = propValue;
|
|
341
|
+
} else {
|
|
342
|
+
if (!Array.isArray(propValue)) {
|
|
343
|
+
opened[prop] = Array.isArray(existingValue)
|
|
344
|
+
? existingValue.concat(propValue)
|
|
345
|
+
: [existingValue, propValue];
|
|
346
|
+
} else {
|
|
347
|
+
opened[prop] = Array.isArray((existingValue as EvaluatedAst<V>[])[0])
|
|
348
|
+
? (existingValue as EvaluatedAst<V>[]).concat([propValue])
|
|
349
|
+
: [existingValue as EvaluatedAst<V>, propValue];
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
return opened;
|
|
355
|
+
};
|
|
356
|
+
|
|
357
|
+
const getShorthandPartsProps = <V, T extends string>(parts: ShorthandPart<V, T>[], shallow?: boolean) => {
|
|
358
|
+
let partsProps: string[] = [];
|
|
359
|
+
for (const part of parts) {
|
|
360
|
+
partsProps = partsProps.concat(shallow || !part.openedProps ? part.prop : part.openedProps);
|
|
361
|
+
}
|
|
362
|
+
return partsProps;
|
|
363
|
+
};
|
|
364
|
+
|
|
365
|
+
const openSingleKeywordShorthand = <V, T extends string>(
|
|
366
|
+
shorthandProp: string,
|
|
367
|
+
partProps: string[],
|
|
368
|
+
astNodes: EvaluatedAst<V>[],
|
|
369
|
+
api: ParseShorthandAPI<V>,
|
|
370
|
+
part?: ShorthandPart<V, T>,
|
|
371
|
+
): SimpleOpenedShorthand<V, T> => {
|
|
372
|
+
let opened: SimpleOpenedShorthand<V> = {};
|
|
373
|
+
|
|
374
|
+
if (astNodes.length === 1) {
|
|
375
|
+
const node = astNodes[0]!;
|
|
376
|
+
const universalPart: ShorthandPart<V> = {
|
|
377
|
+
prop: shorthandProp,
|
|
378
|
+
dataType: universalDataType,
|
|
379
|
+
partOpener: splitSimpleShorthandOpener(partProps),
|
|
380
|
+
};
|
|
381
|
+
/* Identify shorthand single-keyword with predicate */
|
|
382
|
+
const matchingPart =
|
|
383
|
+
part && part.dataType.predicate(node.value)
|
|
384
|
+
? part
|
|
385
|
+
: universalPart.dataType.predicate(node.value)
|
|
386
|
+
? universalPart
|
|
387
|
+
: undefined;
|
|
388
|
+
if (matchingPart) {
|
|
389
|
+
/* Return the opened single-keyword shorthand, using opener if it exists */
|
|
390
|
+
opened = matchingPart.partOpener ? matchingPart.partOpener([node], api) : { [matchingPart.prop]: node };
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
return opened;
|
|
395
|
+
};
|
|
396
|
+
|
|
397
|
+
export const createShorthandOpener =
|
|
398
|
+
<V, T extends string>({
|
|
399
|
+
prop,
|
|
400
|
+
singleKeywordPart,
|
|
401
|
+
parts,
|
|
402
|
+
shorthandOpener,
|
|
403
|
+
}: ShorthandOpenerData<V, T>): ShorthandOpener<V, T> =>
|
|
404
|
+
(shortHand, api, shallow) => {
|
|
405
|
+
/* Evaluate the full input AST */
|
|
406
|
+
const astNodes = evaluateAst(shortHand, api);
|
|
407
|
+
|
|
408
|
+
/* Try opening the shorthand as a single keyword and return it if so */
|
|
409
|
+
const singleKeywordOpened = openSingleKeywordShorthand(
|
|
410
|
+
prop,
|
|
411
|
+
getShorthandPartsProps(parts, shallow),
|
|
412
|
+
astNodes,
|
|
413
|
+
api,
|
|
414
|
+
singleKeywordPart,
|
|
415
|
+
);
|
|
416
|
+
if (Object.keys(singleKeywordOpened).length > 0) {
|
|
417
|
+
return singleKeywordOpened;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
// TODO: Catch errors and return some value on error?
|
|
421
|
+
|
|
422
|
+
/* Open the shorthand using the provided method */
|
|
423
|
+
const opened = shorthandOpener(astNodes, api, parts, shallow);
|
|
424
|
+
|
|
425
|
+
/* Return the opened shorthand, after setting missing initial values */
|
|
426
|
+
return setInitialOpenedProps(prop, parts, opened, shallow);
|
|
427
|
+
};
|
|
428
|
+
|
|
429
|
+
export const createShorthandOpenerFromPart = <V, T extends string>(
|
|
430
|
+
part: ShorthandPart<V, T>,
|
|
431
|
+
): SimpleShorthandOpener<V, T> => {
|
|
432
|
+
return createShorthandOpener({
|
|
433
|
+
prop: part.prop,
|
|
434
|
+
parts: [part],
|
|
435
|
+
shorthandOpener: (astNodes, api, _parts, shallow) =>
|
|
436
|
+
part.partOpener ? part.partOpener(astNodes, api, shallow) : ({} as OpenedShorthand<V, T>),
|
|
437
|
+
}) as SimpleShorthandOpener<V, T>;
|
|
438
|
+
};
|
|
439
|
+
|
|
440
|
+
export const getOpenedNode = <V>(
|
|
441
|
+
nodeOrNodes: OpenedShorthandValue<V>,
|
|
442
|
+
api: ParseShorthandAPI<V>,
|
|
443
|
+
detachExpressions = false,
|
|
444
|
+
multiExpressions: string[] = [],
|
|
445
|
+
): CSSAstNode<V>[] => {
|
|
446
|
+
if (Array.isArray(nodeOrNodes)) {
|
|
447
|
+
return nodeOrNodes.reduce(
|
|
448
|
+
(values, node) => values.concat(getOpenedNode(node, api, detachExpressions, multiExpressions)),
|
|
449
|
+
[] as CSSAstNode<V>[],
|
|
450
|
+
);
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
const { origin } = nodeOrNodes;
|
|
454
|
+
if (!origin || detachExpressions) {
|
|
455
|
+
return [nodeOrNodes.value];
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
const expression = api.toString(origin);
|
|
459
|
+
if (multiExpressions.includes(expression)) {
|
|
460
|
+
return [];
|
|
461
|
+
}
|
|
462
|
+
if (api.getValue(origin).length > 1) {
|
|
463
|
+
multiExpressions.push(expression);
|
|
464
|
+
}
|
|
465
|
+
return [origin];
|
|
466
|
+
};
|
|
467
|
+
|
|
468
|
+
export const getOpenedNodeValue = <V>(nodes: CSSAstNode<V>[], api: ParseShorthandAPI<V>): string =>
|
|
469
|
+
nodes
|
|
470
|
+
.reduce((value, node) => value + (isCSSCodeAst(node) ? getFullText(node) : ' ' + api.toString(node)), '')
|
|
471
|
+
.trim();
|
|
472
|
+
|
|
473
|
+
export const edgesShorthandCloser =
|
|
474
|
+
<V, T extends string = string>(prop: string, corners?: boolean): ShorthandCloser<V, T> =>
|
|
475
|
+
(opened, api, detachExpressions = false) => {
|
|
476
|
+
const [propPrefix, propSuffix] = prop.split(CSS_PROPERTY_DELIMITER);
|
|
477
|
+
const prefix = propPrefix + CSS_PROPERTY_DELIMITER;
|
|
478
|
+
const suffix = propSuffix ? CSS_PROPERTY_DELIMITER + propSuffix : '';
|
|
479
|
+
const edges = !corners ? EDGE_SHORTHAND_EDGES : CORNER_SHORTHAND_CORNERS;
|
|
480
|
+
const multiExpressions: string[] = [];
|
|
481
|
+
|
|
482
|
+
const edgeProp = (edge: CssEdge | CssCorner) => `${prefix}${edge}${suffix}` as T;
|
|
483
|
+
const edgeValue = (index: number) =>
|
|
484
|
+
getOpenedNode(opened[edgeProp(edges[index]!)], api, detachExpressions, multiExpressions);
|
|
485
|
+
|
|
486
|
+
const edgeNodes = [edgeValue(0), edgeValue(1), edgeValue(2), edgeValue(3)];
|
|
487
|
+
const edgeValues = edgeNodes.map((nodes) => getOpenedNodeValue(nodes, api));
|
|
488
|
+
if (edgeValues[3] === edgeValues[1]) {
|
|
489
|
+
edgeNodes.pop();
|
|
490
|
+
edgeValues.pop();
|
|
491
|
+
if (edgeValues[2] === edgeValues[0]) {
|
|
492
|
+
edgeNodes.pop();
|
|
493
|
+
edgeValues.pop();
|
|
494
|
+
if (edgeValues[1] === edgeValues[0]) {
|
|
495
|
+
edgeNodes.pop();
|
|
496
|
+
edgeValues.pop();
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
return fixAstNodesPositions(
|
|
502
|
+
edgeNodes.filter((nodes) => nodes.length > 0).map((nodes) => nodes[0]!),
|
|
503
|
+
api,
|
|
504
|
+
);
|
|
505
|
+
};
|
|
506
|
+
|
|
507
|
+
export const shorthandCloserTemplate = <T extends string>(
|
|
508
|
+
strings: TemplateStringsArray,
|
|
509
|
+
...keys: string[]
|
|
510
|
+
): ShorthandCloserTemplate<T> => ({ strings, keys }) as ShorthandCloserTemplate<T>;
|
|
511
|
+
|
|
512
|
+
export const createShorthandCloserTemplateFromParts = <V, T extends string>(
|
|
513
|
+
parts: ShorthandPart<V, T>[],
|
|
514
|
+
): ShorthandCloserTemplate<T> => {
|
|
515
|
+
const keys = parts.map(({ prop }) => prop) as T[];
|
|
516
|
+
return {
|
|
517
|
+
keys,
|
|
518
|
+
strings: [''].concat(Array(keys.length).fill(' ')),
|
|
519
|
+
};
|
|
520
|
+
};
|
|
521
|
+
|
|
522
|
+
export const createShorthandCloser =
|
|
523
|
+
<V, T extends string = string, R extends OpenedShorthand<V, T> = OpenedShorthand<V, T>>(
|
|
524
|
+
template: ShorthandCloserTemplate<T>,
|
|
525
|
+
): ShorthandCloser<V, T, R> =>
|
|
526
|
+
(opened, api, detachExpressions = false) => {
|
|
527
|
+
const multiExpressions: string[] = [];
|
|
528
|
+
return fixAstNodesPositions(
|
|
529
|
+
(template.strings as string[]).reduce((nodes, currString, index) => {
|
|
530
|
+
const currKey = template.keys[index];
|
|
531
|
+
return currKey === undefined
|
|
532
|
+
? nodes
|
|
533
|
+
: nodes.concat(
|
|
534
|
+
valueTextNode(currString),
|
|
535
|
+
getOpenedNode(opened[currKey], api, detachExpressions, multiExpressions),
|
|
536
|
+
);
|
|
537
|
+
}, [] as CSSAstNode<V>[]),
|
|
538
|
+
api,
|
|
539
|
+
);
|
|
540
|
+
};
|
|
541
|
+
|
|
542
|
+
export const fixAstNodesPositions = <V>(
|
|
543
|
+
nodes: readonly CSSAstNode<V>[],
|
|
544
|
+
api: ParseShorthandAPI<V>,
|
|
545
|
+
start = 0,
|
|
546
|
+
): CSSAstNode<V>[] => {
|
|
547
|
+
let currPosition = start;
|
|
548
|
+
const fixedNodes: CSSAstNode<V>[] = [];
|
|
549
|
+
|
|
550
|
+
nodes.forEach((node) => {
|
|
551
|
+
let nodeText = '';
|
|
552
|
+
|
|
553
|
+
if (isCSSCodeAst(node)) {
|
|
554
|
+
nodeText = node.text.trim();
|
|
555
|
+
if (nodeText.length === 0) {
|
|
556
|
+
return;
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
const before: CSSSeparatorTokens[] = [];
|
|
560
|
+
if (fixedNodes.length > 0 && nodeText !== ',') {
|
|
561
|
+
// Trailing spaces are added only after the first valid node
|
|
562
|
+
before.push({
|
|
563
|
+
type: 'space',
|
|
564
|
+
value: ' ',
|
|
565
|
+
start: currPosition,
|
|
566
|
+
end: currPosition + 1,
|
|
567
|
+
});
|
|
568
|
+
currPosition++;
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
let args: CSSCodeAst[] = [];
|
|
572
|
+
if (node.type === 'call') {
|
|
573
|
+
args = fixAstNodesPositions(
|
|
574
|
+
node.args,
|
|
575
|
+
api,
|
|
576
|
+
// Current position + function name + (
|
|
577
|
+
currPosition + node.name.length + 1,
|
|
578
|
+
) as CSSCodeAst[];
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
fixedNodes.push({
|
|
582
|
+
...node,
|
|
583
|
+
...(nodeText === '/' ? { type: '/' } : nodeText === ',' ? { type: ',' } : {}),
|
|
584
|
+
text: nodeText,
|
|
585
|
+
start: currPosition,
|
|
586
|
+
end: currPosition + nodeText.length,
|
|
587
|
+
before,
|
|
588
|
+
...(args.length > 0 ? { args } : {}),
|
|
589
|
+
});
|
|
590
|
+
} else {
|
|
591
|
+
nodeText = api.toString(node);
|
|
592
|
+
if (fixedNodes.length > 0) {
|
|
593
|
+
currPosition++; // To account for a space before non-first expression nodes
|
|
594
|
+
}
|
|
595
|
+
fixedNodes.push(node);
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
currPosition += nodeText.length;
|
|
599
|
+
});
|
|
600
|
+
|
|
601
|
+
return fixedNodes;
|
|
602
|
+
};
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import type { CSSCodeAst } from '../tokenizers/index.js';
|
|
2
|
+
import type { AstItem, DataType } from '../css-data-types/index.js';
|
|
3
|
+
|
|
4
|
+
export type CSSAstNode<V> = CSSCodeAst | V;
|
|
5
|
+
|
|
6
|
+
export interface ParseShorthandAPI<V> {
|
|
7
|
+
isExpression: (item: CSSAstNode<V>) => item is V;
|
|
8
|
+
getValue: (item: V) => CSSCodeAst[];
|
|
9
|
+
toString: (item: V) => string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface EvaluatedAst<V> extends AstItem {
|
|
13
|
+
origin?: V;
|
|
14
|
+
/**
|
|
15
|
+
* When values are omitted from a CSS shorthand form,
|
|
16
|
+
* each “missing” sub-property is assigned its initial value.
|
|
17
|
+
* `isImplicit` specifies if the AST node represents such an implicit initial value.
|
|
18
|
+
*/
|
|
19
|
+
isImplicit?: boolean;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export type AstEvaluator<V, T> = (ast: CSSAstNode<V>[], api: ParseShorthandAPI<V>) => T[];
|
|
23
|
+
|
|
24
|
+
export interface DataTypeMatch {
|
|
25
|
+
matchAmount: number;
|
|
26
|
+
matchIndex: number;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export type OpenedShorthandValue<V> = EvaluatedAst<V> | EvaluatedAst<V>[];
|
|
30
|
+
export type OpenedShorthand<V, T extends string = string, R = OpenedShorthandValue<V>> = Record<T, R>;
|
|
31
|
+
export type SimpleOpenedShorthand<V, T extends string = string> = OpenedShorthand<V, T, EvaluatedAst<V>>;
|
|
32
|
+
|
|
33
|
+
type GenericShorthandOpener<S, V, T extends string = string, R = OpenedShorthand<V, T>> = (
|
|
34
|
+
shortHand: S[],
|
|
35
|
+
api: ParseShorthandAPI<V>,
|
|
36
|
+
shallow?: boolean,
|
|
37
|
+
) => R;
|
|
38
|
+
|
|
39
|
+
export type ShorthandOpener<V, T extends string = string, R = OpenedShorthand<V, T>> = GenericShorthandOpener<
|
|
40
|
+
CSSAstNode<V>,
|
|
41
|
+
V,
|
|
42
|
+
T,
|
|
43
|
+
R
|
|
44
|
+
>;
|
|
45
|
+
export type SimpleShorthandOpener<V, T extends string = string> = ShorthandOpener<V, T, SimpleOpenedShorthand<V, T>>;
|
|
46
|
+
export type ShorthandOpenerInner<V, T extends string = string, R = OpenedShorthand<V, T>> = GenericShorthandOpener<
|
|
47
|
+
EvaluatedAst<V>,
|
|
48
|
+
V,
|
|
49
|
+
T,
|
|
50
|
+
R
|
|
51
|
+
>;
|
|
52
|
+
export type SimpleShorthandOpenerInner<V, T extends string = string> = ShorthandOpenerInner<
|
|
53
|
+
V,
|
|
54
|
+
T,
|
|
55
|
+
SimpleOpenedShorthand<V, T>
|
|
56
|
+
>;
|
|
57
|
+
export type FullShorthandOpener<V, T extends string = string> = (
|
|
58
|
+
astNodes: EvaluatedAst<V>[],
|
|
59
|
+
api: ParseShorthandAPI<V>,
|
|
60
|
+
parts: ShorthandPart<V, T>[],
|
|
61
|
+
shallow?: boolean,
|
|
62
|
+
) => OpenedShorthand<V, T>;
|
|
63
|
+
|
|
64
|
+
export interface UnorderedListShorthandOptions {
|
|
65
|
+
shallow?: boolean;
|
|
66
|
+
commonValue?: string;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export type BeforeOpenerCheck<V> = (astNodes: EvaluatedAst<V>[]) => void;
|
|
70
|
+
|
|
71
|
+
export interface BasicPart {
|
|
72
|
+
prop: string;
|
|
73
|
+
dataType: DataType;
|
|
74
|
+
mandatory?: boolean;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export interface ShorthandPart<V, T extends string = string> extends BasicPart {
|
|
78
|
+
beforeOpenerCheck?: BeforeOpenerCheck<V>;
|
|
79
|
+
partOpener?: SimpleShorthandOpenerInner<V, T>;
|
|
80
|
+
openedProps?: T[];
|
|
81
|
+
multipleItems?: boolean;
|
|
82
|
+
multipleSplit?: boolean;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export interface ShorthandOpenerData<V, T extends string = string> {
|
|
86
|
+
prop: string;
|
|
87
|
+
singleKeywordPart?: ShorthandPart<V, T>;
|
|
88
|
+
parts: ShorthandPart<V, T>[];
|
|
89
|
+
shorthandOpener: FullShorthandOpener<V, T>;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export type GetShorthandOpener<T extends string> = <V>() => ShorthandOpener<V, T>;
|
|
93
|
+
export type GetSimpleShorthandOpener<T extends string> = <V>() => SimpleShorthandOpener<V, T>;
|
|
94
|
+
|
|
95
|
+
export type ShorthandCloserTemplate<T extends string> = {
|
|
96
|
+
strings: TemplateStringsArray | string[];
|
|
97
|
+
keys: T[];
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
export type ShorthandCloser<V, T extends string = string, R = SimpleOpenedShorthand<V, T>> = (
|
|
101
|
+
opened: R,
|
|
102
|
+
api: ParseShorthandAPI<V>,
|
|
103
|
+
detachExpressions?: boolean,
|
|
104
|
+
shallow?: boolean,
|
|
105
|
+
) => CSSAstNode<V>[];
|
|
106
|
+
|
|
107
|
+
export type GetShorthandCloser<T extends string> = <V>() => ShorthandCloser<V, T>;
|