@thejaredwilcurt/csslop 0.0.12 → 0.0.13

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.12",
5
+ "version": "0.0.13",
6
6
  "description": "Experimental CSS minification",
7
7
  "scripts": {
8
8
  "prestart": "node ./scripts/prestart.js",
@@ -162,6 +162,105 @@ function parseColorStop (stop) {
162
162
  };
163
163
  }
164
164
 
165
+ /**
166
+ * Splits a stop position into individual start and end tokens.
167
+ *
168
+ * @param {string|null} position The raw stop position text.
169
+ * @return {Array} The normalized position tokens.
170
+ */
171
+ function splitStopPositionTokens (position) {
172
+ if (position === null) {
173
+ return [];
174
+ }
175
+
176
+ return position.split(/\s+/).filter(Boolean);
177
+ }
178
+
179
+ /**
180
+ * Serializes a color stop from its color and normalized position tokens.
181
+ *
182
+ * @param {string} color The normalized stop color.
183
+ * @param {Array} positionTokens The normalized stop positions.
184
+ * @return {string} The serialized color stop.
185
+ */
186
+ function serializeColorStop (color, positionTokens) {
187
+ if (positionTokens.length === 0) {
188
+ return color;
189
+ }
190
+
191
+ return color + ' ' + positionTokens.join(' ');
192
+ }
193
+
194
+ /**
195
+ * Merges consecutive stops with the same color into a single logical stop.
196
+ *
197
+ * @param {Array} group The adjacent parsed stops for one color.
198
+ * @return {object} The merged stop data.
199
+ */
200
+ function mergeIdenticalStopGroup (group) {
201
+ const firstStop = group[0];
202
+ const lastStop = group[group.length - 1];
203
+ const firstPositionTokens = splitStopPositionTokens(firstStop.position);
204
+ const lastPositionTokens = splitStopPositionTokens(lastStop.position);
205
+
206
+ let positionTokens;
207
+ if (group.length === 1) {
208
+ positionTokens = firstPositionTokens;
209
+ } else {
210
+ const mergedTokens = [];
211
+ const startPosition = firstPositionTokens[0] || null;
212
+ const endPosition = lastPositionTokens[lastPositionTokens.length - 1] || null;
213
+
214
+ if (startPosition !== null) {
215
+ mergedTokens.push(startPosition);
216
+ }
217
+ if (endPosition !== null && endPosition !== startPosition) {
218
+ mergedTokens.push(endPosition);
219
+ }
220
+
221
+ positionTokens = mergedTokens;
222
+ }
223
+
224
+ return {
225
+ color: firstStop.color,
226
+ effectiveEndPosition: lastPositionTokens[lastPositionTokens.length - 1] || null,
227
+ positionTokens
228
+ };
229
+ }
230
+
231
+ /**
232
+ * Removes implied edge positions and rewrites repeated starts as `0`.
233
+ *
234
+ * @param {Array} mergedStops The merged stops to normalize.
235
+ * @return {Array} The serialized normalized stops.
236
+ */
237
+ function normalizeBoundaryPositionTokens (mergedStops) {
238
+ const result = [];
239
+ let previousEndPosition = null;
240
+
241
+ for (let stopIndex = 0; stopIndex < mergedStops.length; stopIndex++) {
242
+ const stop = mergedStops[stopIndex];
243
+ const isFirstStop = stopIndex === 0;
244
+ const isLastStop = stopIndex === mergedStops.length - 1;
245
+ const positionTokens = [...stop.positionTokens];
246
+
247
+ if (isFirstStop && positionTokens[0] === '0%') {
248
+ positionTokens.shift();
249
+ }
250
+ if (isLastStop && positionTokens[positionTokens.length - 1] === '100%') {
251
+ positionTokens.pop();
252
+ }
253
+ if (positionTokens.length > 0 && positionTokens[0] === previousEndPosition) {
254
+ positionTokens[0] = '0';
255
+ }
256
+
257
+ previousEndPosition = stop.effectiveEndPosition;
258
+ result.push(serializeColorStop(stop.color, positionTokens));
259
+ }
260
+
261
+ return result;
262
+ }
263
+
165
264
  /**
166
265
  * Serializes a parsed gradient stop back into normalized CSS text, ensuring a
167
266
  * separating space is preserved when a stop position is present.
@@ -222,67 +321,11 @@ function combineAdjacentIdenticalStops (args) {
222
321
  }
223
322
 
224
323
  const groups = groupConsecutiveIdenticalStops(stops);
225
- const hasMergeableGroup = groups.some((group) => {
226
- return group.length > 1;
324
+ const mergedStops = groups.map((group) => {
325
+ return mergeIdenticalStopGroup(group);
227
326
  });
228
- if (!hasMergeableGroup) {
229
- return args;
230
- }
231
-
232
- const result = [];
233
- let previousEndPosition = null;
234
-
235
- for (let groupIndex = 0; groupIndex < groups.length; groupIndex++) {
236
- const group = groups[groupIndex];
237
- const color = group[0].color;
238
- const isFirstGroup = groupIndex === 0;
239
- const isLastGroup = groupIndex === groups.length - 1;
240
327
 
241
- if (group.length === 1) {
242
- let position = group[0].position;
243
- if (position === '0%' && isFirstGroup) {
244
- position = null;
245
- }
246
- if (position === '100%' && isLastGroup) {
247
- position = null;
248
- }
249
- if (position !== null && position === previousEndPosition) {
250
- position = '0';
251
- }
252
- previousEndPosition = group[0].position;
253
- result.push(position ? color + ' ' + position : color);
254
- continue;
255
- }
256
-
257
- const firstPosition = group[0].position;
258
- const lastPosition = group[group.length - 1].position;
259
-
260
- let startPart = firstPosition;
261
- let endPart = lastPosition;
262
-
263
- if (startPart === '0%' && isFirstGroup) {
264
- startPart = null;
265
- }
266
- if (endPart === '100%' && isLastGroup) {
267
- endPart = null;
268
- }
269
- if (startPart !== null && startPart === previousEndPosition) {
270
- startPart = '0';
271
- }
272
-
273
- previousEndPosition = lastPosition;
274
-
275
- const positionParts = [startPart, endPart].filter((part) => {
276
- return part !== null;
277
- });
278
- if (positionParts.length > 0) {
279
- result.push(color + ' ' + positionParts.join(' '));
280
- } else {
281
- result.push(color);
282
- }
283
- }
284
-
285
- return result;
328
+ return normalizeBoundaryPositionTokens(mergedStops);
286
329
  }
287
330
 
288
331
  /**