Manual:Coding conventions/SVG
This page documents a MediaWiki development guideline, crafted over time by developer consensus (or sometimes by proclamation from a lead developer) |
This page describes the coding conventions used within files of the MediaWiki codebase written in SVG. See also the general conventions which apply to all programming and markup languages, including SVG.
We make use of SVGO as optimisation tool, see automated optimisation below.
Code structure
[edit]Minimal code as possible with readability in mind is the premise.
Example for simple optimised file – subtract.svg from OOUI:
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
<title>
subtract
</title>
<path d="M4 9h12v2H4z"/>
</svg>
For minimalists, exactly the same can be drawn with
<?xml version="1.0"?>
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20">
<path d="m4,9h12v2H4"/>
</svg>
Example for slightly more complex, optimised file – BetaFeatures screenshot template:
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="264" height="162" viewBox="0 0 264 162">
<title>
BetaFeatures screenshot template
</title>
<defs>
<clipPath id="jagged-edge">
<path d="M0 0v152l12 10 12-10 12 10 12-10 12 10 12-10 12 10 12-10 12 10 12-10 12 10 12-10 12 10 12-10 12 10 12-10 12 10 12-10 12 10 12-10 12 10 12-10V0z"/>
</clipPath>
</defs>
<g fill="#eaecf0" clip-path="url(#jagged-edge)">
<path id="background" fill="#fff" d="M0 0h264v162H0"/>
<path id="logo" d="M11 22c0-8 6-14 14-14s14 6 14 14-6 14-14 14-14-6-14-14M38 45v-5H13v5h25"/>
<path id="sidebar" d="M38 163V58H13v106h25"/>
<path id="personal-tools" d="M233 5h26v6h-26V5zM209 5h22v6h-22zM185 5h22v6h-22zM162 5h13v6h-13zM177 5h6v6h-6zM154 5h6v6h-6z"/>
<path id="search-input" d="M258 16v4h-92v-4h92m1-1h-94v6h94v-6z"/>
<path id="search-icon" d="M168 17h2v2h-2z"/>
<path id="article" d="M252 162V29H48v133z"/>
<path id="border" d="M0 0v162h264V0zm1 1h262v150.533l-11 9.166-12-10-12 10-12-10-12 10-12-10-12 10-12-10-12 10-12-10-12 10-12-10-12 10-12-10-12 10-12-10-12 10-12-10-12 10-12-10-12 10-11-9z"/>
</g>
</svg>
We will explain the different coding conventions in the following section.
Automated optimisation (SVGO)
[edit]SVGO was maintained by Kir Belevich (deepsweet[1]) and Lev Solntsev (GreLI[2]) from August 2012[3] to 2016[4][5] and since 2021 by Bogdan Chadkin (TrySound[6]).
How to use
[edit]Is it recommended to install svgo
from https://github.com/svg/svgo or from npm
for the command line.
There is also an in-browser demo to help with preview and general understanding of the tool at https://jakearchibald.github.io/svgomg/.
This should not be used to create production files however.
Safe plugins:
[edit]As some SVGO default plugins (options) might result in unexpected appearance with more complex SVGs, we differentiate between safe, considerably less-safe and unsafe plugins. Set the "transformPrecision" at least to 7 to reduce the rist of breaking files.[7] When using unsafe plugins it's recommended to verify before and after diffing per file to ensure visual quality.
Mentioning only plugins, that are changed from default setting or that might be counter-intuitive:
- Sorting attributes
sortAttrs
.
Enable by setting totrue
; disabled by default - Remove or cleanup
enable-background
attribute when possiblecleanupEnableBackground
.
Deprecated attribute, only supported by IE/Edge; enabled by default
See SVGO Readme for other enabled, safe plugins.
Plugins to consider carefully:
cleanupIDs
|
Remove unused and minify used IDs Might negatively affect readability[8] and breaks some files[9]; enabled by default |
removeRasterImages
|
As general rule dangerous, could cause data loss, some raster-images are difficult to spot[10]; disabled by default |
inlineStyles
|
Some users prefer to use CSS than inlineStyles, can reduce editability[11] |
removeDoctype
|
For SVG 1.1 there is not reason to remove it, however for the upcommong SVG2-draft it will be deapreciated[12] |
Unsafe rules to disable (don't use!):
convertPathData
|
Might cause (i) imprecise rendering, (ii) wrong rendering by librsvg[13], (iii) breaking files[14][15][16]; enabled by default |
cleanupListOfValues
|
Round/rewrite number lists breaks Wikimedia-renderin[17] |
convertShapeToPath
|
can reduce readability[18] and breaks files[19] |
removeXMLProcInst
|
Remove XML processing instructions, aka XML declaration[20][21] <?xml version="1.0" encoding="UTF-8"?> Issues when viewed as standalone file in some editors, also possible issues with MIME type interpretation Example: If the SVG doesn't start with an XML declaration, then its MIME type will be detected as text/plain rather than image/svg+xml by libmagic and consequently, MediaWiki's CSSMin CSS minifier. libmagic's default database currently requires that SVGs contain an XML declaration; disable by setting to false ; enabled by default
|
removeTitle
|
Remove <title> Problematic for accessibility reasons[22]; set to false ; enabled by default
|
removeDesc
|
Remove <desc> Problematic for accessibility reasons; set to false ; enabled by default
|
removeViewBox
|
Remove viewBox attributeResults in troublesome appearance in some browsers, therefore both, width /height and viewbox should be featured; set to false ; enabled by default
|
removeDimensions
|
Remove dimensions width /height when viewbox is availableAs above; set to false ; disabled by default
|
removeMetadata
|
Possible Copyright-Information[23] |
removeHiddenElems
|
Possible reference lines, editor data, real text before convertion, Copyright-informations[23] |
removeUnknownsAndDefaults
|
removes Flow-Text [24] |
cleanupNumericValues
|
breaks some files [25] |
minifyStyles
|
breaks some files[26] |
removeComments
|
reduces readability and possible removes reference lines, editor data, real text before convertion, Copyright-informations[27] |
removeEditorsNSData
|
reduces editability with GUI-SVG-Editors[28] |
collapseGroups
|
reduced readability and editability [29] and breaks some files[30] |
removeStyleElement
|
breaks some files[31] |
removeOffCanvasPaths
|
breaks some files[32] |
removeEmptyContainers
|
breaks some files[33][34] |
removeElementsByAttr
|
breaks some files[35] |
convertStyleToAttrs
|
breaks some files[36] |
convertTransform
|
breaks some files[37][38][39][40] |
cleanupNumericValues
|
breaks some files [41] |
inlineStyles
|
breaks some CSS-features[42] |
reusePaths
|
breaks some files [43] |
Exemplified safe configuration
[edit]Note that this is for SVGO v1.x; v2.x takes different CLI arguments:
$ svgo path/to/image.svg --disable={cleanupIDs,convertPathData,removeDesc,removeTitle,removeViewBox,removeXMLProcInst} --enable='sortAttrs' --pretty --final-newline
Use pretty
output for human readable code and in the process indent code by tabs.
Exemplified safe configuration (.svgo.config.js)
[edit]June 2023 - SVGO v3.0.0+ compatibility, amending to new cleanupIds
plugin name. (phab:T324899)
January 2022 - NPM run scripts enabled SVGO configuration. (phab:T246321)
/**
* SVGO Configuration
* Compatible to v3.0.0+
* Recommended options from:
* https://www.mediawiki.org/wiki/Manual:Coding_conventions/SVG#Exemplified_safe_configuration
*/
'use strict';
module.exports = {
plugins: [
{
// Set of built-in plugins enabled by default.
name: 'preset-default',
params: {
overrides: {
cleanupIds: false,
removeDesc: false,
removeTitle: false,
removeViewBox: false,
// If the SVG doesn't start with an XML declaration, then its MIME type will be detected as "text/plain" rather than "image/svg+xml" by libmagic and, consequently, MediaWiki's CSSMin CSS minifier.
// libmagic's default database currently requires that SVGs contain an XML declaration:
// https://github.com/threatstack/libmagic/blob/master/magic/Magdir/sgml#L5
removeXMLProcInst: false // https://phabricator.wikimedia.org/T327446
convertPathData: false // https://github.com/svg/svgo/issues/880 https://github.com/svg/svgo/issues/1487
removeMetadata: false // Copyright-Violation
removeHiddenElems: false // source for converted text2path
removeUnknownsAndDefaults: false // removes Flow-Text: https://commons.wikimedia.org/wiki/User:JoKalliauer/RepairFlowRoot
cleanupNumericValues: false // https://github.com/svg/svgo/issues/1080
minifyStyles: false //https://github.com/svg/svgo/issues/888
removeComments: false //reduces readability
removeEditorsNSData: false // https://github.com/svg/svgo/issues/1096
collapseGroups: false // https://github.com/svg/svgo/issues/1057
removeOffCanvasPaths: false //https://github.com/svg/svgo/issues/1732
removeEmptyContainers: false // https://github.com/svg/svgo/issues/1194 https://github.com/svg/svgo/issues/1618
convertTransform: fasle // https://github.com/svg/svgo/issues/988 https://github.com/svg/svgo/issues/1021
cleanupNumericValues: false // https://github.com/svg/svgo/issues/1080
inlineStyles: false // https://github.com/svg/svgo/issues/1486
}
}
},
'removeRasterImages',
'sortAttrs'
],
// Set whitespace according to Wikimedia Coding Conventions.
// @see https://github.com/svg/svgo/blob/main/lib/stringifier.js#L39 for available options.
js2svg: {
eol: 'lf',
finalNewline: true,
// Configure the indent to tabs (default 4 spaces) used by '--pretty' here.
indent: "\t",
pretty: true
},
multipass: true
}
Exemplified safe configuration (Gruntfile.js)
[edit]svgmin: {
options: {
js2svg: {
indent: '\t',
pretty: true
},
plugins: [ {
cleanupIDs: false
}, {
removeDesc: false
}, {
removeRasterImages: true
}, {
removeTitle: false
}, {
removeViewBox: false
}, {
removeXMLProcInst: false
}, {
sortAttrs: true
}, {
convertPathData: false // https://github.com/svg/svgo/issues/880
}, {
removeMetadata: false // Copyright-Violation
}, {
removeHiddenElems: false // source for converted text2path
}, {
removeUnknownsAndDefaults: false // removes Flow-Text
}, {
cleanupNumericValues: false // https://github.com/svg/svgo/issues/1080
}, {
minifyStyles: false //https://github.com/svg/svgo/issues/888
}, {
removeComments: false //reduces readability
}, {
removeEditorsNSData: false // https://github.com/svg/svgo/issues/1096
}, {
collapseGroups: false // https://github.com/svg/svgo/issues/1057
}, {
removeOffCanvasPaths: false //https://github.com/svg/svgo/issues/1732
}, {
removeEmptyContainers:false // https://github.com/svg/svgo/issues/1194 https://github.com/svg/svgo/issues/1618
}, {
convertTransform: fasle // https://github.com/svg/svgo/issues/988 https://github.com/svg/svgo/issues/1021
}, {
cleanupNumericValues: false // https://github.com/svg/svgo/issues/1080
}, {
inlineStyles: false // https://github.com/svg/svgo/issues/1486
} ]
}
}
Manual optimisation
[edit]Beyond automated optimising SVGs there are further steps to consider:
- retain the following code
xml:space="preserve"
,<!--
,<title
,\n
,\r
,\t
,<g
,visibility="hidden"
,opacity="0"
,display="none"
,requiredFeatures="
,<?xml version="1.0" encoding="UTF-8"?>
,<defs>
,<rect
,<style type="text/css"
,class="
,data-name=
,inkscape:label
,<rdf:RDF
,aria-label=
,<inkscape:grid
,<sodipodi:guide
,sodipodi:cx=
,sodipodi:cy=
,sodipodi:rx=
,sodipodi:ry=
,sodipodi:type="arc"
,vector-effect=
,inkscape:groupmode="layer"
,inkscape:label=
,sodipodi:role="line"
, see c:Help:SVG guideline - Remove
standalone="no"
from XML processing instruction, as it's default - Lowercase (for better gzipping) and shorten hex color values, if possible, e.g.
#fff
instead of#FFFFFF
. - Attributes that are the same for a group of elements can be applied to a common parent
<g>
instead, or sometimes even specified by the<svg
statement (see an example: CHE Bettens COA.svg).
This might reduce the editability or readability - Rely on defaults like
fill="#000"
andstroke-width="1"
. - The
<path d="…"/>
syntax is almost always shorter than the syntax of basic shapes like<polygon>
or even<rect>
, however<circle>
,<ellipse>
,<rect>
are generally more easy to read/edit, therfore there is generally prefered to use more specific ones. - Merge
<path d="…"/>
elements where applicable. Do not do that if the both path should be edited speratly. - Do not remove redundant
ry="…"
attribute when identical torx="…"
it get's more difficult to read/edit. - Remove not needed
fill-rule="…"
andclip-rule="…"
. These rules only have an effect on certain paths, e.g. when a path intersects itself. - Look for IEEE rounding errors like
0.999999998
or1.000000003
. Such numbers take up space without providing any additional information. They can almost always be cut off without visually changing anything. - Work with a non-fractional pixel grid while drawing, and align as much points as possible on this grid. These points have a much higher chance of being represented as short integer numbers in the resulting code.
- Pick a non-fractional grid so that it matches the features of an existing image, and scale or redraw shapes so that as many points as possible fall on the grid. The result might be misaligned and can be cropped using
viewBox="<left> <top> <width> <height>"
.
If you want to dig even deeper, there are more optimisations to compress delivery, such as:
- auto-closing paths (aka removing
z
for certain shapes), - use relative commands when creating paths (instead of absolute commands, e.g. "m" for "move by", instead of "M" for "move to"),
- optimising for compression backreferences
Other tools
[edit]Other tools that may be helpful to know about:
- SvgWorkAroundBot
- SVGOMG
- scour
- svgcleaner
- check Help:SVG guidelines#How to optimize for more options.
scour
[edit]Description and history
[edit]This optimizer was one of the first optimizers: Since 2009 it included with the installation of Inkscape, it can be used by saving Inkscape-files with "Optimized Inkscape SVG", and in 2013[45] seperated into an self-contained project available at https://github.com/scour-project/scour. It is maintained by the Inscape-Developer Patrick Storz (Ede123).[44]
How to use
[edit]You can use in the browser at https://svgworkaroundbot.toolforge.org/ or install it via pip install scour
from the command line (Linux-PC/Mac-PC/Windows).
safe plugins
[edit]Scour is a very cautious optimizer, however some plugins can still be break the file or remove important non-visible parts, to be on the safe side you can use scour -i input.svg -o output.svg --disable-simplify-colors --disable-style-to-xml --disable-group-collapsing --keep-editor-data --keep-unreferenced-defs --protect-ids-noninkscape --disable-embed-rasters --set-precision=8 --set-c-precision=8
svgcleaner
[edit]Description and history
[edit]This optimizer was developed from Jan 2012 to 2022 by Yevhenii Reizner.[46] It focusses on following the current w3c-Standards (SVG1.1).[47] Compared to scour or svgo it breaks less files[48], reduces the file size more[49] and the performance is magnitues faster.[50]
How to use
[edit]You can use in the browser at https://svgworkaroundbot.toolforge.org/ or download it from https://github.com/RazrFalcon/svgcleaner-gui/releases .
safe plugins
[edit]Files will be treated according to the standards, however sometimes file non-svg-elements which are important for reading and/or editing the file, to be on the safe side you can use svgcleaner input.svg output.svg --allow-bigger-file --indent yes --resolve-use no --apply-transform-to-gradients yes --apply-transform-to-shapes yes --convert-shapes no --group-by-style no --join-arcto-flags no --join-style-attributes no --merge-gradients yes --regroup-gradient-stops yes --remove-comments no --remove-declarations no --remove-default-attributes yes --remove-desc no --remove-dupl-cmd-in-paths yes --remove-dupl-fegaussianblur yes --remove-dupl-lineargradient yes --remove-dupl-radialgradient yes --remove-gradient-attributes yes --remove-invalid-stops yes --remove-invisible-elements no --remove-metadata no --remove-needless-attributes yes --remove-nonsvg-attributes no --remove-nonsvg-elements no --remove-text-attributes no --remove-title no --remove-unreferenced-ids no --remove-unresolved-classes yes --remove-unused-coordinates yes --remove-unused-defs yes --remove-version yes --remove-xmlns-xlink-attribute yes --simplify-transforms yes --trim-colors yes --trim-ids no --trim-paths yes --ungroup-defs yes --ungroup-groups no --use-implicit-cmds yes --list-separator comma --paths-to-relative yes --remove-unused-segments yes --convert-segments yes --apply-transform-to-paths yes --coordinates-precision 2 --paths-coordinates-precision 5 --properties-precision 3 --transforms-precision 7
References
[edit]- ↑ https://github.com/deepsweet
- ↑ https://github.com/GreLI
- ↑ https://github.com/svg/svgo/commit/b1f3a62809e5b6f73c4ebae4bc792cb18f5ce6c5
- ↑ Still maintained?
- ↑ Call for new maintainer(s)
- ↑ https://github.com/TrySound
- ↑ https://github.com/svg/svgo/issues/1021
- ↑ c:Help:SVG_guidelines#Invalid elements that should be replaced (id=)
- ↑ https://github.com/svg/svgo/issues/1195
- ↑ c:Help:SVG_guidelines#Optimizing SVGs that have already been uploaded (You should not change the appearance of the picture, see File:Oxygen15.04.1-computer-laptop.svg)
- ↑ c:Help:SVG_guidelines#Elements that should not be converted (CSS should in general not be converted)
- ↑ c:Help:SVG_guidelines#Useless elements that should be kept; there are different opinions about it, but it is necessary for https://validator.w3.org/.
- ↑ phab:T217990
- ↑ https://github.com/svg/svgo/issues/880
- ↑ https://github.com/svg/svgo/issues/1487
- ↑ https://github.com/svg/svgo/issues/1493
- ↑ https://github.com/svg/svgo/issues/1402
- ↑ c:Help:SVG_guidelines#Elements that should not be converted (rect should often not be converted to path)
- ↑ https://github.com/svg/svgo/issues/1402
- ↑ phab:T327446
- ↑ https://commons.wikimedia.org/w/index.php?title=Commons:Commons_SVG_Checker&withJS=MediaWiki:CommonsSvgChecker.js (WARNING: XML declaration not found and is strongly recommended)
- ↑ c:Help:SVG_guidelines#Useless elements that should be kept; titles are used to describe/name the file.
- ↑ 23.0 23.1 c:Help:SVG_guidelines#Invalid elements that should be kept
- ↑ c:Help:SVG_guidelines#Invalid elements that should be replaced; (removes Flowtext)
- ↑ https://github.com/svg/svgo/issues/1080
- ↑ https://github.com/svg/svgo/issues/888
- ↑ c:Help:SVG_guidelines#Useless elements that should be kept (comments explain things in the source code)
- ↑ https://github.com/svg/svgo/issues/1096; keep grid and guide
- ↑ c:Help:SVG_guidelines#Useless elements that should be kept (Groups are used to group elements.)
- ↑ https://github.com/svg/svgo/issues/1057
- ↑ https://github.com/svg/svgo/issues/946
- ↑ https://github.com/svg/svgo/issues/1732
- ↑ https://github.com/svg/svgo/issues/1194
- ↑ https://github.com/svg/svgo/issues/1618
- ↑ https://github.com/svg/svgo/issues/945
- ↑ https://github.com/svg/svgo/issues/1735
- ↑ https://github.com/svg/svgo/issues/988
- ↑ https://github.com/svg/svgo/issues/1021
- ↑ https://github.com/svg/svgo/issues/1222
- ↑ https://github.com/svg/svgo/issues/1268
- ↑ https://github.com/svg/svgo/issues/1080
- ↑ https://github.com/svg/svgo/issues/1486
- ↑ https://github.com/svg/svgo/issues/1733
- ↑ https://github.com/Ede123
- ↑ https://github.com/scour-project/scour/commits/master?after=0609c596766ec98e4e2092b49bd03b802702ba1a+279&branch=master&qualified_name=refs%2Fheads%2Fmaster
- ↑ https://github.com/RazrFalcon
- ↑ https://www.w3.org/TR/SVG11/
- ↑ https://github.com/RazrFalcon/svgcleaner#cleaning-ratio
- ↑ https://github.com/RazrFalcon/svgcleaner#cleaning-ratio
- ↑ https://github.com/RazrFalcon/svgcleaner#cleaning-time