├── Get-SVGL.psd1 ├── Get-SVGL.psm1 ├── LICENSE ├── Private ├── Api │ ├── Get-ApiResponseContent.ps1 │ └── Invoke-ApiRequest.ps1 ├── Find-Svg.ps1 ├── Format-ColumnOutput.ps1 ├── Handlers │ ├── Get-AngularCode.ps1 │ ├── Get-AstroCode.ps1 │ ├── Get-SvelteCode.ps1 │ ├── Get-VueCode.ps1 │ └── Parse-SvgContent.ps1 ├── Invoke-SelectedOption.ps1 ├── Options │ ├── Add-Options.ps1 │ └── Get-TypeScriptPreference.ps1 ├── Read-SelectedOption.ps1 ├── UI │ ├── Format-Table.ps1 │ ├── Get-UserSelection.ps1 │ └── Write-TableHeader.ps1 └── Write-SvgSearchResults.ps1 ├── Public └── Get-Svgl.ps1 ├── README.md ├── images ├── Preview-SVGL.gif └── TanStack_React_Component_Svg.jpg └── react.tsx /Get-SVGL.psd1: -------------------------------------------------------------------------------- 1 | @{ 2 | # Script module or binary module file associated with this manifest. 3 | RootModule = 'Get-SVGL.psm1' 4 | 5 | # Version number of this module. 6 | ModuleVersion = '1.1.2' 7 | 8 | # ID used to uniquely identify this module 9 | GUID = 'b3e13b76-75c1-43a9-af77-ffd3c6b7a16a' 10 | 11 | # Author of this module 12 | Author = 'spaansa' 13 | 14 | # Company or vendor of this module 15 | CompanyName = 'N/A' 16 | 17 | # Copyright statement for this module 18 | Copyright = 'See LICENSE file in the project root' 19 | 20 | # Description of the functionality provided by this module 21 | Description = 'PowerShell module for accessing the SVGL API to search for SVG logos' 22 | 23 | # Minimum version of the Windows PowerShell engine required by this module 24 | PowerShellVersion = '7.0' 25 | 26 | # Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export. 27 | FunctionsToExport = @('Get-Svgl') 28 | 29 | # Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export. 30 | CmdletsToExport = @() 31 | 32 | # Variables to export from this module 33 | VariablesToExport = @() 34 | 35 | # Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export. 36 | AliasesToExport = 'svgl' 37 | 38 | # Private data to pass to the module specified in RootModule/ModuleToProcess 39 | PrivateData = @{ 40 | PSData = @{ 41 | # Tags applied to this module. These help with module discovery in online galleries. 42 | Tags = @('SVG', 'Logo', 'API', "SVGL", "React", "Astro", "Vue", "Angular", "Svelte") 43 | 44 | # A URL to the license for this module. 45 | LicenseUri = 'https://github.com/spaansba/SVGL-PowerShell/blob/main/LICENSE' 46 | 47 | # A URL to the main website for this project. 48 | ProjectUri = 'https://github.com/spaansba/SVGL-PowerShell' 49 | 50 | # ReleaseNotes of this module 51 | ReleaseNotes = 'Initial release of the SVGL PowerShell module' 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Get-SVGL.psm1: -------------------------------------------------------------------------------- 1 | # Get the path to the module 2 | $ModulePath = $PSScriptRoot 3 | New-Alias -Name "svgl" -Value "Get-Svgl" 4 | 5 | # Load private functions from the root Private directory only (no subdirectories) 6 | $PrivateFunctionsPath = Join-Path -Path $ModulePath -ChildPath 'Private' 7 | if (Test-Path -Path $PrivateFunctionsPath) { 8 | $PrivateFunctions = Get-ChildItem -Path $PrivateFunctionsPath -Filter '*.ps1' -Depth 0 -ErrorAction SilentlyContinue 9 | foreach ($Function in $PrivateFunctions) { 10 | try { 11 | . $Function.FullName 12 | } 13 | catch { 14 | Write-Error -Message "Failed to import function $($Function.FullName): $_" 15 | } 16 | } 17 | } 18 | 19 | # Load all public functions 20 | $PublicFunctionsPath = Join-Path -Path $ModulePath -ChildPath 'Public' 21 | if (Test-Path -Path $PublicFunctionsPath) { 22 | $PublicFunctions = Get-ChildItem -Path $PublicFunctionsPath -Filter '*.ps1' -Recurse -ErrorAction SilentlyContinue 23 | foreach ($Function in $PublicFunctions) { 24 | try { 25 | . $Function.FullName 26 | } 27 | catch { 28 | Write-Error -Message "Failed to import function $($Function.FullName): $_" 29 | } 30 | } 31 | } 32 | 33 | # Export public functions 34 | $PublicFunctions | ForEach-Object { 35 | Export-ModuleMember -Function $_.BaseName 36 | } 37 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 Bart Spaans 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Private/Api/Get-ApiResponseContent.ps1: -------------------------------------------------------------------------------- 1 | function Get-ApiResponseContent { 2 | param ( 3 | [Parameter(Mandatory = $true)] 4 | [PSObject]$Response 5 | ) 6 | 7 | if ($Response.PSObject.Properties.Name -contains "data") { 8 | return $Response.data 9 | } 10 | 11 | return $Response 12 | } -------------------------------------------------------------------------------- /Private/Api/Invoke-ApiRequest.ps1: -------------------------------------------------------------------------------- 1 | # Helper function to process web requests 2 | function Invoke-ApiRequest { 3 | param ( 4 | [Parameter(Mandatory = $true)] 5 | [string]$Uri, 6 | 7 | [Parameter()] 8 | [string]$Method = "Get", 9 | 10 | [Parameter()] 11 | [object]$Body, 12 | 13 | [Parameter()] 14 | [hashtable]$Headers 15 | ) 16 | 17 | . "$PSScriptRoot.\Get-ApiResponseContent.ps1" 18 | 19 | try { 20 | if ($Method -eq "Get") { 21 | $response = Invoke-WebRequest -Uri $Uri -UseBasicParsing 22 | return $response.Content 23 | } 24 | else { 25 | $response = Invoke-RestMethod -Uri $Uri -Method $Method -Body $Body -Headers $Headers 26 | return Get-ApiResponseContent -Response $response 27 | } 28 | } 29 | catch { 30 | Write-Host "Error making request to $Uri : $_" -ForegroundColor Red 31 | return $null 32 | } 33 | } -------------------------------------------------------------------------------- /Private/Find-Svg.ps1: -------------------------------------------------------------------------------- 1 | 2 | Function Find-Svg { 3 | param ( 4 | [string]$Search 5 | ) 6 | Write-Host "Searching for '$Search'..." -ForegroundColor Cyan 7 | $uri = "https://api.svgl.app?search=$Search" 8 | 9 | try { 10 | $response = Invoke-RestMethod -Uri $uri -Method Get 11 | 12 | if ($response -is [array]) { 13 | return $response 14 | } 15 | else { 16 | return @($response) 17 | } 18 | } 19 | catch { 20 | return @() 21 | } 22 | } -------------------------------------------------------------------------------- /Private/Format-ColumnOutput.ps1: -------------------------------------------------------------------------------- 1 | function Format-ColumnOutput { 2 | param ( 3 | [Parameter(Mandatory = $true)] 4 | [array]$Items, 5 | 6 | [Parameter()] 7 | [int]$ColumnsPerRow = 3, 8 | 9 | [Parameter()] 10 | [int]$ColumnWidth = 25 11 | ) 12 | 13 | # Process items in groups based on ColumnsPerRow 14 | for ($i = 0; $i -lt $Items.Count; $i += $ColumnsPerRow) { 15 | $row = "" 16 | 17 | # Process each column in this row 18 | for ($j = 0; $j -lt $ColumnsPerRow; $j++) { 19 | $index = $i + $j 20 | 21 | # If we have an item for this position, add it with padding 22 | if ($index -lt $Items.Count) { 23 | $row += "{0,-$ColumnWidth}" -f $Items[$index] 24 | } 25 | } 26 | 27 | # Output the formatted row 28 | Write-Host $row 29 | } 30 | } -------------------------------------------------------------------------------- /Private/Handlers/Get-AngularCode.ps1: -------------------------------------------------------------------------------- 1 | function Get-AngularCode { 2 | param ( 3 | [Parameter(Mandatory = $true)] 4 | [string]$Content, 5 | 6 | [Parameter(Mandatory = $true)] 7 | [string]$ComponentName 8 | ) 9 | 10 | # Update SVG to include Angular binding for width and height 11 | $updatedSvgContent = $Content -replace ']*)>', '' 12 | $trimmedSvgContent = $updatedSvgContent.Trim() 13 | 14 | # Create template part with literal backticks 15 | $templateStart = "template: ``" 16 | $templateContent = "`n $trimmedSvgContent" 17 | $templateEnd = "`n ``," 18 | 19 | # Create Angular component 20 | $componentStart = @" 21 | import { Component, Input } from '@angular/core'; 22 | 23 | @Component({ 24 | selector: 'svg-${ComponentName}', 25 | standalone: true, 26 | "@ 27 | 28 | $componentEnd = @" 29 | 30 | }) 31 | export class ${ComponentName}Component { 32 | @Input({ required: true }) size: { width: number; height: number }; 33 | } 34 | "@ 35 | 36 | # Combine all parts 37 | $angularCode = $componentStart + $templateStart + $templateContent + $templateEnd + $componentEnd 38 | 39 | return $angularCode 40 | } 41 | -------------------------------------------------------------------------------- /Private/Handlers/Get-AstroCode.ps1: -------------------------------------------------------------------------------- 1 | function Get-AstroCode { 2 | param ( 3 | [Parameter(Mandatory = $true)] 4 | [string]$Content 5 | ) 6 | 7 | # Remove width and height attributes 8 | $cleanedSvg = $Content 9 | $cleanedSvg = $cleanedSvg -replace '\s*(width|height)="[^"]*"', '' 10 | $cleanedSvg = $cleanedSvg -replace "\s*(width|height)='[^']*'", '' 11 | $cleanedSvg = $cleanedSvg -replace '\s*(width|height)=\{[^}]*\}', '' 12 | 13 | # Add Astro.props to the SVG tag 14 | $cleanedSvg = $cleanedSvg -replace ']*)>', { 15 | param($match, $attrs) 16 | 17 | # Clean existing Astro.props if present 18 | $cleanedAttrs = $args[1] -replace '\s*\{?\.\.\.Astro\.props\}?\s*', '' 19 | 20 | # Return the modified SVG opening tag 21 | return "" 22 | } 23 | 24 | # Return the trimmed SVG 25 | return $cleanedSvg.Trim() 26 | } 27 | -------------------------------------------------------------------------------- /Private/Handlers/Get-SvelteCode.ps1: -------------------------------------------------------------------------------- 1 | function Get-SvelteCode { 2 | param ( 3 | [Parameter(Mandatory = $true)] 4 | [string]$Content, 5 | 6 | [Parameter()] 7 | [ValidateSet('ts', 'js')] 8 | [string]$Lang = 'ts' 9 | ) 10 | 11 | # Create Svelte component code 12 | $scriptLang = if ($Lang) { "" } else { "" } 13 | 14 | $svelteCode = @" 15 | $scriptLang 16 | $Content 17 | "@ 18 | 19 | return $svelteCode 20 | } 21 | -------------------------------------------------------------------------------- /Private/Handlers/Get-VueCode.ps1: -------------------------------------------------------------------------------- 1 | function Get-VueCode { 2 | param ( 3 | [Parameter(Mandatory = $true)] 4 | [string]$Content, 5 | 6 | [Parameter()] 7 | [ValidateSet('ts', 'js')] 8 | [string]$Lang = 'ts' 9 | ) 10 | 11 | # Create Vue component code 12 | $langAttribute = if ($Lang) { " lang=`"$Lang`"" } else { "" } 13 | 14 | # Parse SVG content to extract any styles 15 | $parsedContent = Parse-SvgContent -Content $Content -Framework "Vue" 16 | 17 | $vueCode = @" 18 | 19 | 22 | 23 | $($parsedContent.componentStyle) 24 | "@ 25 | 26 | return $vueCode 27 | } 28 | -------------------------------------------------------------------------------- /Private/Handlers/Parse-SvgContent.ps1: -------------------------------------------------------------------------------- 1 | function Parse-SvgContent { 2 | param ( 3 | [Parameter(Mandatory = $true)] 4 | [string]$Content, 5 | 6 | [Parameter(Mandatory = $true)] 7 | [ValidateSet("Vue", "Svelte")] 8 | [string]$Framework 9 | ) 10 | 11 | # Remove XML declaration if present 12 | if ($Content -match ']*\?>', '' 14 | } 15 | 16 | # Regular expression to match ' 18 | 19 | # Extract styles and store them in an array 20 | $styles = @() 21 | $matches = [regex]::Matches($Content, $styleTagRegex) 22 | 23 | foreach ($match in $matches) { 24 | $styleContent = $match.Groups[1].Value 25 | $styles += $styleContent 26 | } 27 | 28 | # Remove " 35 | } else { 36 | "" 37 | } 38 | 39 | # Return the result as a hashtable 40 | return @{ 41 | componentStyle = $componentStyle 42 | templateContent = $templateContent 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Private/Invoke-SelectedOption.ps1: -------------------------------------------------------------------------------- 1 | function Invoke-SelectedOption { 2 | param ( 3 | [Parameter(Mandatory=$true)] 4 | [System.Collections.Hashtable]$SelectedOption 5 | ) 6 | 7 | . "$PSScriptRoot\Handlers\Parse-SvgContent.ps1" 8 | . "$PSScriptRoot\Handlers\Get-VueCode.ps1" 9 | . "$PSScriptRoot\Handlers\Get-SvelteCode.ps1" 10 | . "$PSScriptRoot\Handlers\Get-AngularCode.ps1" 11 | . "$PSScriptRoot\Handlers\Get-AstroCode.ps1" 12 | . "$PSScriptRoot\Options\Get-TypeScriptPreference.ps1" 13 | . "$PSScriptRoot\Api\Invoke-ApiRequest.ps1" 14 | 15 | if ($SelectedOption) { 16 | switch ($SelectedOption.Action) { 17 | "URL" { 18 | # Copy SVG URL to clipboard 19 | $SelectedOption.SvgUrl | Set-Clipboard 20 | Write-Host "Copied SVG URL to clipboard: $($SelectedOption.SvgUrl)" -ForegroundColor Green 21 | Start-Process $SelectedOption.SvgUrl 22 | } 23 | "Raw SVG" { 24 | # Request SVG content and copy to clipboard 25 | $svgContent = Invoke-ApiRequest -Uri $SelectedOption.SvgUrl 26 | 27 | if ($svgContent) { 28 | $svgContent | Set-Clipboard 29 | Write-Host "Copied Raw SVG content to clipboard from: $($SelectedOption.SvgUrl)" -ForegroundColor Green 30 | } 31 | } 32 | "React" { 33 | $isTypeScript = Get-TypeScriptPreference 34 | 35 | # First get the SVG content 36 | $svgContent = Invoke-ApiRequest -Uri $SelectedOption.SvgUrl 37 | 38 | if ($svgContent) { 39 | # Prepare the request body 40 | $body = @{ 41 | code = $svgContent 42 | name = $SelectedOption.Title 43 | typescript = $isTypeScript 44 | } | ConvertTo-Json 45 | 46 | # Send request to SVGR API 47 | $headers = @{ 48 | "Content-Type" = "application/json" 49 | } 50 | 51 | $reactComponent = Invoke-ApiRequest -Uri "https://svgl.app/api/svgs/svgr" -Method Post -Body $body -Headers $headers 52 | 53 | if ($reactComponent) { 54 | # Copy React component to clipboard 55 | $reactComponent | Set-Clipboard 56 | 57 | $tsMessage = if ($isTypeScript) { "TypeScript" } else { "JavaScript" } 58 | Write-Host "Copied $tsMessage React component to clipboard for: $($SelectedOption.Title) ($($SelectedOption.LogoType))" -ForegroundColor Green 59 | } 60 | } 61 | } 62 | "Vue" { 63 | $isTypeScript = Get-TypeScriptPreference 64 | $lang = if ($isTypeScript) { 'ts' } else { 'js' } 65 | 66 | # First get the SVG content 67 | $svgContent = Invoke-ApiRequest -Uri $SelectedOption.SvgUrl 68 | 69 | if ($svgContent) { 70 | # Generate Vue component 71 | $vueComponent = Get-VueCode -Content $svgContent -Lang $lang 72 | 73 | # Copy Vue component to clipboard 74 | $vueComponent | Set-Clipboard 75 | 76 | $tsMessage = if ($isTypeScript) { "TypeScript" } else { "JavaScript" } 77 | Write-Host "Copied $tsMessage Vue component to clipboard for: $($SelectedOption.Title) ($($SelectedOption.LogoType))" -ForegroundColor Green 78 | } 79 | } 80 | "Svelte" { 81 | $isTypeScript = Get-TypeScriptPreference 82 | $lang = if ($isTypeScript) { 'ts' } else { 'js' } 83 | 84 | # First get the SVG content 85 | $svgContent = Invoke-ApiRequest -Uri $SelectedOption.SvgUrl 86 | 87 | if ($svgContent) { 88 | # Generate Svelte component 89 | $svelteComponent = Get-SvelteCode -Content $svgContent -Lang $lang 90 | 91 | # Copy Svelte component to clipboard 92 | $svelteComponent | Set-Clipboard 93 | 94 | $tsMessage = if ($isTypeScript) { "TypeScript" } else { "JavaScript" } 95 | Write-Host "Copied $tsMessage Svelte component to clipboard for: $($SelectedOption.Title) ($($SelectedOption.LogoType))" -ForegroundColor Green 96 | } 97 | } 98 | "Angular" { 99 | # First get the SVG content 100 | $svgContent = Invoke-ApiRequest -Uri $SelectedOption.SvgUrl 101 | 102 | if ($svgContent) { 103 | # Generate Angular component 104 | # Use title as component name (ensure valid name by removing special chars and capitalizing) 105 | $componentName = $SelectedOption.Title -replace '[^a-zA-Z0-9]', '' 106 | $componentName = (Get-Culture).TextInfo.ToTitleCase($componentName) 107 | 108 | $angularComponent = Get-AngularCode -Content $svgContent -ComponentName $componentName 109 | 110 | # Copy Angular component to clipboard 111 | $angularComponent | Set-Clipboard 112 | 113 | Write-Host "Copied Angular component to clipboard for: $($SelectedOption.Title) ($($SelectedOption.LogoType))" -ForegroundColor Green 114 | } 115 | } 116 | "Astro" { 117 | # First get the SVG content 118 | $svgContent = Invoke-ApiRequest -Uri $SelectedOption.SvgUrl 119 | 120 | if ($svgContent) { 121 | # Generate Astro component 122 | $astroComponent = Get-AstroCode -Content $svgContent 123 | 124 | # Copy Astro component to clipboard 125 | $astroComponent | Set-Clipboard 126 | 127 | Write-Host "Copied Astro component to clipboard for: $($SelectedOption.Title) ($($SelectedOption.LogoType))" -ForegroundColor Green 128 | } 129 | } 130 | } 131 | Write-Host "" 132 | } 133 | else { 134 | Write-Host "Invalid selection" -ForegroundColor Red 135 | } 136 | } -------------------------------------------------------------------------------- /Private/Options/Add-Options.ps1: -------------------------------------------------------------------------------- 1 | Function Add-Options { 2 | param ( 3 | [int]$StartNumber, 4 | [string]$LogoType, 5 | [string]$SvgUrl, 6 | [string]$Title, 7 | [string[]]$Actions, 8 | [System.Collections.ArrayList]$SvgOptions, 9 | [string]$TableFormat 10 | ) 11 | 12 | Write-Host ($TableFormat -f $LogoType, $StartNumber, ($StartNumber + 1), ($StartNumber + 2), ($StartNumber + 3), ($StartNumber + 4), ($StartNumber + 5), ($StartNumber + 6)) 13 | 14 | $offset = 0 15 | foreach ($action in $Actions) { 16 | [void]$SvgOptions.Add(@{ 17 | Number = $StartNumber + $offset 18 | LogoType = $LogoType 19 | Action = $action 20 | SvgUrl = $SvgUrl 21 | Title = $Title 22 | }) 23 | $offset += 1 24 | } 25 | 26 | return $SvgOptions 27 | } 28 | -------------------------------------------------------------------------------- /Private/Options/Get-TypeScriptPreference.ps1: -------------------------------------------------------------------------------- 1 | # Return true if typescript 2 | function Get-TypeScriptPreference { 3 | param() 4 | 5 | do { 6 | $response = Read-Host "Do you want TypeScript support? (y/n)" 7 | $response = $response.Trim().ToLower() 8 | 9 | if ($response -notin 'y', 'n', 'yes', 'no') { 10 | Write-Host "Please enter 'y' or 'n'" -ForegroundColor Yellow 11 | } 12 | } while ($response -notin 'y', 'n', 'yes', 'no') 13 | 14 | 15 | return $response -in 'y', 'yes' 16 | } -------------------------------------------------------------------------------- /Private/Read-SelectedOption.ps1: -------------------------------------------------------------------------------- 1 | function Read-SelectedOption { 2 | param( 3 | [Parameter(Mandatory=$true)] 4 | [System.Collections.ArrayList]$SvgOptions 5 | ) 6 | 7 | $selection = Read-Host "Enter the number of the SVG you want to copy" 8 | 9 | try { 10 | $selectionInt = [int]$selection 11 | $selectedOption = $SvgOptions | Where-Object { $_.Number -eq $selectionInt } | Select-Object -First 1 -Property * 12 | 13 | if ($selectedOption -and $selectedOption -isnot [System.Collections.Hashtable]) { 14 | $hashtable = @{} 15 | $selectedOption.PSObject.Properties | ForEach-Object { 16 | $hashtable[$_.Name] = $_.Value 17 | } 18 | $selectedOption = $hashtable 19 | } 20 | } 21 | catch { 22 | $selectedOption = $null 23 | } 24 | 25 | return $selectedOption 26 | } -------------------------------------------------------------------------------- /Private/UI/Format-Table.ps1: -------------------------------------------------------------------------------- 1 | function Format-Table { 2 | param ( 3 | [Parameter(Mandatory = $true)] 4 | [string]$Format, 5 | 6 | [Parameter(Mandatory = $true)] 7 | [string[]]$Values 8 | ) 9 | 10 | # Format the table row 11 | return $Format -f $Values 12 | } 13 | -------------------------------------------------------------------------------- /Private/UI/Get-UserSelection.ps1: -------------------------------------------------------------------------------- 1 | function Get-UserSelection { 2 | param ( 3 | [Parameter(Mandatory = $true)] 4 | [array]$Options 5 | ) 6 | 7 | if ($Options.Count -eq 0) { 8 | return $null 9 | } 10 | 11 | # Prompt for selection 12 | $selection = Read-Host "Enter the number of the SVG you want to use" 13 | 14 | # Convert selection to integer and find matching option 15 | try { 16 | $selectionInt = [int]$selection 17 | $selectedOption = $Options | Where-Object { $_.Number -eq $selectionInt } 18 | return $selectedOption 19 | } 20 | catch { 21 | Write-Host "Invalid selection" -ForegroundColor Red 22 | return $null 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Private/UI/Write-TableHeader.ps1: -------------------------------------------------------------------------------- 1 | function Write-TableHeader { 2 | param ( 3 | [Parameter(Mandatory = $true)] 4 | [string]$Format, 5 | 6 | [Parameter(Mandatory = $true)] 7 | [string[]]$Headers, 8 | 9 | [Parameter(Mandatory = $true)] 10 | [int[]]$Widths 11 | ) 12 | 13 | # Write the header row 14 | Write-Host (Format-Table -Format $Format -Values $Headers) 15 | 16 | # Create separator strings based on the width 17 | $separators = @() 18 | foreach ($width in $Widths) { 19 | $separators += "-" * $width 20 | } 21 | 22 | # Write the separator row 23 | Write-Host (Format-Table -Format $Format -Values $separators) 24 | } 25 | -------------------------------------------------------------------------------- /Private/Write-SvgSearchResults.ps1: -------------------------------------------------------------------------------- 1 | Function Write-SvgSearchResults { 2 | param ( 3 | [array]$Results, 4 | [string]$SearchTerm 5 | ) 6 | 7 | . "$PSScriptRoot\Options\Add-Options.ps1" 8 | 9 | $count = $Results.Count 10 | Write-Host "Found $count results for '$SearchTerm'" -ForegroundColor Green 11 | Write-Host "" 12 | 13 | if ($Results.Count -eq 0) { 14 | Write-Host "No results found for '$SearchTerm'" -ForegroundColor Yellow 15 | Write-Host "Try Get-Svgl for a list of svgs" -ForegroundColor Yellow 16 | Write-Host "Or try Get-Svgl -c to only return svgs in a category" -ForegroundColor Yellow 17 | Write-Host "" 18 | return 19 | } 20 | 21 | $svgOptions = [System.Collections.ArrayList]::new() 22 | $counter = 1 23 | $tableFormat = "{0,-15} │ {1,-3} │ {2,-7} │ {3,-5} │ {4,-3} │ {5,-6} │ {6,-5} │ {7,-7}" 24 | $headers = "Logo Type", "URL", "Raw SVG", "React", "Vue", "Svelte", "Astro", "Angular" 25 | $actions = $headers | Where-Object { $_ -ne "Logo Type" } 26 | $itemColors = "light", "dark" 27 | $itemTypes = "route", "wordmark" 28 | 29 | foreach ($item in $Results) { 30 | Write-Host "$($item.title)" -ForegroundColor Cyan 31 | Write-Host ($tableFormat -f $headers) 32 | Write-Host ($tableFormat -f ("─" * 15), "───", ("─" * 7), "─────", "───", "──────", "─────", "───────") 33 | 34 | foreach ($itemType in $itemTypes) { 35 | if ($item.PSObject.Properties.Name -contains $itemType) { 36 | 37 | $LogoTypePreFix = if ($itemType -ne "route") { ($itemType.Substring(0,1).ToUpper() + $itemType.Substring(1) + " ") } else { "" } 38 | 39 | if ($item.$itemType -is [PSCustomObject]) { 40 | foreach ($colorType in $itemColors) { 41 | if ($item.$itemType.PSObject.Properties.Name -contains $colorType) { 42 | $svgOptions = Add-Options -StartNumber $counter ` 43 | -Actions $actions ` 44 | -SvgOptions $svgOptions ` 45 | -LogoType ($LogoTypePreFix + ($colorType -replace '^.', { $_.Value.ToUpper() })) ` 46 | -SvgUrl $item.$itemType.$colorType ` 47 | -Title $item.title ` 48 | -TableFormat $tableFormat 49 | $counter += $actions.Length 50 | } 51 | } 52 | } 53 | else { 54 | $svgOptions = Add-Options -StartNumber $counter ` 55 | -Actions $actions ` 56 | -SvgOptions $svgOptions ` 57 | -LogoType ($LogoTypePreFix + "Default") ` 58 | -SvgUrl $item.$itemType ` 59 | -Title $item.title ` 60 | -TableFormat $tableFormat 61 | 62 | $counter += $actions.length 63 | } 64 | } 65 | } 66 | Write-Host "" 67 | } 68 | return $svgOptions 69 | 70 | } 71 | -------------------------------------------------------------------------------- /Public/Get-Svgl.ps1: -------------------------------------------------------------------------------- 1 | function Get-Svgl { 2 | [CmdletBinding()] 3 | param ( 4 | [Parameter(Position=0)] 5 | [string]$Search = "", 6 | 7 | [Parameter(Position=1)] 8 | [Alias("c")] 9 | [string]$Category = "" 10 | ) 11 | 12 | $validCategories = @( 13 | 'All', 'AI', 'Software', 'Hardware', 'Library', 'Hosting', 'Framework', 14 | 'Devtool', 'Monorepo', 'CMS', 'Database', 'Compiler', 'Crypto', 15 | 'Cybersecurity', 'Social', 'Entertainment', 'Browser', 'Language', 16 | 'Education', 'Design', 'Community', 'Marketplace', 'Music', 'Vercel', 17 | 'Google', 'Payment', 'VoidZero', 'Authentication', 'IoT', 'Config', 'Secrets' 18 | ) 19 | Write-Host "" 20 | if ($Search -ne "") { 21 | $Search = $Search.Substring(0,1).ToUpper() + $Search.Substring(1).ToLower() 22 | $results = Find-Svg -Search $Search 23 | $svgOptions = Write-SvgSearchResults -Results $results -SearchTerm $Search 24 | $selectedOption = Read-SelectedOption -SvgOptions $svgOptions 25 | Invoke-SelectedOption -SelectedOption $selectedOption 26 | return 27 | } 28 | 29 | $showAllCategories = $Category -eq "all" -or $Category -eq "All" -or $Category -eq "" 30 | 31 | if (-not $showAllCategories) { 32 | $Category = $Category.Substring(0,1).ToUpper() + $Category.Substring(1).ToLower() 33 | 34 | if ($validCategories -notcontains $Category) { 35 | Write-Error "Invalid category: $Category" 36 | Write-Host "Valid categories are:" -ForegroundColor Yellow 37 | Format-ColumnOutput -Items $validCategories 38 | return 39 | } 40 | } 41 | 42 | if ($showAllCategories) { 43 | Write-Host "Fetching all categories..." -ForegroundColor Cyan 44 | $uri = "https://api.svgl.app" 45 | } else { 46 | Write-Host "Fetching category: $Category" -ForegroundColor Cyan 47 | $uri = "https://api.svgl.app/category/$Category" 48 | } 49 | 50 | try { 51 | $response = Invoke-RestMethod -Uri $uri -Method Get 52 | 53 | if (-not $showAllCategories) { 54 | Write-Host "" 55 | Write-Host "$Category ($($response.Count))" -ForegroundColor Green 56 | $items = $response | Sort-Object -Property title 57 | $titles = $items | ForEach-Object { $_.title } 58 | Format-ColumnOutput -Items $titles 59 | Write-Host "" 60 | } 61 | else { 62 | $groupedByCategory = $response | Group-Object -property category | Sort-Object -Property Name 63 | 64 | foreach ($categoryGroup in $groupedByCategory) { 65 | Write-Host "$($categoryGroup.Name) ($($categoryGroup.Count))" -ForegroundColor Green 66 | $items = $categoryGroup.Group | Sort-Object -Property title 67 | $titles = $items | ForEach-Object { $_.title } 68 | Format-ColumnOutput -Items $titles 69 | Write-Host "" 70 | } 71 | 72 | Write-Host "Get-Svgl will return the svg" -ForegroundColor Cyan 73 | Write-Host "Or try Get-Svgl -c to only return svgs in a category" -ForegroundColor Cyan 74 | Write-Host "" 75 | } 76 | } 77 | catch { 78 | Write-Error "Error making request to SVGL API: $_" 79 | } 80 | } 81 | 82 | Export-ModuleMember -Function Get-Svgl 83 | 84 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SVGL-PowerShell (Get-SVGL) 2 | A PowerShell module for accessing the SVGL API to search for SVG logos. 3 | 4 | Required PowerShell version: 7+ 5 | 6 | [![PowerShell Gallery Version](https://img.shields.io/powershellgallery/v/Get-SVGL)](https://img.shields.io/powershellgallery/v/Get-SVGL) 7 | [![PowerShell Gallery](https://img.shields.io/powershellgallery/dt/Get-SVGL)](https://www.powershellgallery.com/packages/Get-SVGL) 8 | ![License](https://img.shields.io/github/license/spaansba/SVGL-PowerShell) 9 | 10 | ![](https://github.com/spaansba/SVGL-PowerShell/blob/main/images/Preview-SVGL.gif) 11 | 12 | ## Installation 13 | 14 | ### Manual Installation 15 | 16 | From [PowerShell Gallery](https://www.powershellgallery.com/packages/Get-SVGL): 17 | 18 | ```powershell 19 | Install-Module -Name Get-SVGL 20 | ``` 21 | 22 | ## Usage 23 | 24 | ### List All SVG Categories 25 | 26 | ```powershell 27 | Get-Svgl 28 | # Or use the alias 29 | svgl 30 | ``` 31 | 32 | ### List SVGs in a Specific Category 33 | 34 | ```powershell 35 | svgl -c Framework 36 | ``` 37 | 38 | ### Search for a Specific SVG 39 | 40 | To get the Tanstack react typescript component SVG we can do the following: 41 | 42 | ```powershell 43 | svgl Tanstack 44 | ``` 45 | 46 | Type `3` (see table) for the React component and `y` for the typescript version: 47 | Tanstack React component SVG copy 48 | 49 | #### Result (copied to clipboard) 50 | ``` 51 | import * as React from "react"; 52 | import type { SVGProps } from "react"; 53 | const TanStack = (props: SVGProps) => ; 54 | export default TanStack; 55 | ``` 56 | 57 | ## Credits 58 | 59 | Original SVGL API: [https://svgl.app/](https://svgl.app/) 60 | -------------------------------------------------------------------------------- /images/Preview-SVGL.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spaansba/SVGL-PowerShell/7148811218718ac5b80217b7642695e90c62721d/images/Preview-SVGL.gif -------------------------------------------------------------------------------- /images/TanStack_React_Component_Svg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spaansba/SVGL-PowerShell/7148811218718ac5b80217b7642695e90c62721d/images/TanStack_React_Component_Svg.jpg -------------------------------------------------------------------------------- /react.tsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spaansba/SVGL-PowerShell/7148811218718ac5b80217b7642695e90c62721d/react.tsx --------------------------------------------------------------------------------