Lucide icon processing workflow for Home Assistant
A short tutorial on processing Lucide icons for Home Assistant integration.
Converting strokes to fills
Home Assistant icon API provides only an option to provide single (or at most 2) paths for the svg icon, which is an issue for Lucide, because they are originally provided as a set of strokes. Therefore we need to convert the strokes with respective stroke-width
to a filled path and merge all of those together to achieve single, filled path. For this purpose we will use Inkscape. Here is a bash script, that does described process.
Inkscape
#!/usr/bin/env bash
mkdir ./output
cd ./icons || return
for i in *.svg
do
inkscape --actions="select-all;selection-ungroup;select-all;selection-ungroup;select-all;object-stroke-to-path;object-set-attribute:stroke-width,0;path-union;object-set-attribute:stroke-width,0;" --export-plain-svg --export-type=svg --export-filename=- $i > ../output/$i
echo "done with "$i
done
Sanitizing output
Now we have a new folder output
, which contains processed icons. However, we may sanitize output and provide additional useful attributes like tags, that are provided with the icons inside .json
files. To do this, I used Julia with following script:
using EzXML
using JSON
const ROOT_DIR = "/home/xxx"
const OUTPUT_DIR = "/output"
const INPUT_DIR = "/icons"
function process_icon(icon, root_dir, input_dir, output_dir)
attributes = JSON.parsefile("$root_dir$input_dir/$icon.json")
doc = readxml("$root_dir$output_dir/$icon.svg")
root = EzXML.root(doc)
# Remove unneccessary attributes from svg tag and set correct values
delete!(root, "version")
delete!(root, "id")
delete!(root, "stroke")
delete!(root, "stroke-width")
delete!(root, "stroke-linecap")
delete!(root, "stroke-linejoin")
root["fill"] = "currentColor"
root["tags"] = join(attributes["tags"], ",")
root["categories"] = join(attributes["categories"], ",")
els = elements(root)
#Remove defs tag
unlink!(els[1])
# Remove unneccessary attributes from path tag
delete!(els[2], "id")
delete!(els[2], "style")
delete!(els[2], "stroke-width")
write("$root_dir$output_dir/$icon.svg", doc)
end
filelist = readdir("$ROOT_DIR$INPUT_DIR/")
filelist = filter(x -> occursin(".svg", x), filelist)
for p in filelist
# Extract icon name from filename
icon = p[1:end-4]
process_icon(icon, ROOT_DIR, INPUT_DIR, OUTPUT_DIR)
end