Created
October 18, 2024 06:02
-
-
Save mjblacker/e663676e99d6013dbfffc06e7455e9ea to your computer and use it in GitHub Desktop.
FSharp Iconify generator
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #load "FSharp.Keywords.fs" | |
| open System | |
| open System.IO | |
| open System.Text.Json | |
| open System.Text.RegularExpressions | |
| // string helpers from Glutinum | |
| let pascalize (input : string) = | |
| Regex.Replace( | |
| input, | |
| "(?:^|_|-| +)(.)", | |
| fun m -> m.Groups[1].Value.ToUpper() | |
| ) | |
| let capitalize (input : string) = | |
| if input.Length > 0 then | |
| (string input[0]).ToLower() + input.Substring(1) | |
| else | |
| input | |
| let camelize (input : string) = | |
| let word = pascalize input | |
| if word.Length > 0 then | |
| (string word[0]).ToLower() + word.Substring(1) | |
| else | |
| word | |
| let sanitizeKeyword (input : string) = | |
| if Set.contains input FSharp.Keywords.keywords then | |
| input + "_" | |
| else | |
| input | |
| let sanitizeIfStartWithNumber (value : string) = | |
| if Regex.IsMatch(value, "^\d") then | |
| "_" + value | |
| else | |
| value | |
| // Generate F# code | |
| let generateCode (iconSet: string) = | |
| try | |
| let iconSet = iconSet.ToLower() | |
| // Read the JSON file | |
| let jsonFile = $"node_modules/@iconify-json/{iconSet}/icons.json" | |
| let jsonText = File.ReadAllText(jsonFile) | |
| let jsonDocument = JsonDocument.Parse(jsonText) | |
| // Extract icon names | |
| let iconNames = | |
| jsonDocument.RootElement.GetProperty("icons").EnumerateObject() | |
| |> Seq.map (fun prop -> prop.Name) | |
| |> Seq.toList | |
| // PascalCase the module name | |
| let moduleName = iconSet |> pascalize | |
| // setup the new file to generate | |
| let sb = System.Text.StringBuilder() | |
| sb.AppendLine($"module Feliz.Iconify") |> ignore | |
| sb.AppendLine("") |> ignore | |
| sb.AppendLine($" [<RequireQualifiedAccess>]") |> ignore | |
| sb.AppendLine($" module {moduleName} = ") |> ignore | |
| for icon in iconNames do | |
| let cleanIconName = icon |> camelize |> sanitizeIfStartWithNumber |> sanitizeKeyword | |
| sb.AppendLine($" let [<Literal>] {cleanIconName} = \"{iconSet}--{icon}\"") |> ignore | |
| sb.ToString() |> Ok | |
| with | |
| | _ -> Error "Failed, ensure the iconSet has been installed using NPM/Yarn first" | |
| // get the arg for the name of the package | |
| let args = | |
| match fsi.CommandLineArgs |> Array.toList with | |
| | _::tail when tail.IsEmpty = false -> tail |> List.head |> Ok | |
| | _ -> Error "Please provide an installed icon set name as the argument" | |
| match args with | |
| | Ok iconSet -> | |
| // Generate and write the F# code to a file | |
| match generateCode iconSet with | |
| | Ok generatedCode -> | |
| let fileName = iconSet |> pascalize |> (+) <| "Icons.fs" | |
| File.WriteAllText(fileName, generatedCode) | |
| printfn $"F# code generated successfully in {fileName}" | |
| | Error msg -> | |
| printfn $"{msg}" | |
| | Error msg -> | |
| printfn $"{msg}" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment