mirror of
				https://github.com/Mibew/simple-icons.git
				synced 2025-10-31 18:41:07 +03:00 
			
		
		
		
	Lint collinear coordinates inside straight lines (#4589)
This commit is contained in:
		
							parent
							
								
									5b0d1d3e49
								
							
						
					
					
						commit
						45130ca86a
					
				
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										110
									
								
								.svglintrc.js
									
									
									
									
									
								
							
							
						
						
									
										110
									
								
								.svglintrc.js
									
									
									
									
									
								
							| @ -38,6 +38,14 @@ function removeLeadingZeros(number) { | |||||||
|   return number.toString().replace(/^(-?)(0)(\.?.+)/, '$1$3'); |   return number.toString().replace(/^(-?)(0)(\.?.+)/, '$1$3'); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /** | ||||||
|  |  * Given three points, returns if the middle one (x2, y2) is collinear | ||||||
|  |  *   to the line formed by the two limit points. | ||||||
|  |  **/ | ||||||
|  | function collinear(x1, y1, x2, y2, x3, y3) { | ||||||
|  |     return (x1 * (y2 - y3) + x2 * (y3 - y1) +  x3 * (y1 - y2)) === 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| if (updateIgnoreFile) { | if (updateIgnoreFile) { | ||||||
|   process.on('exit', () => { |   process.on('exit', () => { | ||||||
|     // ensure object output order is consistent due to async svglint processing
 |     // ensure object output order is consistent due to async svglint processing
 | ||||||
| @ -300,6 +308,108 @@ module.exports = { | |||||||
|               } |               } | ||||||
|             } |             } | ||||||
|           }, |           }, | ||||||
|  |           function(reporter, $, ast) { | ||||||
|  |             reporter.name = "collinear-segments"; | ||||||
|  | 
 | ||||||
|  |             const iconPath = $.find("path").attr("d"); | ||||||
|  |             if (!updateIgnoreFile && isIgnored(reporter.name, iconPath)) { | ||||||
|  |               return; | ||||||
|  |             } | ||||||
|  |              | ||||||
|  |             /** | ||||||
|  |              * Extracts collinear coordinates from SVG path straight lines | ||||||
|  |              *   (does not extracts collinear coordinates from curves). | ||||||
|  |              **/ | ||||||
|  |             const getCollinearSegments = (path) => { | ||||||
|  |               const { segments } = svgPath(path).unarc().unshort(), | ||||||
|  |                     collinearSegments = [], | ||||||
|  |                     straightLineCommands = 'HhVvLlMm', | ||||||
|  |                     zCommands = 'Zz'; | ||||||
|  |               let currLine = [], | ||||||
|  |                   currAbsCoord = [undefined, undefined], | ||||||
|  |                   _inStraightLine = false, | ||||||
|  |                   _nextInStraightLine = false; | ||||||
|  | 
 | ||||||
|  |               for (let s = 0; s < segments.length; s++) { | ||||||
|  |                 let seg = segments[s], | ||||||
|  |                     cmd = seg[0], | ||||||
|  |                     nextCmd = s + 1 < segments.length ? segments[s + 1][0] : null; | ||||||
|  |                  | ||||||
|  |                     if ('LM'.includes(cmd)) { | ||||||
|  |                       currAbsCoord[0] = seg[1]; | ||||||
|  |                       currAbsCoord[1] = seg[2]; | ||||||
|  |                     } else if ('lm'.includes(cmd)) { | ||||||
|  |                       currAbsCoord[0] = (!currAbsCoord[0] ? 0 : currAbsCoord[0]) + seg[1]; | ||||||
|  |                       currAbsCoord[1] = (!currAbsCoord[1] ? 0 : currAbsCoord[1]) + seg[2]; | ||||||
|  |                     } else if (cmd === 'H') { | ||||||
|  |                       currAbsCoord[0] = seg[1]; | ||||||
|  |                     } else if (cmd === 'h') { | ||||||
|  |                       currAbsCoord[0] = (!currAbsCoord[0] ? 0 : currAbsCoord[0]) + seg[1]; | ||||||
|  |                     } else if (cmd === 'V') { | ||||||
|  |                       currAbsCoord[1] = seg[1]; | ||||||
|  |                     } else if (cmd === 'v') { | ||||||
|  |                       currAbsCoord[1] = (!currAbsCoord[1] ? 0 : currAbsCoord[1]) + seg[1]; | ||||||
|  |                     } else if (cmd === 'C') { | ||||||
|  |                       currAbsCoord[0] = seg[5]; | ||||||
|  |                       currAbsCoord[1] = seg[6]; | ||||||
|  |                     } else if (cmd === 'c') { | ||||||
|  |                       currAbsCoord[0] = (!currAbsCoord[0] ? 0 : currAbsCoord[0]) + seg[5]; | ||||||
|  |                       currAbsCoord[1] = (!currAbsCoord[1] ? 0 : currAbsCoord[1]) + seg[6]; | ||||||
|  |                     } else if (cmd === 'Q') { | ||||||
|  |                       currAbsCoord[0] = seg[3]; | ||||||
|  |                       currAbsCoord[1] = seg[4]; | ||||||
|  |                     } else if (cmd === 'q') { | ||||||
|  |                       currAbsCoord[0] = (!currAbsCoord[0] ? 0 : currAbsCoord[0]) + seg[3]; | ||||||
|  |                       currAbsCoord[1] = (!currAbsCoord[1] ? 0 : currAbsCoord[1]) + seg[4]; | ||||||
|  |                     } else if (zCommands.includes(cmd)) { | ||||||
|  |                       // Overlapping in Z should be handled in another rule
 | ||||||
|  |                       currAbsCoord = [undefined, undefined]; | ||||||
|  |                     } else { | ||||||
|  |                       throw new Error(`"${cmd}" command not handled`) | ||||||
|  |                     } | ||||||
|  |                  | ||||||
|  |                 _nextInStraightLine = straightLineCommands.includes(nextCmd); | ||||||
|  |                 let _exitingStraightLine = (_inStraightLine && !_nextInStraightLine); | ||||||
|  |                 _inStraightLine = straightLineCommands.includes(cmd); | ||||||
|  | 
 | ||||||
|  |                 if (_inStraightLine) { | ||||||
|  |                   currLine.push([currAbsCoord[0], currAbsCoord[1]]); | ||||||
|  |                 } else { | ||||||
|  |                   if (_exitingStraightLine) { | ||||||
|  |                     if (!zCommands.includes(cmd)) { | ||||||
|  |                       currLine.push([currAbsCoord[0], currAbsCoord[1]]); | ||||||
|  |                     } | ||||||
|  |                     // Get collinear coordinates
 | ||||||
|  |                     for (let p = 0; p < currLine.length; p++) { | ||||||
|  |                       if (p === 0 || p === currLine.length - 1) { | ||||||
|  |                         continue; | ||||||
|  |                       } | ||||||
|  |                       let _collinearCoord = collinear(currLine[p - 1][0], | ||||||
|  |                                                       currLine[p - 1][1], | ||||||
|  |                                                       currLine[p][0], | ||||||
|  |                                                       currLine[p][1], | ||||||
|  |                                                       currLine[p + 1][0], | ||||||
|  |                                                       currLine[p + 1][1]) | ||||||
|  |                       if (_collinearCoord) { | ||||||
|  |                         collinearSegments.push(segments[s - currLine.length + p + 1]); | ||||||
|  |                       } | ||||||
|  |                     } | ||||||
|  |                   } | ||||||
|  |                   currLine = []; | ||||||
|  |                 } | ||||||
|  |               } | ||||||
|  |                | ||||||
|  |               return collinearSegments; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             getCollinearSegments(iconPath).forEach((segment) => { | ||||||
|  |               let segmentString = `${segment[0]}${segment[1]}`; | ||||||
|  |               if ('LlMm'.includes(segment[0])) { | ||||||
|  |                 segmentString += ` ${segment[2]}` | ||||||
|  |               } | ||||||
|  |               reporter.error(`Collinear segment "${segmentString}" in path (should be removed)`); | ||||||
|  |             }); | ||||||
|  |           }, | ||||||
|           function(reporter, $, ast) { |           function(reporter, $, ast) { | ||||||
|             reporter.name = "extraneous"; |             reporter.name = "extraneous"; | ||||||
| 
 | 
 | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user