Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make symbol library for use by Inkscape #18

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6,141 changes: 6,141 additions & 0 deletions affinity-network-symbols.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
120 changes: 120 additions & 0 deletions make-symbol-library/make-symbols.xsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
<!--

Converts a list of SVG files into a single SVG containing a
symbol element with each file's body, making the identifiers
inside each symbol unique across the whole document. This
single SVG can be placed into an Inkscape symbols directory,
and will make the symbols available to drag-and-drop into
Inkscape drawings.

Input format:

<files>
<file id="valid_identifier1">/entire/pathname/of/file.svg</file>
<file id="valid2">C:\A\Windows\Path\Works\Too.svg</file>
...
</files>

-->
<!-- started from https://stackoverflow.com/a/52715878 CC BY-SA Tomalak 2018 -->
<!-- (most) namespaces here get inherited by the output's root svg element -->
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:serif="http://www.serif.com/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
>

<xsl:output method="xml" version="1.0" encoding="utf-8"
indent="yes"
doctype-public="-//W3C//DTD SVG 1.1//EN"
doctype-system="http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" />

<xsl:template match="/">
<svg width="100%" height="100%" viewBox="0 0 300 300" version="1.1" xml:space="preserve" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:1.41421;">
<title>Affinity</title>
<desc>ecceman's free 2D symbols for computer network diagrams</desc>
<metadata>
<rdf:RDF>
<cc:Work rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
<dc:title>Affinity</dc:title>
<dc:date>2021-07-17</dc:date>
<dc:creator>
<cc:Agent>
<dc:title>ecceman</dc:title>
</cc:Agent>
</dc:creator>
<dc:rights rdf:resource="https://github.com/ecceman/affinity/blob/master/LICENSE"/>
<dc:source>https://github.com/ecceman/affinity</dc:source>
<dc:description>ecceman's free 2D symbols for computer network diagrams</dc:description>
</cc:Work>
</rdf:RDF>
</metadata>
<defs>


<xsl:apply-templates />


</defs>
</svg>
</xsl:template>

<xsl:template match="/files">
<xsl:apply-templates />
</xsl:template>

<xsl:template match="/files/file">
<!-- my default xmlns for this document is SVG, but only when I
added a specific svg namespace and used it here did I get
the proper behavior. -->
<svg:symbol>
<xsl:copy-of select="@id" />
<xsl:copy-of select="document(.)/svg:svg/@viewBox" />
<xsl:apply-templates select="document(.)/svg:svg/*">
<xsl:with-param name="idprefix" select="concat(@id,'__')" />
</xsl:apply-templates>
</svg:symbol>
</xsl:template>

<!-- to combine all these files, we need to make any id's of
elements inside them unique across the whole collection. so
we prefix all id attribute values with an idprefix.

references to those id's at this writing seem to be limited
to elements with clip-path attributes equal to
'url(#an-id-value)'. so we fix those references up too.
-->

<xsl:template match="@id">
<xsl:param name="idprefix" />
<xsl:attribute name="id"><xsl:value-of select="$idprefix" /><xsl:value-of select="." /></xsl:attribute>
</xsl:template>

<xsl:template match="@clip-path">
<xsl:param name="idprefix" />
<xsl:choose>
<xsl:when test="starts-with(., 'url(#')">
<xsl:variable name="rest" select="substring-after(., 'url(#')" />
<xsl:attribute name="clip-path">url(#<xsl:value-of select="$idprefix"/><xsl:value-of select="$rest"/></xsl:attribute>
</xsl:when>
<xsl:otherwise><xsl:copy-of select="."/></xsl:otherwise>
</xsl:choose>
</xsl:template>

<xsl:template match="@*|node()">
<xsl:param name="idprefix" />
<xsl:copy>
<xsl:apply-templates select="@*|node()">
<xsl:with-param name="idprefix" select="$idprefix" />
</xsl:apply-templates>
</xsl:copy>
</xsl:template>

</xsl:stylesheet>
81 changes: 81 additions & 0 deletions make-symbol-library/transform.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# Transform the svg files containing individual symbols into an
# Inkscape symbol library using make-symbols.xsl. Worked in 2021 on a
# Windows Server 2016 machine with Powershell 5. Might work with
# PowerShell Core on a Linux machine.
#
# To use: Change directories into the affinity directory, then run
# this script from there, e.g. make-symbol-library\transform.ps1. No
# parameters are necessary. After the script is done, take the SVG
# file named by the $out_svg variable below, and place it into your
# Inkscape symbols directory:
# e.g. c:\users\yourname\appdata\roaming\inkscape\symbols, or perhaps
# ~/.local/share/inkscape/symbols. See also
# https://wiki.inkscape.org/wiki/index.php/SymbolsDialog.

function filename_to_id($filename) {
# In this particular set of files, every filename is unique:
# circle\blue\*.svg are named c_*_blue.svg, making the directory
# path redundant. So a unique identifier only needs the file's
# basename. But we keep it so that everything will sort properly.
$keep_dirs_in_id = $true
if($keep_dirs_in_id) {
$x = Resolve-Path $filename -relative
$x = $x -replace "^.\\",""
$x = $x -replace "^svg\\",""
} else {
$x = Split-Path -Leaf $filename
}
$x = $x -replace "\.svg$",""
$x = $x -replace "[^A-Za-z0-9]","_"
$x
}

# started from https://mwallner.net/2017/03/31/merging-xml-with-xslt-and-powershell-ok/
$xsltfile = Join-Path $PSScriptRoot "make-symbols.xsl"
$svg_list_xml = Join-Path $(Get-Location) "svg-list.xml"
$out_svg = Join-Path $(Get-Location) "affinity-network-symbols.svg"
$svg_dir = Join-Path $(Get-Location) "svg"

write-output "Gathering SVGs under $svg_dir"

$XsltSettings = New-Object System.Xml.Xsl.XsltSettings
$XsltSettings.EnableDocumentFunction = 1

$xslt = New-Object System.Xml.Xsl.XslCompiledTransform;
$xslt.Load($xsltfile , $XsltSettings, $(New-Object System.Xml.XmlUrlResolver))

# https://petri.com/creating-custom-xml-net-powershell
[xml] $filelist = New-Object System.Xml.XmlDocument
$filelist.AppendChild($filelist.CreateXmlDeclaration("1.0", "UTF-8", $null)) | out-null
$files = $filelist.CreateNode("element", "files", $null)
$ngathered = 0
foreach($fn in (Get-ChildItem -r -file $svg_dir/*.svg | select -expand Fullname )) {
$f = $filelist.CreateElement("file", $null)
$f.InnerText = $fn
$id_att = $filelist.CreateAttribute("id", $null)
$id_att.Value = filename_to_id($fn)
$f.Attributes.Append($id_att) | out-null
$files.AppendChild($f) | out-null
$ngathered += 1
}
$filelist.AppendChild($files) | out-null
$filelist.save($svg_list_xml)

[System.Xml.XmlReaderSettings] $settings = [System.Xml.XmlReaderSettings]::new()
$settings.DtdProcessing = [System.Xml.DtdProcessing]::Ignore
[System.Xml.XmlReader]$file_list_reader = [System.Xml.XmlReader]::Create($svg_list_xml, $settings)
[System.Xml.XmlWriter]$xmlwriter = [System.Xml.XmlWriter]::Create($out_svg)
try {
$xslt.Transform($file_list_reader, $xmlwriter)
Write-Output "Gathered $ngathered symbols"
Write-Output "Symbol library written to $out_svg"
} catch {
$e = $_
while($e.innerexception) {
$e = $e.innerexception
}
throw $e
} finally {
$xmlwriter.close()
$file_list_reader.close()
}