Unlisted
Edited
Aug 31, 2023
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
function toConfig(plugins) {
return Object.entries(plugins).map(([name, params = {}]) => ({name, params}));
}
Insert cell
// Use a helper to make the configuration less verbose.
plugins = toConfig({
// Add all default plugins, override some options.
'preset-default': {
overrides: {
// Disable some default plugins.
removeViewBox: false,
minifyStyles: false,
}
},

// Enable builtin plugins that are disabled by default
convertStyleToAttrs: {},
removeDimensions: {},
// Do not use a dynamic prefix here!
prefixIds: {}

})
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
viewof svg_original = textView(await (await toFile(source.value)).text())
Insert cell
viewof svg_processed = textView(await awaitDone(runWorker(svg_original)))
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
function randomId(prefix = 's-', base = 36) {
return prefix + Math.round(Math.random() * 1e8).toString(base) + Date.now().toString(base);
}
Insert cell
Insert cell
import {interval} from '@mootari/range-slider'
Insert cell
Insert cell
pipe(
fetch('https://raw.githubusercontent.com/svg/svgo/main/README.md'),
res => res.text(),
str => {
const from = '## Built-in plugins\n';
const to = '## Other Ways to Use SVGO\n';
const table = md`${str.slice(str.indexOf(from) + from.length, str.indexOf(to))}`;
return table;
},
)
Insert cell
defaults = ({
cleanupAttrs: {
_desc: 'cleanup attributes from newlines, trailing, and repeating spaces',
_default: true,
params: {
newlines: {_type: 'boolean', _default: true},
trim: {_type: 'boolean', _default: true},
spaces: {_type: 'boolean', _default: true},
},
},
mergeStyles: {
_desc: 'merge multiple style elements into one',
default: true,
},

inlineStyles: {
_desc: 'move and merge styles from <style> elements to element style attributes',
_default: true,
params: {
onlyMatchedOnce: {_type: 'boolean', _default: true, _desc: `inline only selectors that match once`},
removeMatchedSelectors: {_type: 'boolean', _default: true, _desc: `clean up matched selectors, leave selectors that hadn't matched`},
useMqs: {_type: 'string[]', _default: ['', 'screen'], _desc: `what media queries to be used; empty string element for styles outside media queries`},
usePseudos: {_type: 'string[]', _default: [''], _desc: `what pseudo-classes/-elements to be used; empty string element for all non-pseudo-classes and/or -elements`},
},
},

removeDoctype: {
_desc: `remove doctype declaration`,
_default: true
},

removeXMLProcInst: {
_desc: `remove XML processing instructions`,
_default: true
},

removeComments: {
_desc: `remove comments`,
_default: true
},

removeMetadata: {
_desc: `removes <metadata>`,
_default: true
},

removeTitle: {
_desc: `removes <title>`,
_default: true
},

removeDesc: {
_desc: `removes <desc>`,
_default: true,
_params: {
removeAny: {_type: 'boolean', _default: true, _desc: `disable to remove only standard editors content or empty elements 'cause it can be used for accessibility; enable to remove any description.`}
}
},

removeUselessDefs: {
_desc: 'removes elements in <defs> without id',
_default: true
},

removeXMLNS: {
_desc: `removes the xmlns attribute (for inline SVG)`,
_default: false
},

removeEditorsNSData: {
_desc: `remove editors namespaces, elements, and attributes`,
_default: true,
_params: {
additionalNamespaces: {_type: 'string[]', _default: undefined, _desc: ``},
}
},

removeEmptyAttrs: {
_desc: `remove empty attributes`,
_default: true
},

removeHiddenElems: {
_desc: `remove hidden elements`,
_default: true,
_params: {
isHidden: {_type: 'boolean', _default: true, _desc: `hidden visibility`},
displayNone: {_type: 'boolean', _default: true, _desc: `display="none"`},
opacity0: {_type: 'boolean', _default: true, _desc: `opacity="0"`},
circleR0: {_type: 'boolean', _default: true, _desc: `circle with zero radius`},
ellipseRX0: {_type: 'boolean', _default: true, _desc: `ellipse with zero x-axis radius`},
ellipseRY0: {_type: 'boolean', _default: true, _desc: `ellipse with zero y-axis radius`},
rectWidth0: {_type: 'boolean', _default: true, _desc: `rectangle with zero width`},
rectHeight0: {_type: 'boolean', _default: true, _desc: `rectangle with zero height`},
patternWidth0: {_type: 'boolean', _default: true, _desc: `pattern with zero width`},
patternHeight0: {_type: 'boolean', _default: true, _desc: `pattern with zero height`},
imageWidth0: {_type: 'boolean', _default: true, _desc: `image with zero width`},
imageHeight0: {_type: 'boolean', _default: true, _desc: `image with zero height`},
pathEmptyD: {_type: 'boolean', _default: true, _desc: `path with empty data`},
polylineEmptyPoints: {_type: 'boolean', _default: true, _desc: `polyline with empty points`},
polygonEmptyPoints: {_type: 'boolean', _default: true, _desc: `polygon with empty points`}
}
},

removeEmptyText: {
_desc: `remove empty Text elements`,
_default: true,
_params: {
text: {_type: 'boolean', _default: true, _desc: `remove empty text element`},
tspan: {_type: 'boolean', _default: true, _desc: `remove empty tspan element`},
tref: {_type: 'boolean', _default: true, _desc: `remove tref with empty xlink:href attribute`}
}
},

removeEmptyContainers: {
_desc: `remove empty Container elements`,
_default: true
},

removeViewBox: {
_desc: `remove viewBox attribute when possible`,
_default: true
},

cleanupEnableBackground: {
_desc: `remove or cleanup enable-background attribute when possible`,
_default: true
},

minifyStyles: {
_desc: `minify <style> elements content with CSSO`,
_default: true,
_params: {
usage: {
_type: 'group', _params: {
force: {_type: 'boolean', _default: false, _desc: `force to use usage data even if it unsafe (document contains <script> or on* attributes)`},
ids: {_type: 'boolean', _default: true, _desc: ``},
classes: {_type: 'boolean', _default: true, _desc: ``},
tags: {_type: 'boolean', _default: true, _desc: ``}
}
}
}
},

convertStyleToAttrs: {
_desc: `convert styles into attributes`,
_default: false,
params: {
keepImportant: {_type: 'boolean', _default: false, _desc: ``}
}
},

convertColors: {
_desc: `convert colors (from rgb() to #rrggbb, from #rrggbb to #rgb)`,
_default: true,
_params: {
currentColor: {_type: 'boolean', _default: false, _desc: `convert colors to currentColor`},
names2hex: {_type: 'boolean', _default: true, _desc: `convert color name keyword to long hex`},
rgb2hex: {_type: 'boolean', _default: true, _desc: `convert rgb() to long hex`},
shorthex: {_type: 'boolean', _default: true, _desc: `convert long hex to short hex`},
shortname: {_type: 'boolean', _default: true, _desc: `convert hex to short name`}
}
},

// todo
convertPathData: {
_desc: `convert Path data to relative or absolute (whichever is shorter), convert one segment to another, trim useless delimiters, smart rounding, and much more`,
_default: true,
_params: {
applyTransforms: {_type: 'boolean', _default: true, _desc: ``},
applyTransformsStroked: {_type: 'boolean', _default: true, _desc: ``},
// todo
makeArcs: {
threshold: {_type: 'number', _default: 2.5, _desc: `coefficient of rounding error`},
tolerance: {_type: 'number', _default: 0.5, _desc: `percentage of radius`},
},
straightCurves: {_type: 'boolean', _default: true, _desc: `convert straight curves into lines segments`},
lineShorthands: {_type: 'boolean', _default: true, _desc: `horizontal and vertical line shorthands`},
curveSmoothShorthands: {_type: 'boolean', _default: true, _desc: `convert curves into smooth shorthands`},
/*!*/ floatPrecision: {_type: 'number', _default: 3, _desc: ``},
transformPrecision: {_type: 'number', _default: 5, _desc: ``},
removeUseless: {_type: 'boolean', _default: true, _desc: `remove useless non-first path segments`},
collapseRepeated: {_type: 'boolean', _default: true, _desc: `collapse repeated commands`},
utilizeAbsolute: {_type: 'boolean', _default: true, _desc: ``},
/*!*/ leadingZero: {_type: 'boolean', _default: true, _desc: ``},
/*!*/ negativeExtraSpace: {_type: 'boolean', _default: true, _desc: ``},
/*!*/ noSpaceAfterFlags: {_type: 'boolean', _default: false, _desc: ``},
forceAbsolutePath: {_type: 'boolean', _default: false, _desc: ``}
}
},

// todo
convertTransform: {
_desc: `collapse multiple transforms into one, convert matrices to the short aliases, and much more`,
_default: true,
_params: {
convertToShorts: {_type: 'boolean', _default: true, _desc: ``},
degPrecision: {_type: 'number', _default: 2, _desc: ``},
floatPrecision: {_type: 'number', _default: 3, _desc: ``},
transformPrecision: {_type: 'number', _default: 5, _desc: ``},
matrixToTransform: {_type: 'boolean', _default: true, _desc: ``},
shortTranslate: {_type: 'boolean', _default: true, _desc: ``},
shortScale: {_type: 'boolean', _default: true, _desc: ``},
shortRotate: {_type: 'boolean', _default: true, _desc: ``},
removeUseless: {_type: 'boolean', _default: true, _desc: ``},
collapseIntoOne: {_type: 'boolean', _default: true, _desc: ``},
leadingZero: {_type: 'boolean', _default: true, _desc: ``},
negativeExtraSpace: {_type: 'boolean', _default: false, _desc: ``}
}
},

// todo
removeUnknownsAndDefaults: {
_desc: `remove unknown elements content and attributes, remove attributes with default values`,
_default: true,
_params: {
unknownContent: {_type: 'boolean', _default: true, _desc: ``},
unknownAttrs: {_type: 'boolean', _default: true, _desc: ``},
defaultAttrs: {_type: 'boolean', _default: true, _desc: ``},
uselessOverrides: {_type: 'boolean', _default: true, _desc: ``},
keepDataAttrs: {_type: 'boolean', _default: true, _desc: ``},
keepAriaAttrs: {_type: 'boolean', _default: true, _desc: ``},
keepRoleAttr: {_type: 'boolean', _default: false, _desc: ``}
}
},

removeNonInheritableGroupAttrs: {
_desc: `remove non-inheritable group's "presentation" attributes`,
_default: true
},

removeUselessStrokeAndFill: {
_desc: `remove useless stroke and fill attributes`,
_default: true,
_params: {
stroke: {_type: 'boolean', _default: true, _desc: `remove stroke*`},
fill: {_type: 'boolean', _default: true, _desc: `remove fill*`},
removeNone: {_type: 'boolean', _default: false, _desc: ``}
}
},

removeUnusedNS: {
_desc: `remove unused namespaces declaration`,
_default: true
},

// todo
prefixIds: {
_desc: `prefix IDs and classes with the SVG filename or an arbitrary string`,
_default: false,
_params: {
prefix: {_type: 'string', _default: 'prefix', _desc: ``},
delim: {_type: 'string', _default: '__', _desc: ``},
prefixIds: {_type: 'boolean', _default: true, _desc: ``},
prefixClassNames: {_type: 'boolean', _default: true, _desc: ``}
}
},

cleanupIds: {
_desc: `remove unused and minify used IDs`,
_default: true,
_params: {
remove: {_type: 'boolean', _default: true, _desc: ``},
minify: {_type: 'boolean', _default: true, _desc: ``},
preserve: {_type: 'string[]', _default: [], _desc: ``},
preservePrefixes: {_type: 'string[]', _default: [], _desc: ``},
force: {_type: 'boolean', _default: false, _desc: ``}
}
},

cleanupNumericValues: {
_desc: `round numeric values to the fixed precision, remove default px units`,
_default: true,
_params: {
/*!*/ floatPrecision: {_type: 'number', _default: 3, _desc: ``},
leadingZero: {_type: 'boolean', _default: true, _desc: `remove leading zero`},
defaultPx: {_type: 'boolean', _default: true, _desc: `remove default 'px' units`},
convertToPx: {_type: 'boolean', _default: true, _desc: `convert absolute values to pixels`}
}
},

cleanupListOfValues: {
_desc: `round numeric values in attributes that take a list of numbers (like viewBox or enable-background)`,
_default: false,
_params: {
/*!*/ floatPrecision: {_type: 'number', _default: 3, _desc: ``},
leadingZero: {_type: 'boolean', _default: true, _desc: `remove leading zero`},
defaultPx: {_type: 'boolean', _default: true, _desc: `remove default 'px' units`},
convertToPx: {_type: 'boolean', _default: true, _desc: `convert absolute values to pixels`}
}
},

moveElemsAttrsToGroup: {
_desc: `move elements' attributes to their enclosing group`,
_default: true
},

moveGroupAttrsToElems: {
_desc: `move some group attributes to the contained elements`,
_default: true
},

collapseGroups: {
_desc: `collapse useless groups`,
_default: true
},

removeRasterImages: {
_desc: `remove raster images`,
_default: false
},

// todo
mergePaths: {
_desc: `merge multiple Paths into one`,
_default: true,
_params: {
force: {_type: 'boolean', _default: false, _desc: ``},
/*!*/ floatPrecision: {_type: 'number', _default: 3, _desc: ``},
/*!*/ noSpaceAfterFlags: {_type: 'boolean', _default: false, _desc: ``}
}
},

// todo
convertShapeToPath: {
_desc: `convert some basic shapes to <path>`,
_default: true,
_params: {
convertArcs: {_type: 'boolean', _default: false, _desc: `convert circle and ellipse`},
/*!*/ floatPrecision: {_type: 'number', _default: 3, _desc: ``}
}
},

convertEllipseToCircle: {
_desc: `convert non-eccentric <ellipse> to <circle>`,
_default: true
},

sortAttrs: {
_desc: `sort element attributes for epic readability`,
_default: true,
_params: {
order: {_type: 'string[]', _default: ['id', 'width', 'height', 'x', 'x1', 'x2', 'y', 'y1', 'y2', 'cx', 'cy', 'r', 'fill', 'stroke', 'marker', 'd', 'points'], _desc: ``},
xmlnsOrder: {_type: ['front', 'alphabetical'], _default: 'front', _desc: ``}
}
},

sortDefsChildren: {
_desc: `sort children of <defs> in order to improve compression`,
_default: true
},

removeDimensions: {
_desc: `remove width/height and add viewBox if it's missing (opposite to removeViewBox, disable it first)`,
_default: false
},

// todo
removeAttrs: {
_desc: `remove attributes by pattern`,
_default: false,
_params: {
elemSeparator: {_type: 'string', _default: ':', _desc: ``},
preserveCurrentColor: {_type: 'boolean', _default: false, _desc: ``},
/* TODO */ attrs: null,
},
},

// todo
removeAttributesBySelector: {
_desc: `removes attributes of elements that match a CSS selector`,
_default: false,
_params:
/* TODO */ selectors: null
},

____: {
_desc: ``,
_default: false,
},

____: {
_desc: ``,
_default: false,
},

____: {
_desc: ``,
_default: false,
},

____: {
_desc: ``,
_default: false,
},

____: {
_desc: ``,
_default: false,
},

____: {
_desc: ``,
_default: false,
},

})
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more