Simon Willison’s Weblog

Subscribe
Atom feed for svg

37 items tagged “svg”

2024

Mastodon discussion about sandboxing SVG data. I asked this on Mastodon and got some really useful replies:

How hard is it to process untrusted SVG data to strip out any potentially harmful tags or attributes (like stuff that might execute JavaScript)?

The winner for me turned out to be the humble <img src=""> tag. SVG images that are rendered in an image have all dynamic functionality - including embedded JavaScript - disabled by default, and that's something that's directly included in the spec:

2.2.6. Secure static mode

This processing mode is intended for circumstances where an SVG document is to be used as a non-animated image that is not allowed to resolve external references, and which is not intended to be used as an interactive document. This mode might be used where image support has traditionally been limited to non-animated raster images (such as JPEG and PNG.)

[...]

'image' references

An SVG embedded within an 'image' element must be processed in secure animated mode if the embedding document supports declarative animation, or in secure static mode otherwise.

The same processing modes are expected to be used for other cases where SVG is used in place of a raster image, such as an HTML 'img' element or in any CSS property that takes an data type. This is consistent with HTML's requirement that image sources must reference "a non-interactive, optionally animated, image resource that is neither paged nor scripted" [HTML]

This also works for SVG data that's presented in a <img src="data:image/svg+xml;base64,... attribute. I had Claude help spin me up this interactive demo:

Build me an artifact - just HTML, no JavaScript - which demonstrates embedding some SVG files using img src= base64 URIs

I want three SVGs - one of the sun, one of a pelican and one that includes some tricky javascript things which I hope the img src= tag will ignore

Screenshot of SVG demo page showing three examples: "Simple Sun SVG" with a yellow circular sun and rays, "Pelican SVG" with a gray stylized bird shape, and "SVG with JavaScript (ignored)" showing a coral-colored square with text "JS Ignored". Page titled "SVG Base64 Embedding Demo". Each example includes descriptive text explaining its purpose.

If you right click and "open in a new tab" on the JavaScript-embedding SVG that script will execute, showing an alert. You can click the image to see another alert showing location.href and document.cookie which should confirm that the base64 image is not treated as having the same origin as the page itself.

# 26th October 2024, 8:51 pm / svg, mastodon, ai-assisted-programming, security, sandboxing

LLM Pictionary. Inspired by my SVG pelicans on a bicycle, Paul Calcraft built this brilliant system where different vision LLMs can play Pictionary with each other, taking it in turns to progressively draw SVGs while the other models see if they can guess what the image represents.

# 26th October 2024, 8:19 pm / vision-llms, svg, generative-ai, ai, llms

Pelicans on a bicycle. I decided to roll out my own LLM benchmark: how well can different models render an SVG of a pelican riding a bicycle?

I chose that because a) I like pelicans and b) I'm pretty sure there aren't any pelican on a bicycle SVG files floating around (yet) that might have already been sucked into the training data.

My prompt:

Generate an SVG of a pelican riding a bicycle

I've run it through 16 models so far - from OpenAI, Anthropic, Google Gemini and Meta (Llama running on Cerebras), all using my LLM CLI utility. Here's my (Claude assisted) Bash script: generate-svgs.sh

Here's Claude 3.5 Sonnet (2024-06-20) and Claude 3.5 Sonnet (2024-10-22):

Gemini 1.5 Flash 001 and Gemini 1.5 Flash 002:

GPT-4o mini and GPT-4o:

o1-mini and o1-preview:

Cerebras Llama 3.1 70B and Llama 3.1 8B:

And a special mention for Gemini 1.5 Flash 8B:

The rest of them are linked from the README.

# 25th October 2024, 11:56 pm / gemini, anthropic, llama, openai, ai, llms, svg, generative-ai, llm, cerebras

fav.farm (via) Neat little site by Wes Bos: it serves SVG (or PNG for Safari) favicons of every Emoji, which can be added to any site like this:

<link rel="icon" href="https://fav.farm/🔥" />

The source code is on GitHub. It runs on Deno and Deno Deploy, and recently added per-Emoji hit counters powered by the Deno KV store, implemented in db.ts using this pattern:

export function incrementCount(emoji: string) {
  const VIEW_KEY = [`favicon`, `${emoji}`];
  return db.atomic().sum(
    VIEW_KEY, 1n
  ).commit(); // Increment KV by 1
}

# 7th October 2024, 6:46 am / deno, favicon, javascript, svg

VTracer (via) VTracer is an open source library written in Rust for converting raster images (JPEG, PNG etc) to vector SVG.

This VTracer web app provides access to a WebAssembly compiled version of the library, with a UI that lets you open images, tweak the various options and download the resulting SVG.

Screenshot of VisionCortex VTracer web interface. Central image shows a surreal scene with a giant pelican wearing a monocle, overlooking a coastal city with yachts and an F1 car. UI elements include: logo, download options, and image processing controls for clustering, filtering, color precision, gradient step, and curve fitting.

I heard about this today on Twitter in a reply to my tweet demonstrating a much, much simpler Image to SVG tool I built with the help of Claude and the handy imagetracerjs library by András Jankovics.

# 7th October 2024, 4:17 am / svg, rust, webassembly

SVG to JPG/PNG. The latest in my ongoing series of interactive HTML and JavaScript tools written almost entirely by LLMs. This one lets you paste in (or open-from-file, or drag-onto-page) some SVG and then use that to render a JPEG or PNG image of your desired width.

Screenshot of the SVG to JPEG/PNG tool. It starts with a Browse... option for selecting a file, next to a Load example image link, above a textarea full of SVG code. Then a radio box to select between JPEG and PNG, plus a background color color picker widget next to a checkbox labelled transparent. Then Output width, a number field set to 300. Then a convert SVG button. Below is the classic SVG tiger image, with a Download image link that says 47.38BK. Under that is a Base 64 image tag header with a copy image tag button and some visible HTML for a data:image/jpeg image element.

I built this using Claude 3.5 Sonnet, initially as an Artifact and later in a code editor since some of the features (loading an example image and downloading the result) cannot run in the sandboxed iframe Artifact environment.

Here's the full transcript of the Claude conversation I used to build the tool, plus a few commits I later made by hand to further customize it.

The code itself is mostly quite simple. The most interesting part is how it renders the SVG to an image, which (simplified) looks like this:

// First extract the viewbox to get width/height
const svgElement = new DOMParser().parseFromString(
    svgInput, 'image/svg+xml'
).documentElement;
let viewBox = svgElement.getAttribute('viewBox');
[, , width, height] = viewBox.split(' ').map(Number);

// Figure out the width/height of the output image
const newWidth = parseInt(widthInput.value) || 800;
const aspectRatio = width / height;
const newHeight = Math.round(newWidth / aspectRatio);

// Create off-screen canvas
const canvas = document.createElement('canvas');
canvas.width = newWidth;
canvas.height = newHeight;

// Draw SVG on canvas
const svgBlob = new Blob([svgInput], {type: 'image/svg+xml;charset=utf-8'});
const svgUrl = URL.createObjectURL(svgBlob);
const img = new Image();
const ctx = canvas.getContext('2d');
img.onload = function() {
    ctx.drawImage(img, 0, 0, newWidth, newHeight);
    URL.revokeObjectURL(svgUrl);
    // Convert that to a JPEG
    const imageDataUrl = canvas.toDataURL("image/jpeg");
    const convertedImg = document.createElement('img');
    convertedImg.src = imageDataUrl;
    imageContainer.appendChild(convertedImg);
};
img.src = svgUrl;

Here's the MDN explanation of that revokeObjectURL() method, which I hadn't seen before.

Call this method when you've finished using an object URL to let the browser know not to keep the reference to the file any longer.

# 6th October 2024, 7:57 pm / claude-3-5-sonnet, images, claude, ai, llms, svg, claude-artifacts, javascript, ai-assisted-programming, generative-ai

tiny-world-map (via) I love this project. It’s a JavaScript file (694K uncompressed, 283KB compressed) which can be used with the Leaflet mapping library and provides a SVG base map of the world with country borders and labels for every world city with a population more than 48,000—10,000 cities total.

This means you can bundle an offline map of the world as part of any application that doesn’t need a higher level of detail. A lot of smaller island nations are missing entirely though, so this may not be right for every project.

It even includes a service worker to help implement offline mapping support, plus several variants of the map with less cities that are even smaller.

# 21st April 2024, 10:11 pm / svg, serviceworkers, javascript, gis, mapping

2023

SVG Tutorial: Learn SVG through 25 examples (via) Hunor Márton Borbély published this fantastic advent calendar of tutorials for learning SVG, from the basics up to advanced concepts like animation and interactivity.

# 7th December 2023, 6:47 pm / svg

excalidraw.com (via) Really nice browser-based editor for simple diagrams using a pleasing hand-sketched style, with the ability to export them as SVG or PNG.

# 30th August 2023, 4:30 pm / svg

2022

Draw SVG rope using JavaScript (via) Delightful interactive tutorial by Stanko Tadić showing how to render an illustration of a rope using SVG, starting with a path. The way the tutorial is presented is outstanding.

# 31st December 2022, 5:31 pm / explorables, svg, graphics, javascript

2021

Making GitHub’s new homepage fast and performant. A couple of really clever tricks in this article by Tobias Ahlin. The first is using IntersectionObserver in conjunction with the video preload=“none” attribute to lazily load a video when it scrolls into view. The second is an ingenious trick to create an efficiently encoded transparent JPEG image: embed the image in a SVG file twice, once as the image and once as a transparency mask.

# 29th January 2021, 7:05 pm / images, performance, svg, javascript, github

2020

Pikchr. Interesting new project from SQLite creator D. Richard Hipp. Pikchr is a new mini language for describing visual diagrams, designed to be embedded in Markdown documentation. It’s already enabled for the SQLite forum. Implementation is a no-dependencies C library and output is SVG.

# 21st October 2020, 4:02 pm / c, svg, markdown, sqlite, d-richard-hipp

html-to-svg (via) ‪This is absolutely ingenious: 50 lines of JavaScript which uses Puppeteer to get headless Chrome to grab a PDF screenshot of a page, then shells out to Inkscape to convert the PDF to SVG. Wraps the whole thing up in a Docker container and ships it to Cloud Run as a web service you can call by passing it a URL.

# 7th May 2020, 6:01 am / cloudrun, chrome, svg, puppeteer

2017

Of SVG, Minification and Gzip. Delightfully nerdy exploration of tricks you can use to hand-optimize your SVG in order to maximize gzip compression. Premature optimization may be the root of all evil but this is still a great way to learn about how gzip actually works.

# 21st November 2017, 2:54 pm / svg, gzip, minification

Using SVG as placeholders — More Image Loading Techniques. This is such a good idea: generate a tiny SVG placeholder for an image, and display that until the image itself has loaded. This article explores potential ways of generating those SVGs in some depth.

# 14th November 2017, 7:19 pm / svg

Carbon (via) Beautiful little tool that you can paste source code into to generate an image of that code with syntax highlighting applied, ready to be tweeted or shared anywhere that lets you share an image. Built in Node and next.js, with image generation handled client-side by the dom-to-image JavaScript library which loads HTML into a SVG foreignObject (sadly not yet supported by Safari) and uses that to populate a canvas and produce a PNG.

# 19th October 2017, 6:31 pm / zeit-now, nodejs, svg, javascript

2010

Polymaps. Absurdly classy: “a JavaScript library for image- and vector-tiled maps using SVG”. It can pull in image tiles from sources such as OpenStreetMap, then overlay SVG paths specified using GeoJSON. The demos make use of GeoJSON tiles for US states and counties hosted on AppEngine. The library is developed by Stamen and SimpleGeo, and released under a BSD license. SVG support in the browser is required.

# 20th August 2010, 6:46 pm / appengine, geojson, javascript, mapping, polymaps, simplegeo, svg, recovered, stamen-design, openstreetmap

canto.js: An Improved HTML5 Canvas API (via) Improved is an understatement: canto adds jQuery-style method chaining, the ability to multiple coordinates to e.g. lineTo at once, relative coordinate methods (regular Canvas does everything in terms of absolute coordinates), the ability to use degrees instead of radians, a rounded corner shortcut, a more convenient .revert() method and a simple parser that can understand SVG path expressions! The only catch: it uses getters and setters so won’t work in IE.

# 29th July 2010, 9:39 am / canto, canvas, david-flanagan, html5, javascript, svg, recovered

Smokescreen demo: a Flash player in JavaScript. Chris Smoak’s Smokescreen, “a Flash player written in JavaScript”, is an incredible piece of work. It runs entirely in the browser, reads in SWF binaries, unzips them (in native JS), extracts images and embedded audio and turns them in to base64 encoded data:uris, then stitches the vector graphics back together as animated SVG. Open up the Chrome Web Inspector while the demo is running and you can see the SVG changing in real time. Smokescreen even implements its own ActionScript bytecode interpreter. It’s stated intention is to allow Flash banner ads to execute on the iPad and iPhone, but there are plenty of other interesting applications (such as news site infographics). The company behind it have announced plans to open source it in the near future. My one concern is performance—the library is 175 KB and over 8,000 lines of JavaScript which might cause problems on low powered mobile devices.

# 29th May 2010, 11:32 am / chris-smoak, datauri, flash, javascript, smokescreen, svg, recovered

ZOMBO.com in HTML5. Uses SVG (scripted by JavaScript) and the audio element. Finally, Zombo.com comes to the iPad.

# 20th May 2010, 3:26 pm / audio, html5, ipad, svg, zombo, zombocom, recovered

Firefox 4: the HTML5 parser—inline SVG, speed and more. A complete replacement for the oldest part of Gecko (the HTML parser dates back to 1998) headed up by HTML5 validator author Henri Sivonen, using the parsing algorithm defined in the HTML5 specification. Improvements include parsing taking place off the main UI thread and the ability to embed SVG and MathML directly inline in HTML pages.

# 12th May 2010, 8:56 am / firefox4, gecko, henrisivonen, html5, mathml, parser, svg, recovered

"... the interchange format needed to be able to support future Flash Player features, which would not necessarily map to SVG features. As such, the decision was made to go with a new interchange format, FXG, instead of having a non-standard implementation of SVG. FXG does borrow from SVG whenever possible."

FXG 1.0 Specification

# 11th April 2010, 6:58 pm / adobe, flash, fxg, svg

Internet Explorer Platform Preview Guide for Developers (via) Lots of SVG and CSS3 stuff, no mention of canvas here either though.

# 16th March 2010, 6:36 pm / svg, css3, ie9, ie, microsoft, canvas, html5

An Early Look At IE9 for Developers (via) Surprisingly, no mention of SVG or canvas and only a note in passing about HTML 5.

# 16th March 2010, 6:11 pm / svg, canvas, html5, ie, ie9, microsoft

svg-edit. Click the “Try out SVG-edit 2.4” link—this is an impressive, full featured open source vector graphics editor that runs in the browser.

# 7th February 2010, 10:30 am / svgedit, svg, html5, demos

2009

How to Make a US County Thematic Map Using Free Tools. This is the trick I’ve been using to generate choropleths at the Guardian for the past year: figure out the preferred colours for a set of data in a Python script and then rewrite an SVG file to colour in the areas. I use ElementTree rather than BeautifulSoup but the technique is exactly the same. The best thing about SVG is that our graphics department can export them directly out of Illustrator, with named layers and paths automatically becoming SVG ID attributes. Bonus tip: sometimes you don’t have to rewrite the SVG XML at all, instead you can generate CSS to colour areas by ID selector and inject it in to the top of the file.

# 12th November 2009, 10:49 am / choropleths, mapping, python, infographics, beautifulsoup, elementtree, css, svg

svgweb. Awesome. I’ve been having a lot of fun with SVG for dynamic graphics recently (maps in particular), and hoping someone builds an SVG renderer in Flash so I could serve up SVG files for IE. Brad Neuberg and team have done exactly that.

# 22nd August 2009, 10:42 pm / flash, brad-neuberg, svg, svgweb

Fixing IE by porting Canvas to Flash. Implementing canvas using Flash is an obvious step, but personally I’m much more interested in an SVG renderer using Flash that finally brings non-animated SVGs to IE.

# 15th March 2009, 1:34 pm / svg, flash, canvas, ie

2008

Using SVG on the Web. I’ve been having a lot of fun playing with SVG recently. Here are some useful tips for including SVG images in HTML and XHTML documents.

# 23rd December 2008, 1 pm / svg, html, xhtml, benjamin-smedberg

It’s a purple world. Stuart Langridge made a purplish map of the US election results, using JSON data from Google and an SVG map of the US from Wikipedia.

# 6th November 2008, 8:26 pm / stuart-langridge, uselection, svg, wikipedia