Git Product home page Git Product logo

mini-svg-data-uri's Introduction

Mini SVG data: URI

This tool converts SVGs into the most compact, compressible data: URI that SVG-supporting browsers tolerate. The results look like this (169 bytes):

data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 50 50'
%3e%3cpath d='M22 38V51L32 32l19-19v12C44 26 43 10 38 0 52 15 49 39 22 38z'/%3e
%3c/svg%3e

Compare to the Base64 version (210 bytes):

data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIH
ZpZXdCb3g9IjAgMCA1MCA1MCI+PHBhdGggZD0iTTIyIDM4VjUxTDMyIDMybDE5LTE5djEyQzQ0IDI2ID
QzIDEwIDM4IDAgNTIgMTUgNDkgMzkgMjIgMzh6Ii8+PC9zdmc+

Or the URL-encoded version other tools produce (256 bytes):

data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%
2F2000%2Fsvg%22%20viewBox%3D%220%200%2050%2050%22%3E%3Cpath%20d%3D%22M22%2038V51
L32%2032l19-19v12C44%2026%2043%2010%2038%200%2052%2015%2049%2039%2022%2038z%22%2
F%3E%3C%2Fsvg%3E

For a more realistic example, I inlined the icons from the Open Iconic project into CSS files with the 3 above methods:

Compression Base64 Basic %-encoding mini-svg-data-uri
None 96.459 kB 103.268 kB 76.583 kB
gzip -9 17.902 kB 13.780 kB 12.974 kB
brotli -Z 15.797 kB 11.693 kB 10.976 kB

Roughly 6% smaller compressed, but don't write off the ≈20% uncompressed savings either. Some browser caches decompress before store, and parsing time/memory usage scale linearly with uncompressed filesize.

Usage

var svgToMiniDataURI = require('mini-svg-data-uri');

var svg = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 50"><path d="M22 38V51L32 32l19-19v12C44 26 43 10 38 0 52 15 49 39 22 38z"/></svg>';

var optimizedSVGDataURI = svgToMiniDataURI(svg);
// "data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 50 50'%3e%3cpath d='M22 38V51L32 32l19-19v12C44 26 43 10 38 0 52 15 49 39 22 38z'/%3e%3c/svg%3e"

You can also try it in your browser at RunKit.

CLI

If you have it installed globally, or as some kind of dependency inside your project’s directory:

mini-svg-data-uri file.svg # writes to stdout
mini-svg-data-uri file.svg file.svg.uri # writes to the given output filename

Use --help for more info.

Warning

  • This does not optimize the SVG source file. You’ll want svgo or its brother SVGOMG for that.

  • The default output does not work inside srcset attributes. Use the .toSrcset method for that:

    var srcsetExample = html`
    <picture>
      <source srcset="${svgToMiniDataURI.toSrcset(svg)}">
      <img src="${svgToMiniDataURI(svg)}">
    </picture>`;
  • The resulting Data URI should be wrapped with double quotes: url("…"), <img src="…">, etc.

  • This might change or break SVGs that use " in character data, like inside <text> or aria-label or something. Try curly quotes (“”) or &quot; instead.

FAQ

Don’t you need a charset in the MIME Type?

charset does nothing for Data URIs. The URI can only be the encoding of its parent file — it’s included in it!

Why lowercase the URL-encoded hex pairs?

It compresses slightly better. No, really. Using the same files from earlier:

Compression Uppercase (%AF) Lowercase (%af)
gzip -9 12.978 kB 12.974 kB
brotli -Z 10.988 kB 10.976 kB

I did say slightly.

Browser support

  • Internet Explorer 9 and up, including Edge
  • Firefox, Safari, Chrome, whatever else uses their engines
  • Android WebKit 3+
  • Opera Mini’s server-side Presto

mini-svg-data-uri's People

Contributors

fjc0k avatar kovart avatar malexandert avatar simonewebdesign avatar taylor-hunt-kr avatar tigt avatar timbest avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

mini-svg-data-uri's Issues

Example code not working

Thanks for your article and your code. I tried it here https://runkit.com/embed/b3g4cq89e8ys but I get a ReferenceError: svgToMiniDataURI is not defined. I looked in your code and saw the function is named svgToTinyDataUri, but with line var optimizedSVGDataURI = svgToTinyDataUri(svg); I get a not defined error as well. Would be glad, if you could explain me what's wrong with my code.

Should this work in a cursor as well?

I have an svg I've compressed on svgmo. The output from mini-svg-data-uri works perfectly as a background-image. But it fails when used as a cursor? (Chrome / Mac) Do you know what may be causing this difference? Full code

const svgToMiniDataURI = require("mini-svg-data-uri");
const workingSvg = `<svg width="73" height="26" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><filter x="-11.8%" y="-46.2%" width="123.5%" height="192.5%" filterUnits="objectBoundingBox" id="a"><feOffset in="SourceAlpha" result="shadowOffsetOuter1"/><feGaussianBlur stdDeviation="2.5" in="shadowOffsetOuter1" result="shadowBlurOuter1"/><feColorMatrix values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.75 0" in="shadowBlurOuter1"/></filter><path id="b" d="M225.369 461.888l.871.49 12 6.75 1.55.872-1.55.872-12 6.75-.871.49-.98-1.743.87-.49 8.673-4.879H176v-2h57.932l-8.672-4.878-.872-.49z"/></defs><g fill="#000" transform="translate(-171 -457)" fill-rule="nonzero"><use filter="url(#a)" xlink:href="#b"/><use xlink:href="#b"/></g></svg>`;
const optimizedSVGDataURI = svgToMiniDataURI(workingSvg);

Used like

.my-custom-cursor {
   cursor: url("data:image/svg+xml,%3csvg width='73' height='26' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'%3e%3cdefs%3e%3cfilter x='-11.8%25' y='-46.2%25' width='123.5%25' height='192.5%25' filterUnits='objectBoundingBox' id='a'%3e%3cfeOffset in='SourceAlpha' result='shadowOffsetOuter1'/%3e%3cfeGaussianBlur stdDeviation='2.5' in='shadowOffsetOuter1' result='shadowBlurOuter1'/%3e%3cfeColorMatrix values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.75 0' in='shadowBlurOuter1'/%3e%3c/filter%3e%3cpath id='b' d='M225.369 461.888l.871.49 12 6.75 1.55.872-1.55.872-12 6.75-.871.49-.98-1.743.87-.49 8.673-4.879H176v-2h57.932l-8.672-4.878-.872-.49z'/%3e%3c/defs%3e%3cg fill='black' transform='translate(-171 -457)' fill-rule='nonzero'%3e%3cuse filter='url(%23a)' xlink:href='%23b'/%3e%3cuse xlink:href='%23b'/%3e%3c/g%3e%3c/svg%3e");
}

Not compatible in srcset attribute

In the gatsby-image project, we've discovered in a PR being reviewed that SVG data URIs from this library are not compatible with the srcset attribute.

Only base64 or url-encoded work. The only notable difference from the example given, was literal spaces vs %20. In the srcset attribute, you provide a comma delimited list of URL/URIs and an optional space followed by a descriptor(eg 1x, 100w), if none provided they'll use a default.

With the output from mini-svg-data-uri a console error is raised, and the srcset is ignored.


It might be worth mentioning on your README that mini-svg-data-uri will not work for this use-case? Or at least requires another pass to convert the spaces to %20, or this library provides some config/option to handle that?(it looks like you intentionally convert to literal spaces?)

Going the other direction

Hi, I want to use this package to inline svgs with Webpack asset modules.

When I render them, though, I want to take the data URI and convert it back to plain SVG data so I can dangerouslySetInnerHTML. This way I can control things like the fill color with CSS.

Any suggestions on how to achieve that?

Works in link only after pressing Enter

Hello! I'm using mini-svg-data-uri to cram an SVG into a link. My code looks like this:

var argMap = response.svg;

// remove linebreaks and comments from inside the SVG, as these tend to break it
argMap = argMap.replace(/\r?\n|\r/g,""); // remove linebreaks
argMap = argMap.replace(/<!--[\s\S]*?-->/g, ""); // remove comments

argMap = svgToMiniDataURI(argMap);

const mapIcon = '<span class="wikiglyph wikiglyph-map" aria-hidden="true"></span>';
const mapButton = `<a href="${argMap}" target="_blank">` + mapIcon + '</a>';

When I do this, I get this URL in a new tab. The tab shows a grey screen.

data:image/svg+xml,%3csvg width='458pt' height='229pt' viewBox='0.00 0.00 458.00 228.80' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'%3e%3cg id='graph0' class='graph' transform='scale(1 1) rotate(0) translate(4 224.8)'%3e%3ctitle%3eArgument Map%3c/title%3e%3cg id='clust1' class='cluster'%3e%3ctitle%3ecluster_1%3c/title%3e%3cpolygon fill='%23cccccc' stroke='%23cccccc' points='8%2c-8 8%2c-172.8 442%2c-172.8 442%2c-8 8%2c-8'/%3e%3ctext text-anchor='start' x='191.32' y='-158' font-family='arial' font-size='12.00' fill='black'%3eI am a group%3c/text%3e%3c/g%3e%3cg id='clust2' class='cluster'%3e%3ctitle%3ecluster_2%3c/title%3e%3cpolygon fill='%23cccccc' stroke='%23cccccc' points='16%2c-16 16%2c-94.4 228%2c-94.4 228%2c-16 16%2c-16'/%3e%3ctext text-anchor='start' x='78.65' y='-79.6' font-family='arial' font-size='12.00' fill='black'%3eI am a subgroup%3c/text%3e%3c/g%3e%3cg id='node1' class='node'%3e%3ctitle%3en1%3c/title%3e%3cpath fill='%2363aef2' stroke='black' d='M422%2c-64C422%2c-64 250%2c-64 250%2c-64 244%2c-64 238%2c-58 238%2c-52 238%2c-52 238%2c-36 238%2c-36 238%2c-30 244%2c-24 250%2c-24 250%2c-24 422%2c-24 422%2c-24 428%2c-24 434%2c-30 434%2c-36 434%2c-36 434%2c-52 434%2c-52 434%2c-58 428%2c-64 422%2c-64'/%3e%3ctext text-anchor='start' x='310.72' y='-50' font-family='arial' font-weight='bold' font-size='10.00' fill='black'%3eargument 1%3c/text%3e%3ctext text-anchor='start' x='260.14' y='-33' font-family='arial' font-size='10.00' fill='black'%3eI am an attacking argument. %23tag2%3c/text%3e%3c/g%3e%3cg id='node4' class='node'%3e%3ctitle%3en0%3c/title%3e%3cpath fill='white' stroke='%2363aef2' stroke-width='2' d='M315%2c-220.8C315%2c-220.8 143%2c-220.8 143%2c-220.8 137%2c-220.8 131%2c-214.8 131%2c-208.8 131%2c-208.8 131%2c-192.8 131%2c-192.8 131%2c-186.8 137%2c-180.8 143%2c-180.8 143%2c-180.8 315%2c-180.8 315%2c-180.8 321%2c-180.8 327%2c-186.8 327%2c-192.8 327%2c-192.8 327%2c-208.8 327%2c-208.8 327%2c-214.8 321%2c-220.8 315%2c-220.8'/%3e%3ctext text-anchor='start' x='207.05' y='-206.8' font-family='arial' font-weight='bold' font-size='10.00' fill='black'%3estatement%3c/text%3e%3ctext text-anchor='start' x='176.48' y='-189.8' font-family='arial' font-size='10.00' fill='black'%3eI am a statement. %23tag1%3c/text%3e%3c/g%3e%3cg id='edge1' class='edge'%3e%3ctitle%3en1%26%2345%3b%26gt%3bn0%3c/title%3e%3cpath fill='none' stroke='black' d='M324.17%2c-64.01C309.2%2c-87.79 282.2%2c-129.78 251.14%2c-172.29'/%3e%3cpolygon fill='black' stroke='black' points='248.2%2c-170.38 245.09%2c-180.51 253.84%2c-174.53 248.2%2c-170.38'/%3e%3c/g%3e%3cg id='node2' class='node'%3e%3ctitle%3en2%3c/title%3e%3cpath fill='%2363aef2' stroke='black' d='M230%2c-142.4C230%2c-142.4 58%2c-142.4 58%2c-142.4 52%2c-142.4 46%2c-136.4 46%2c-130.4 46%2c-130.4 46%2c-114.4 46%2c-114.4 46%2c-108.4 52%2c-102.4 58%2c-102.4 58%2c-102.4 230%2c-102.4 230%2c-102.4 236%2c-102.4 242%2c-108.4 242%2c-114.4 242%2c-114.4 242%2c-130.4 242%2c-130.4 242%2c-136.4 236%2c-142.4 230%2c-142.4'/%3e%3ctext text-anchor='start' x='118.72' y='-128.4' font-family='arial' font-weight='bold' font-size='10.00' fill='black'%3eargument 2%3c/text%3e%3ctext text-anchor='start' x='67.59' y='-111.4' font-family='arial' font-size='10.00' fill='black'%3eI am a supporting argument. %23tag3%3c/text%3e%3c/g%3e%3cg id='edge3' class='edge'%3e%3ctitle%3en2%26%2345%3b%26gt%3bn0%3c/title%3e%3cpath fill='none' stroke='black' d='M165.45%2c-142.68C176%2c-152.16 188.86%2c-163.72 200.25%2c-173.96'/%3e%3cpolygon fill='black' stroke='black' points='198.08%2c-176.71 207.85%2c-180.79 202.75%2c-171.5 198.08%2c-176.71'/%3e%3c/g%3e%3cg id='node3' class='node'%3e%3ctitle%3en3%3c/title%3e%3cpath fill='%2363aef2' stroke='black' d='M208%2c-64C208%2c-64 36%2c-64 36%2c-64 30%2c-64 24%2c-58 24%2c-52 24%2c-52 24%2c-36 24%2c-36 24%2c-30 30%2c-24 36%2c-24 36%2c-24 208%2c-24 208%2c-24 214%2c-24 220%2c-30 220%2c-36 220%2c-36 220%2c-52 220%2c-52 220%2c-58 214%2c-64 208%2c-64'/%3e%3ctext text-anchor='start' x='96.72' y='-50' font-family='arial' font-weight='bold' font-size='10.00' fill='black'%3eargument 3%3c/text%3e%3ctext text-anchor='start' x='46.7' y='-33' font-family='arial' font-size='10.00' fill='black'%3eI am an undercut argument. %23tag4%3c/text%3e%3c/g%3e%3cg id='edge2' class='edge'%3e%3ctitle%3en3%26%2345%3b%26gt%3bn2%3c/title%3e%3cpath fill='none' stroke='black' d='M127.55%2c-64.28C130.02%2c-72.85 132.98%2c-83.12 135.7%2c-92.57'/%3e%3cpolygon fill='black' stroke='black' points='132.4%2c-93.75 138.53%2c-102.39 139.12%2c-91.81 132.4%2c-93.75'/%3e%3c/g%3e%3c/g%3e%3c/svg%3e

When I click the URL and press Enter, it converts to this, and the image appears:

data:image/svg+xml,<svg width='458pt' height='229pt' viewBox='0.00 0.00 458.00 228.80' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'><g id='graph0' class='graph' transform='scale(1 1) rotate(0) translate(4 224.8)'><title>Argument Map</title><g id='clust1' class='cluster'><title>cluster_1</title><polygon fill='%23cccccc' stroke='%23cccccc' points='8%2c-8 8%2c-172.8 442%2c-172.8 442%2c-8 8%2c-8'/><text text-anchor='start' x='191.32' y='-158' font-family='arial' font-size='12.00' fill='black'>I am a group</text></g><g id='clust2' class='cluster'><title>cluster_2</title><polygon fill='%23cccccc' stroke='%23cccccc' points='16%2c-16 16%2c-94.4 228%2c-94.4 228%2c-16 16%2c-16'/><text text-anchor='start' x='78.65' y='-79.6' font-family='arial' font-size='12.00' fill='black'>I am a subgroup</text></g><g id='node1' class='node'><title>n1</title><path fill='%2363aef2' stroke='black' d='M422%2c-64C422%2c-64 250%2c-64 250%2c-64 244%2c-64 238%2c-58 238%2c-52 238%2c-52 238%2c-36 238%2c-36 238%2c-30 244%2c-24 250%2c-24 250%2c-24 422%2c-24 422%2c-24 428%2c-24 434%2c-30 434%2c-36 434%2c-36 434%2c-52 434%2c-52 434%2c-58 428%2c-64 422%2c-64'/><text text-anchor='start' x='310.72' y='-50' font-family='arial' font-weight='bold' font-size='10.00' fill='black'>argument 1</text><text text-anchor='start' x='260.14' y='-33' font-family='arial' font-size='10.00' fill='black'>I am an attacking argument. %23tag2</text></g><g id='node4' class='node'><title>n0</title><path fill='white' stroke='%2363aef2' stroke-width='2' d='M315%2c-220.8C315%2c-220.8 143%2c-220.8 143%2c-220.8 137%2c-220.8 131%2c-214.8 131%2c-208.8 131%2c-208.8 131%2c-192.8 131%2c-192.8 131%2c-186.8 137%2c-180.8 143%2c-180.8 143%2c-180.8 315%2c-180.8 315%2c-180.8 321%2c-180.8 327%2c-186.8 327%2c-192.8 327%2c-192.8 327%2c-208.8 327%2c-208.8 327%2c-214.8 321%2c-220.8 315%2c-220.8'/><text text-anchor='start' x='207.05' y='-206.8' font-family='arial' font-weight='bold' font-size='10.00' fill='black'>statement</text><text text-anchor='start' x='176.48' y='-189.8' font-family='arial' font-size='10.00' fill='black'>I am a statement. %23tag1</text></g><g id='edge1' class='edge'><title>n1%26%2345%3b%26gt%3bn0</title><path fill='none' stroke='black' d='M324.17%2c-64.01C309.2%2c-87.79 282.2%2c-129.78 251.14%2c-172.29'/><polygon fill='black' stroke='black' points='248.2%2c-170.38 245.09%2c-180.51 253.84%2c-174.53 248.2%2c-170.38'/></g><g id='node2' class='node'><title>n2</title><path fill='%2363aef2' stroke='black' d='M230%2c-142.4C230%2c-142.4 58%2c-142.4 58%2c-142.4 52%2c-142.4 46%2c-136.4 46%2c-130.4 46%2c-130.4 46%2c-114.4 46%2c-114.4 46%2c-108.4 52%2c-102.4 58%2c-102.4 58%2c-102.4 230%2c-102.4 230%2c-102.4 236%2c-102.4 242%2c-108.4 242%2c-114.4 242%2c-114.4 242%2c-130.4 242%2c-130.4 242%2c-136.4 236%2c-142.4 230%2c-142.4'/><text text-anchor='start' x='118.72' y='-128.4' font-family='arial' font-weight='bold' font-size='10.00' fill='black'>argument 2</text><text text-anchor='start' x='67.59' y='-111.4' font-family='arial' font-size='10.00' fill='black'>I am a supporting argument. %23tag3</text></g><g id='edge3' class='edge'><title>n2%26%2345%3b%26gt%3bn0</title><path fill='none' stroke='black' d='M165.45%2c-142.68C176%2c-152.16 188.86%2c-163.72 200.25%2c-173.96'/><polygon fill='black' stroke='black' points='198.08%2c-176.71 207.85%2c-180.79 202.75%2c-171.5 198.08%2c-176.71'/></g><g id='node3' class='node'><title>n3</title><path fill='%2363aef2' stroke='black' d='M208%2c-64C208%2c-64 36%2c-64 36%2c-64 30%2c-64 24%2c-58 24%2c-52 24%2c-52 24%2c-36 24%2c-36 24%2c-30 30%2c-24 36%2c-24 36%2c-24 208%2c-24 208%2c-24 214%2c-24 220%2c-30 220%2c-36 220%2c-36 220%2c-52 220%2c-52 220%2c-58 214%2c-64 208%2c-64'/><text text-anchor='start' x='96.72' y='-50' font-family='arial' font-weight='bold' font-size='10.00' fill='black'>argument 3</text><text text-anchor='start' x='46.7' y='-33' font-family='arial' font-size='10.00' fill='black'>I am an undercut argument. %23tag4</text></g><g id='edge2' class='edge'><title>n3%26%2345%3b%26gt%3bn2</title><path fill='none' stroke='black' d='M127.55%2c-64.28C130.02%2c-72.85 132.98%2c-83.12 135.7%2c-92.57'/><polygon fill='black' stroke='black' points='132.4%2c-93.75 138.53%2c-102.39 139.12%2c-91.81 132.4%2c-93.75'/></g></g></svg>

Any idea what's going on? Can you suggest a way I can make this work without having to press Enter in the URL bar?

Feature request: usable via command line

This is a cool utility, after I found it I started using it all the time. Thank you for this & the research behind it!

I think it could be even more useful and efficient used directly from the command line. It's really so simple and needs only one piece of external data (the svg code). Being able to run something like $ svg2data optimized.svg optimized.svg.datauri would make this 💯 vs going through node prompt / js file / online for standalone file conversions.

Compact version

Just wanted to leave this here in case somebody is looking for something more compact. Turned out my use case didn't include any colors matching those in here, and as that added a lot of code size, I compacted it down to the code below, which seems to work well for my use case in sudokupad.app.
This could probably minified quite a lot as it's still fairly verbosely-formatted and named.

const svgToTinyDataUri = (() => {
	// Source: https://github.com/tigt/mini-svg-data-uri
	const reWhitespace = /\s+/g,
		reUrlHexPairs = /%[\dA-F]{2}/g,
		hexDecode = {'%20': ' ', '%3D': '=', '%3A': ':', '%2F': '/'},
		specialHexDecode = match => hexDecode[match] || match.toLowerCase(),
		svgToTinyDataUri = svg => {
			svg = String(svg);
			if(svg.charCodeAt(0) === 0xfeff) svg = svg.slice(1);
			svg = svg
				.trim()
				.replace(reWhitespace, ' ')
				.replaceAll('"', '\'');
			svg = encodeURIComponent(svg);
			svg = svg.replace(reUrlHexPairs, specialHexDecode);
			return 'data:image/svg+xml,' + svg;
		};
	svgToTinyDataUri.toSrcset = svg => svgToTinyDataUri(svg).replace(/ /g, '%20');
	return svgToTinyDataUri;
})();

Why single quotes?

I was hoping to see the "why" documented in the readme - Why are double quotes replaced by single quotes? It's causing some headache in our implementation and I'd like to be able to speak on why that choice was made.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.