@thejaredwilcurt/csslop 0.0.30 → 0.0.31

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/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@thejaredwilcurt/csslop",
3
3
  "main": "index.js",
4
4
  "type": "module",
5
- "version": "0.0.30",
5
+ "version": "0.0.31",
6
6
  "description": "Experimental CSS minification",
7
7
  "scripts": {
8
8
  "prestart": "node ./scripts/prestart.js",
@@ -5,6 +5,7 @@
5
5
  import { minifyValue } from '../value/minify.js';
6
6
 
7
7
  import { shorthandMap } from './config.js';
8
+ import { buildLayerPositionAndSize } from './image-layers.js';
8
9
 
9
10
  const BACKGROUND_POSITION_KEYWORDS = new Set(['left', 'center', 'right', 'top', 'bottom']);
10
11
  const BACKGROUND_REPEAT_KEYWORDS = new Set(['repeat', 'no-repeat', 'repeat-x', 'repeat-y', 'space', 'round']);
@@ -246,16 +247,7 @@ function buildBackgroundShorthandValue (valueMap, importantSuffix) {
246
247
  if (image && image !== 'none') {
247
248
  result.push(image);
248
249
  }
249
- if (position && position !== '0 0' && position !== '0% 0%') {
250
- result.push(position);
251
- }
252
- if (size && size !== 'auto') {
253
- if (position && position !== '0 0' && position !== '0% 0%') {
254
- result.push('/' + size);
255
- } else {
256
- result.push('0 0/' + size);
257
- }
258
- }
250
+ result.push(...buildLayerPositionAndSize(position, size));
259
251
  if (repeat && repeat !== 'repeat') {
260
252
  result.push(repeat);
261
253
  }
@@ -0,0 +1,79 @@
1
+ /**
2
+ * @file Shared grammar helpers for the layered image shorthands, `background` and `mask`, whose layers only accept a size behind a slash that follows a position.
3
+ */
4
+
5
+ /**
6
+ * The layer positions a shorthand may leave unstated, since they already match
7
+ * the initial position that the shorthand resets the layer to.
8
+ *
9
+ * @type {Set<string>}
10
+ */
11
+ const INITIAL_LAYER_POSITIONS = new Set(['0 0', '0% 0%']);
12
+
13
+ /**
14
+ * The shortest spelling of the initial layer position, used whenever a stated
15
+ * size needs a position in front of it.
16
+ *
17
+ * @type {string}
18
+ */
19
+ const SHORTEST_INITIAL_LAYER_POSITION = '0 0';
20
+
21
+ /**
22
+ * The layer size a shorthand may leave unstated, since it already matches the
23
+ * initial size that the shorthand resets the layer to.
24
+ *
25
+ * @type {string}
26
+ */
27
+ const INITIAL_LAYER_SIZE = 'auto';
28
+
29
+ /**
30
+ * Reduces a layer position to what the shorthand has to spell out, which is
31
+ * nothing at all while the position holds its initial value.
32
+ *
33
+ * @param {string} position The layer position, or a falsy value when the layer states none.
34
+ * @return {string} The position to write, or an empty string when it can be left out.
35
+ */
36
+ function resolveStatedLayerPosition (position) {
37
+ if (!position || INITIAL_LAYER_POSITIONS.has(position)) {
38
+ return '';
39
+ }
40
+ return position;
41
+ }
42
+
43
+ /**
44
+ * Reduces a layer size to what the shorthand has to spell out, which is nothing
45
+ * at all while the size holds its initial value.
46
+ *
47
+ * @param {string} size The layer size, or a falsy value when the layer states none.
48
+ * @return {string} The size to write, or an empty string when it can be left out.
49
+ */
50
+ function resolveStatedLayerSize (size) {
51
+ if (!size || size === INITIAL_LAYER_SIZE) {
52
+ return '';
53
+ }
54
+ return size;
55
+ }
56
+
57
+ /**
58
+ * Builds the position and size components of a layered image shorthand value.
59
+ * The layer grammar only reads a size directly behind a `/` that follows a
60
+ * position, so a stated size pulls the initial position back into the output
61
+ * whenever the layer states no position of its own.
62
+ *
63
+ * @param {string} position The layer position, or a falsy value when the layer states none.
64
+ * @param {string} size The layer size, or a falsy value when the layer states none.
65
+ * @return {Array} The shorthand components covering the position and the size.
66
+ */
67
+ function buildLayerPositionAndSize (position, size) {
68
+ const statedPosition = resolveStatedLayerPosition(position);
69
+ const statedSize = resolveStatedLayerSize(size);
70
+ if (statedSize) {
71
+ return [(statedPosition || SHORTEST_INITIAL_LAYER_POSITION) + '/' + statedSize];
72
+ }
73
+ if (statedPosition) {
74
+ return [statedPosition];
75
+ }
76
+ return [];
77
+ }
78
+
79
+ export { buildLayerPositionAndSize };
@@ -7,6 +7,7 @@ import { splitTopLevelComponents } from '../value/syntax.js';
7
7
 
8
8
  import { buildBackgroundShorthandValue } from './background.js';
9
9
  import { UNIFORM_VALUE_SHORTHANDS } from './config.js';
10
+ import { buildLayerPositionAndSize } from './image-layers.js';
10
11
 
11
12
  /**
12
13
  * @typedef {object} ShorthandComponents
@@ -124,26 +125,33 @@ function buildBackgroundValue ({ valueMap, importantSuffix }) {
124
125
  }
125
126
 
126
127
  /**
127
- * Builds a `mask` value, attaching the size after the position separator.
128
+ * Builds a `mask` value. A mask layer follows the same grammar as a background
129
+ * layer, so the image leads, the size only reads as a size while it sits behind
130
+ * a `/` that follows the position, and the repeat comes after both of them. A
131
+ * component holding its initial value is left out, since the shorthand already
132
+ * resets every longhand it covers back to that value.
128
133
  *
129
134
  * @param {ShorthandComponents} components The collected longhand values.
130
135
  * @return {string|null} The shorthand value, or null when it cannot be built.
131
136
  */
132
137
  function buildMaskValue ({ valueMap, importantSuffix }) {
133
138
  const image = valueMap.get('mask-image');
134
- const repeat = valueMap.get('mask-repeat');
135
- const size = valueMap.get('mask-size');
136
139
  if (!image) {
137
140
  return null;
138
141
  }
139
- let result = image;
140
- if (repeat) {
141
- result += ' ' + repeat;
142
+ const repeat = valueMap.get('mask-repeat');
143
+ const result = [];
144
+ if (image !== 'none') {
145
+ result.push(image);
146
+ }
147
+ result.push(...buildLayerPositionAndSize(valueMap.get('mask-position'), valueMap.get('mask-size')));
148
+ if (repeat && repeat !== 'repeat') {
149
+ result.push(repeat);
142
150
  }
143
- if (size) {
144
- result += '/' + size;
151
+ if (!result.length) {
152
+ return 'none' + importantSuffix;
145
153
  }
146
- return result + importantSuffix;
154
+ return result.join(' ') + importantSuffix;
147
155
  }
148
156
 
149
157
  /**