Custom Perspective Icon SVG Syntax

I am working on converting an open-source icon library into the format necessary for Perspective, and I am not finding great documentation on syntax that the SVG renderer is ignoring vs accepting.

Here is the repo: https://lucide.dev

An example SVG:

<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <polyline points="22 12 18 12 15 21 9 3 6 12 2 12"></polyline>
</svg>

My example converted version:

<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="transparent" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
	<g class="icon" id="activity">
		<polyline points="22 12 18 12 15 21 9 3 6 12 2 12"></polyline>
	</g>
</svg>

But I am noticing that I can't get it to recognize the additional props in the <svg> tag other than viewBox. So I am always getting a greyed out icon, unless I add properties in the designer to override fill and stroke

EDIT: It looks like the icon selection popup renders the stroke attribute in the svg tag accurately, but not the fill.

EDIT #2: It looks like if I move the styling syntax in to the group tag it works as well, just not the svg tag... so maybe this is a bug?

Also a "Crash the designer" but that this identified, there are a handful of values that can cause the designer to crash when you open the icon viewer if found inside the icons svg.

For example this is where I have fill="transparent" in the group property of an icon

You can kind of see the error in the output console, but the whole designer freezes up and I can't go select the text to share the full exception.

It does this whenever I have fill=var(--icon) or fill="transparent"

These would make great support tickets :slight_smile:

You make a good point, but just imagine the benefit all the random people following behind me will get that don't have support contracts!

Also I just didn't have time to make a call when I posted it. lol

2 Likes

To anyone curious who comes after this, here is a simple python script that converts (at least that) folder of .svg files into the icon library structure needed for Perspective.

import os, re


# Iterate through a folder of svg files and add them to one svg repo
folder = './myFolder'
repo = './myFolder.svg'
repo = open(repo, 'w')

xml_base = '<?xml version="1.0" encoding="utf-8"?>\n' \
		   '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">\n' \
		   '\t<defs>\n' \
			'\t\t<style>\n' \
			'\t\t\t.icon { display: none }\n' \
			'\t\t\t.icon:target { display: inline }\n' \
			'\t\t</style>\n' \
			'\t</defs>\n'

repo.write(xml_base)

base_tab_count = 1

for filename in os.listdir(folder):
	if filename.endswith(".svg"):
		base_tabs = '\t' * base_tab_count
		repo.write('\n%s<!--%s-->\n' % (base_tabs, filename[:-4]))
		repo.write('%s<svg viewBox="0 0 24 24" width="24" height="24">\n' % base_tabs)
		svg = open(folder + '/' + filename, 'r')
		for line in svg:
			# If the line starts with <svg, use a regex to replace the xmlns and width/height attributes
			if line.startswith('<svg'):
				line = line.replace('<svg', '<g class="icon" id="%s"' % filename[:-4])
				line = re.sub(r' xmlns="[^"]+"', '', line)
				line = re.sub(r' width="[^"]+"', '', line)
				line = re.sub(r' height="[^"]+"', '', line)
				line = re.sub(r' viewBox="[^"]+"', '', line)
				line = re.sub(r' fill="[^"]+"', ' fill="none"', line)
				line = re.sub(r' stroke="[^"]+"', ' stroke="black"', line)

			if line.startswith('</svg'):
				line = line.replace('</svg', '</g')
			
			if line != '\n':
				repo.write("%s\t%s" % (base_tabs, line))
			
		svg.close()
		repo.write('\n%s</svg>\n' % base_tabs)

repo.write('\n</svg>')
repo.close()
1 Like

You are using 8.1.22 right? it has some recent svg changes^^

Why not use an XML library? I use xmltodict in python 3.9
Not sure if it's got any C dependencies... But otherwise there should be a Java XML library you can use

Yes sir 8.1.22

To be fair, GitHub copilot wrote most of the script, I was just along for the ride

3 Likes

This was beautiful. Thank you for sharing

What a bummer!:
image

That was a well delivered point

1 Like