<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;Ak8FQ3oyfyp7ImA9WhRRFE4.&quot;"><id>tag:blogger.com,1999:blog-15626356</id><updated>2011-11-27T16:06:52.497-08:00</updated><category term="ruby" /><category term="FireEagle" /><category term="emacs" /><category term="geocoding" /><category term="tools" /><category term="javascript" /><category term="AES" /><category term="CSS" /><category term="Google Maps API" /><category term="geomapping" /><category term="books" /><category term="Google Spreadsheets" /><category term="perl" /><category term="Opera" /><category term="SVG" /><category term="github" /><category term="bookmarks" /><category term="firefox extensions" /><category term="BOM" /><category term="getters" /><category term="OpenID" /><category term="EditGrid" /><category term="Greasemonkey" /><category term="chrome extensions" /><category term="Firefox" /><category term="Firebug" /><category term="opera extensions" /><category term="Chrome" /><category term="Exhibit" /><category term="extension" /><category term="reference" /><category term="mac" /><category term="xpath" /><category term="HTML" /><category term="design" /><category term="standards" /><category term="MD5" /><category term="JSON" /><category term="Google Gears" /><category term="user script" /><category term="Time zones" /><category term="google" /><title>ecmanaut</title><subtitle type="html">Webby thoughts, most about around interesting applications of ecmascript in relation to other open web standards. I live in Mountain View, California, and spend some of my spare time co-maintaining Greasemonkey together with Anthony Lieuallen.</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://ecmanaut.blogspot.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://ecmanaut.blogspot.com/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/15626356/posts/default?start-index=26&amp;max-results=25&amp;redirect=false&amp;v=2" /><author><name>Johan Sundström</name><uri>http://www.blogger.com/profile/04076097346172610543</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>242</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/blogspot/xxBcs" /><feedburner:info uri="blogspot/xxbcs" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry gd:etag="W/&quot;CUYARX4_cCp7ImA9WhdbEEQ.&quot;"><id>tag:blogger.com,1999:blog-15626356.post-7720472903000055531</id><published>2011-10-08T09:42:00.000-07:00</published><updated>2011-10-08T09:59:04.048-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-10-08T09:59:04.048-07:00</app:edited><title>Death and IE</title><content type="html">This post is a brief celebration of succession on the web. Not Mosaic begat Netscape begat Mozilla begat Firefox succession, but Firefox 4 begat Firefox 5 begat Firefox 6 begat Firefox 7 and Chrome N begate Chrome N+1 type succession. Google got it right with Chrome last decade, and not long thereafter, &lt;a href="http://blog.mozilla.com/webdev/2011/10/05/stay-hungry-stay-foolish/"&gt;Mozilla got it too&lt;/a&gt; this year.&lt;br /&gt;
&lt;br /&gt;
Quoting that post's quote of Steve Jobs' &lt;a href="http://www.youtube.com/watch?v=UF8uR6Z6KLc"&gt;2005 Stanford commencement address&lt;/a&gt; (worth watching, if you haven't),&lt;br /&gt;
&lt;blockquote&gt;Death is very likely the single best invention of Life. It is Life’s change agent. It clears out the old to make way for the new. Right now the new is you, but someday not too long from now, you will gradually become the old and be cleared away.&lt;/blockquote&gt;&lt;br /&gt;
This very strongly applies to web browsers, and as it turns out, the best thing a browser version can do (besides getting things right in the first place) is dying even more quickly than it came. I wonder if this enlightened insight might have sprung with Mozilla, if only Firefox could have kept its inaugural name, &lt;a href="http://en.wikipedia.org/wiki/History_of_Firefox#Naming"&gt;Phoenix&lt;/a&gt;, which it now fully embodies, but at least now, this gift has finally been given to web developers: &lt;br /&gt;
&lt;blockquote&gt;You need not bother writing applications (or perfecting layouts) to high-fidelity for old browsers, for their time is short and their better ancestors replace them quickly.&lt;/blockquote&gt;&lt;br /&gt;
Assuming your deployment domain is web pages. As browser add-ons go, if you still maintain one of the old style XPI design your work burden has shot through the roof instead, unless you have near zero UI footprint, happen to only need and use APIs that time proves to remain stable and host it on addons.mozilla.org, where they bump its maxVersion every few weeks for you when it still seems to work. Failing either, you have to manually update and test it seven times per year. In Chrome, this has premeditatedly been addressed by not promiscuously offering any APIs it can't support in the long run, at the cost of limiting how much add-ons can do. Firefox, in this regard, remains the only browser where add-on authors can innovate 100% of the browser, and in this regard it has filled an important need in the browser eco-system (and still does). It is both its greatest feature and its greatest burden. Hopefully this will be mitigated to some extent with Jetpack and the new add-on builder.&lt;br /&gt;
&lt;br /&gt;
Returning to the paramount topic of graceful, benevolent, rapid-evolution-supportive death, &lt;a href="http://paulirish.com/2011/browser-market-pollution-iex-is-the-new-ie6/"&gt;Microsoft's IE&lt;/a&gt; &lt;a href="http://geddesign.com/post/10775181893/microsofts-golden-ticket-ie10"&gt;does not yet get it&lt;/a&gt;. Like a third world nation befallen by sudden prosperity, it has doubled its reproduction rate while keeping its mortality rate constant. As noted in mentioned posts, this does not bring just better browsers faster, it brings over-population, and makes web development unsustainable. Or, as Paul Irish put it in the first post: it pollutes the browser market.&lt;br /&gt;
&lt;br /&gt;
In this respect, the conditional comments and many "backwards compatibility simulation" modes IE bring you are not mainly tools helping web developers make sites work on Internet Explorer, but a huge extra burden of work forced onto web developers, to cope with IE's broken release process. This is Microsoft's job, not ours, and we should be outraged with them for forcing it on us.&lt;br /&gt;
&lt;br /&gt;
It is not the rotting corpses of IE6, IE7, IE8 or IE9 that all need to die to give space to IE10, which still smells fresh, it is a broken release process that needs to get addressed and brought up to date with best browser practices of the decade. It is the reinvention of sudden death, not just the gift of new life, that must come to Redmond, too. I applaud the IE team for making it their business to get up to speed with the web's evolution, but it's less the whats than the hows that are important to get right now. SVG is great, but sort out the release process before taking on, say, webGL. It can wait. Fixing the world's hard problems like over-population is harder than running after the latest ooo-shiny! - but the alternative is systemic collapse.&lt;br /&gt;
&lt;br /&gt;
For a browser, it is better to live a great but short life and go out with a boom, than it is to burden its extended family with a never-ending old age in an insufferable early-set rigor mortis. However you feel about &lt;a href="http://www.apple.com/stevejobs/"&gt;Steve Jobs&lt;/a&gt; he lived and died in this way, never holding back, never growing stale of mind nor action, and the world was better off for it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15626356-7720472903000055531?l=ecmanaut.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/lIT_wwLpwI5bHAcfRdLGvjtfk5k/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/lIT_wwLpwI5bHAcfRdLGvjtfk5k/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/lIT_wwLpwI5bHAcfRdLGvjtfk5k/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/lIT_wwLpwI5bHAcfRdLGvjtfk5k/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/xxBcs/~4/2GoClqf9ZPk" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://ecmanaut.blogspot.com/feeds/7720472903000055531/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=15626356&amp;postID=7720472903000055531" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/15626356/posts/default/7720472903000055531?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/15626356/posts/default/7720472903000055531?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/xxBcs/~3/2GoClqf9ZPk/death-and-ie.html" title="Death and IE" /><author><name>Johan Sundström</name><uri>http://www.blogger.com/profile/04076097346172610543</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://ecmanaut.blogspot.com/2011/10/death-and-ie.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0QMQHg6fip7ImA9WhdUE08.&quot;"><id>tag:blogger.com,1999:blog-15626356.post-4621964446376871143</id><published>2011-09-29T12:36:00.000-07:00</published><updated>2011-09-29T12:43:01.616-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-09-29T12:43:01.616-07:00</app:edited><title>Running an old rails 2.3.8 with rvm</title><content type="html">I was helping set up a local (legacy) rails 2.3.8 server on a macbook today, autonomous from the system ruby installation. This was a bit messy, as modern versions of rubygems conflict with the old rails 2.3.8 environment to the tune of:&lt;br /&gt;
&lt;pre&gt;Uninitialized constant ActiveSupport::Dependencies::Mutex (NameError)&lt;/pre&gt;...when you try to start the server. Here's the recipe I came up with: &lt;ol&gt;&lt;li&gt;&lt;a href="http://beginrescueend.com/rvm/install/"&gt;Install rvm.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;pre&gt;&lt;code&gt;# Install ruby 1.8.7 and downgrade its rubygems to 1.5.3:
rvm install 1.8.7 &amp;amp;&amp;amp; \
  rvm use 1.8.7 &amp;amp;&amp;amp; \
  rvm gem install -v 1.4.2 rubygems-update &amp;amp;&amp;amp; \
  rvm gem update --system 1.4.2 &amp;amp;&amp;amp; \
  update_rubygems &amp;amp;&amp;amp; \
  echo 'Okay.'&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;&lt;pre&gt;&lt;code&gt;# Install all the gems you need, for instance:
rvm gem install -v 2.3.8 rails &amp;amp;&amp;amp; \
  rvm gem install -v 3.0 haml &amp;amp;&amp;amp; \
  rvm gem install -v 2.1 authlogic &amp;amp;&amp;amp; \
  rvm gem install -v 1.0 dalli &amp;amp;&amp;amp; \
  rvm gem install -v 0.2 omniauth &amp;amp;&amp;amp; \
  rvm gem install -v 2.7.0 erubis &amp;amp;&amp;amp; \
  rvm gem install -v 1.3.3 sqlite3 &amp;amp;&amp;amp; \
  echo 'Gems installed!'&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;If needed, run &lt;code&gt;rake db:setup&lt;/code&gt; in your rails tree to set up its databases.&lt;/li&gt;
&lt;li&gt;Done! &lt;code&gt;rails/script/server -p &lt;i&gt;your_port&lt;/i&gt;&lt;/code&gt; is ready for action.&lt;/li&gt;
&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15626356-4621964446376871143?l=ecmanaut.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/Gnsb9yIfN-KDQ9mEJrfwWcSXaDo/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Gnsb9yIfN-KDQ9mEJrfwWcSXaDo/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/Gnsb9yIfN-KDQ9mEJrfwWcSXaDo/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Gnsb9yIfN-KDQ9mEJrfwWcSXaDo/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/xxBcs/~4/obhIe_AJxYA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://ecmanaut.blogspot.com/feeds/4621964446376871143/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=15626356&amp;postID=4621964446376871143" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/15626356/posts/default/4621964446376871143?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/15626356/posts/default/4621964446376871143?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/xxBcs/~3/obhIe_AJxYA/running-old-rails-238-with-rvm.html" title="Running an old rails 2.3.8 with rvm" /><author><name>Johan Sundström</name><uri>http://www.blogger.com/profile/04076097346172610543</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://ecmanaut.blogspot.com/2011/09/running-old-rails-238-with-rvm.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUQGQn4yfCp7ImA9WhdTEEo.&quot;"><id>tag:blogger.com,1999:blog-15626356.post-1635257323003270877</id><published>2011-07-05T23:46:00.000-07:00</published><updated>2011-07-07T14:15:23.094-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-07-07T14:15:23.094-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="user script" /><category scheme="http://www.blogger.com/atom/ns#" term="SVG" /><category scheme="http://www.blogger.com/atom/ns#" term="github" /><title>Optimized SVGs at gist.github.com</title><content type="html">Lately, I've been having a lot of fun hand optimizing SVG files for size, a bit like &lt;a href="http://intertwingly.net/"&gt;Sam Ruby&lt;/a&gt; does for his blog (it is highly instructive peeking at &lt;a href="http://intertwingly.net/svg/"&gt;his collection&lt;/a&gt;, as I think I have mentioned before). &lt;br /&gt;
&lt;br /&gt;
For me, SVG has something of the magical flair I first found in HTML in the nineties, back when it was the new bleeding edge New Thing, but I argue that it's even more fun than HTML was. The &lt;a href="http://www.w3.org/TR/SVG/"&gt;W3C SVG specs&lt;/a&gt; are not prohibitively difficult to read, and of course you have much greater graphical freedom than structured documents can afford you (duh!).&lt;br /&gt;
&lt;br /&gt;
Like Sam, I try for something presentable in a kilobyte or less (uncompressed, though modern good browsers are as happy to render SVG:s delivered with &lt;code&gt;content-encoding: gzip&lt;/code&gt;, of course, as long as they are otherwise correct and delivered with an &lt;code&gt;image/svg&lt;/code&gt; or &lt;code&gt;image/svg+xml&lt;/code&gt; content-type), and to never enforce a fix width in the svg tag itself – so they just beautifully grow to any size you want them to be, with no loss of quality.&lt;br /&gt;
&lt;br /&gt;
Which is the other main beauty of SVG, besides being fly-weight, standardized, widely supported and still growing broader support in all the main-stream browsers. Over the last few years, the SVG front has been progressing happily and now is very practically useful already, for at least those of us that care most about Chrome, Firefox and Opera (I get the perception that Opera's often rather exceptional lead on the SVG support front is largely or even solely the work of &lt;a href="http://my.opera.com/MacDev_ed/blog/"&gt;Erik Dahlström&lt;/a&gt;, but I might exaggerate a bit).&lt;br /&gt;
&lt;br /&gt;
&lt;svg style="float:left; width:360px; height:320px; margin:0 0.5em 0.5em 0" viewBox="-160 -160 360 320" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"&gt;&lt;path id="f" d="m123,0a123,123 0,0 1-246,0a123,123 0,0 1 246,0"/&gt;&lt;g fill="#057"&gt;&lt;circle r="160"/&gt;&lt;circle r="150" fill="#fff"/&gt;[&lt;text font-size="28" font-stretch="condensed" font-family="Impact"&gt;&lt;animatetransform type="rotate" from="360 0 0" to="0 0 0" dur="10s" attributeName="transform" repeatCount="indefinite"/&gt;&lt;textpath xlink:href="#f"&gt;I thought what I'd do was, I'd pretend I was one of those deaf-mutes&lt;/textPath&gt;&lt;/text&gt;] (&amp;lt;- this is text content in an inline SVG, if your browser or reader has stripped off the SVG or can't render such modernisms :-) &lt;circle r="115"/&gt;&lt;circle r="95" fill="#fff"/&gt;&lt;path d="m-8-119h16 l2,5h-20z"/&gt;&lt;circle cx="160" cy="0" r="40"/&gt;&lt;path d="m-95-20v-20h255a40,40 0,0 1 0,80h-55v-20z"/&gt;&lt;path d="m-85 0a85,85 0,0 0 170,0h-20a65,65 0,0 1-130,0z"/&gt;&lt;path d="m-65 20v20h140v-20z"/&gt;&lt;path d="m-115-20v10h25v30h250a20,20 0,0 0 0,-40z" fill="#fff"/&gt;&lt;path d="m-20 10c-17-14-27-14-44 0 6-25 37-25 44 0z"/&gt;&lt;path d="m60 10c-17-14-27-14-44 0 6-25 37-25 44 0z"/&gt;&lt;/g&gt;&lt;/svg&gt; Anyway, this weekend, I had fun turning the Laughing Man (from &lt;a href="http://en.wikipedia.org/wiki/Ghost_in_the_Shell:_Stand_Alone_Complex"&gt;Ghost in the Shell: Stand Alone Complex&lt;/a&gt;) that &lt;a href="http://www.ta-sa.org/projects/laughing_man_logo.html"&gt;@elmex&lt;/a&gt; vectorized at some point, into a 1000 byte version of my own, also featuring the gentle rotating text seen in the anime series (&lt;a href="http://www.youtube.com/watch?v=4nw9hooeZ_I"&gt;YouTube&lt;/a&gt;), via declarative animation (so there is no javascript involved here).&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Edit:&lt;/b&gt; I initially missed an excellent opportunity here to plug Jeff Schiller's &lt;a href="http://codedread.com/scour"&gt;scour&lt;/a&gt;, which is an ideal first step when you start from an SVG source file. Be sure to run with -p something-large, as its defaults are being lossy about precision, which cuts needed decimals from some input files. With -p 99 you'll be on the safe side. Experiment with low single-digit numbers if you like (the current default – 5 – is often good), but make sure things are still looking right, or you may just ruin your file, rather than optimizing it for tiny foot-print. Broken images don't get extra credit for also being small!&lt;br /&gt;
&lt;br /&gt;
The result is in &lt;a href="https://gist.github.com/1066590"&gt;this gist&lt;/a&gt; (if you install &lt;a href="https://github.com/johan/github-improved/raw/master/gist-svg.user.js"&gt;this user script&lt;/a&gt;, you can swap between &lt;code&gt;*.svg&lt;/code&gt; text/plain source code image/svg rendition) or to the left, if your browser renders inline SVG:s properly in HTML content (I recommend the gist over view source, as Blogger inserts linebreak HTML tags unless I strip out all newlines first).&lt;br /&gt;
&lt;br /&gt;
What surprised me, when I made this user script, is how far standards support has come in modern browsers: in order to inject the &lt;code&gt;&amp;lt;svg&amp;gt;&lt;/code&gt; tag I create for the rendered version, I had to feed the source through &lt;code&gt;DOMParser&lt;/code&gt; (as setting &lt;code&gt;.innerHTML&lt;/code&gt; is lossy from treating the SVG content as &lt;code&gt;text/html&lt;/code&gt;, not &lt;code&gt;text/xml&lt;/code&gt;), and the few lines doing that, just magically worked in all of Chrome, Firefox 4 and Opera 11 (de-jQuery:fied, to make more sense outside of the script's context) with no special extra effort on my part:&lt;br /&gt;
&lt;pre&gt;&lt;code&gt;// turn the raw SVG source string into an XML document:
svg = (new DOMParser).parseFromString(svg, 'text/xml');

// import it into an SVGSVGElement in this document:
svg = document.importNode(svg.documentElement, true);

// and insert that element somewhere in the document:
document.body.appendChild(svg);&lt;/code&gt;&lt;/pre&gt;To me, that's a rather clear sign SVG is ready for prime time now.&lt;br /&gt;
&lt;br /&gt;
&lt;svg style="width:160px; height:160px; float:left; margin:0 0.5em 0.5em 0" xmlns="http://www.w3.org/2000/svg" viewBox="-0.2 -1 379 334"&gt;&lt;path id="puddle" fill="#9CDAF1" d="m296.94 295.43c0 20.533-47.56 37.176-106.22 37.176-58.67 0-106.23-16.643-106.23-37.176s47.558-37.18 106.23-37.18c58.66 0 106.22 16.65 106.22 37.18z"/&gt;&lt;g id="shadow-legs" fill="#7DBBE6"&gt;&lt;path d="m161.85 331.22v-26.5c0-3.422-.619-6.284-1.653-8.701 6.853 5.322 7.316 18.695 7.316 18.695v17.004c6.166.481 12.534.773 19.053.861l-.172-16.92c-.944-23.13-20.769-25.961-20.769-25.961-7.245-1.645-7.137 1.991-6.409 4.34-7.108-12.122-26.158-10.556-26.158-10.556-6.611 2.357-.475 6.607-.475 6.607 10.387 3.775 11.33 15.105 11.33 15.105v23.622c5.72.98 11.71 1.79 17.94 2.4z"/&gt;&lt;path d="m245.4 283.48s-19.053-1.566-26.16 10.559c.728-2.35.839-5.989-6.408-4.343 0 0-19.824 2.832-20.768 25.961l-.174 16.946c6.509-.025 12.876-.254 19.054-.671v-17.219s.465-13.373 7.316-18.695c-1.034 2.417-1.653 5.278-1.653 8.701v26.775c6.214-.544 12.211-1.279 17.937-2.188v-24.113s.944-11.33 11.33-15.105c0-.01 6.13-4.26-.48-6.62z"/&gt;&lt;/g&gt;&lt;path id="cat" d="m378.18 141.32l.28-1.389c-31.162-6.231-63.141-6.294-82.487-5.49 3.178-11.451 4.134-24.627 4.134-39.32 0-21.073-7.917-37.931-20.77-50.759 2.246-7.25 5.246-23.351-2.996-43.963 0 0-14.541-4.617-47.431 17.396-12.884-3.22-26.596-4.81-40.328-4.81-15.109 0-30.376 1.924-44.615 5.83-33.94-23.154-48.923-18.411-48.923-18.411-9.78 24.457-3.733 42.566-1.896 47.063-11.495 12.406-18.513 28.243-18.513 47.659 0 14.658 1.669 27.808 5.745 39.237-19.511-.71-50.323-.437-80.373 5.572l.276 1.389c30.231-6.046 61.237-6.256 80.629-5.522.898 2.366 1.899 4.661 3.021 6.879-19.177.618-51.922 3.062-83.303 11.915l.387 1.36c31.629-8.918 64.658-11.301 83.649-11.882 11.458 21.358 34.048 35.152 74.236 39.484-5.704 3.833-11.523 10.349-13.881 21.374-7.773 3.718-32.379 12.793-47.142-12.599 0 0-8.264-15.109-24.082-16.292 0 0-15.344-.235-1.059 9.562 0 0 10.267 4.838 17.351 23.019 0 0 9.241 31.01 53.835 21.061v32.032s-.943 11.33-11.33 15.105c0 0-6.137 4.249.475 6.606 0 0 28.792 2.361 28.792-21.238v-34.929s-1.142-13.852 5.663-18.667v57.371s-.47 13.688-7.551 18.881c0 0-4.723 8.494 5.663 6.137 0 0 19.824-2.832 20.769-25.961l.449-58.06h4.765l.453 58.06c.943 23.129 20.768 25.961 20.768 25.961 10.383 2.357 5.663-6.137 5.663-6.137-7.08-5.193-7.551-18.881-7.551-18.881v-56.876c6.801 5.296 5.663 18.171 5.663 18.171v34.929c0 23.6 28.793 21.238 28.793 21.238 6.606-2.357.474-6.606.474-6.606-10.386-3.775-11.33-15.105-11.33-15.105v-45.786c0-17.854-7.518-27.309-14.87-32.3 42.859-4.25 63.426-18.089 72.903-39.591 18.773.516 52.557 2.803 84.873 11.919l.384-1.36c-32.131-9.063-65.692-11.408-84.655-11.96.898-2.172 1.682-4.431 2.378-6.755 19.25-.80 51.38-.79 82.66 5.46z"/&gt;&lt;path id="face" fill="#F4CBB2" d="m258.19 94.132c9.231 8.363 14.631 18.462 14.631 29.343 0 50.804-37.872 52.181-84.585 52.181-46.721 0-84.589-7.035-84.589-52.181 0-10.809 5.324-20.845 14.441-29.174 15.208-13.881 40.946-6.531 70.147-6.531 29.07-.004 54.72-7.429 69.95 6.357z"/&gt;&lt;path id="eyes" fill="#FFF" d="m160.1 126.06 c0 13.994-7.88 25.336-17.6 25.336-9.72 0-17.6-11.342-17.6-25.336 0-13.992 7.88-25.33 17.6-25.33 9.72.01 17.6 11.34 17.6 25.33z m94.43 0 c0 13.994-7.88 25.336-17.6 25.336-9.72 0-17.6-11.342-17.6-25.336 0-13.992 7.88-25.33 17.6-25.33 9.72.01 17.6 11.34 17.6 25.33z"/&gt;&lt;g fill="#AD5C51"&gt;&lt;path id="pupils" d="m154.46 126.38 c0 9.328-5.26 16.887-11.734 16.887s-11.733-7.559-11.733-16.887c0-9.331 5.255-16.894 11.733-16.894 6.47 0 11.73 7.56 11.73 16.89z m94.42 0 c0 9.328-5.26 16.887-11.734 16.887s-11.733-7.559-11.733-16.887c0-9.331 5.255-16.894 11.733-16.894 6.47 0 11.73 7.56 11.73 16.89z"/&gt;&lt;circle id="nose" cx="188.5" cy="148.56" r="4.401"/&gt;&lt;path id="mouth" d="m178.23 159.69c-.26-.738.128-1.545.861-1.805.737-.26 1.546.128 1.805.861 1.134 3.198 4.167 5.346 7.551 5.346s6.417-2.147 7.551-5.346c.26-.738 1.067-1.121 1.805-.861s1.121 1.067.862 1.805c-1.529 4.324-5.639 7.229-10.218 7.229s-8.68-2.89-10.21-7.22z"/&gt;&lt;/g&gt;&lt;path id="octo" fill="#C3E4D8" d="m80.641 179.82 c0 1.174-1.376 2.122-3.07 2.122-1.693 0-3.07-.948-3.07-2.122 0-1.175 1.377-2.127 3.07-2.127 1.694 0 3.07.95 3.07 2.13z m8.5 4.72 c0 1.174-1.376 2.122-3.07 2.122-1.693 0-3.07-.948-3.07-2.122 0-1.175 1.377-2.127 3.07-2.127 1.694 0 3.07.95 3.07 2.13z m5.193 6.14 c0 1.174-1.376 2.122-3.07 2.122-1.693 0-3.07-.948-3.07-2.122 0-1.175 1.377-2.127 3.07-2.127 1.694 0 3.07.95 3.07 2.13z m4.72 7.08 c0 1.174-1.376 2.122-3.07 2.122-1.693 0-3.07-.948-3.07-2.122 0-1.175 1.377-2.127 3.07-2.127 1.694 0 3.07.95 3.07 2.13z m5.188 6.61 c0 1.174-1.376 2.122-3.07 2.122-1.693 0-3.07-.948-3.07-2.122 0-1.175 1.377-2.127 3.07-2.127 1.694 0 3.07.95 3.07 2.13z m7.09 5.66 c0 1.174-1.376 2.122-3.07 2.122-1.693 0-3.07-.948-3.07-2.122 0-1.175 1.377-2.127 3.07-2.127 1.694 0 3.07.95 3.07 2.13z m9.91 3.78 c0 1.174-1.376 2.122-3.07 2.122-1.693 0-3.07-.948-3.07-2.122 0-1.175 1.377-2.127 3.07-2.127 1.694 0 3.07.95 3.07 2.13z m9.87 0 c0 1.174-1.376 2.122-3.07 2.122-1.693 0-3.07-.948-3.07-2.122 0-1.175 1.377-2.127 3.07-2.127 1.694 0 3.07.95 3.07 2.13z m10.01 -1.64 c0 1.174-1.376 2.122-3.07 2.122-1.693 0-3.07-.948-3.07-2.122 0-1.175 1.377-2.127 3.07-2.127 1.694 0 3.07.95 3.07 2.13z"/&gt;&lt;path id="drop" fill="#9CDAF1" d="m69.369 186.12l-3.066 10.683s-.8 3.861 2.84 4.546c3.8-.074 3.486-3.627 3.223-4.781z"/&gt;&lt;/svg&gt; While github reports having no plans on serving &lt;code&gt;*.svg&lt;/code&gt; gists with an image content-type (they don't want people using gists for image hosting, I guess, even though it's sad you can't easily preview without saving to disk or using my hack above) I still think the light-weight gist community oriented sharing is good for this kind of thing. Others happily forked the &lt;a href="https://gist.github.com/1007813"&gt;octocat&lt;/a&gt; SVG I &lt;a href="https://github.com/blog/868-who-is-github-anyway#comment-12368"&gt;similarly format converted&lt;/a&gt; a while ago from the github About page, and &lt;a href="https://gist.github.com/milligramme"&gt;milligramme&lt;/a&gt; made &lt;a href="https://gist.github.com/1058563"&gt;this much spacier version&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
I gather all my SVG play in a &lt;a href="https://github.com/johan/svg-cleanups/"&gt;svg-cleanups&lt;/a&gt; repository on github, if anyone wants to get inspired the fork or follow way, and occasionally &lt;a href="http://twitter.com/ecmanaut/"&gt;tweet&lt;/a&gt; about it. If you find this kind of exercise as much fun, I love hearing about it; here, on Twitter, github, or elsewhere. I believe it's good teaching and learning for the web as a whole, too. Any logos, trademarks and the like above are property of their respective owners.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15626356-1635257323003270877?l=ecmanaut.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/3vFZSwUWbFQn4vCW1MG3o6rFBEQ/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/3vFZSwUWbFQn4vCW1MG3o6rFBEQ/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/3vFZSwUWbFQn4vCW1MG3o6rFBEQ/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/3vFZSwUWbFQn4vCW1MG3o6rFBEQ/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/xxBcs/~4/OX6IcEb8bNs" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://ecmanaut.blogspot.com/feeds/1635257323003270877/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=15626356&amp;postID=1635257323003270877" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/15626356/posts/default/1635257323003270877?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/15626356/posts/default/1635257323003270877?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/xxBcs/~3/OX6IcEb8bNs/optimized-svgs-at-gistgithubcom.html" title="Optimized SVGs at gist.github.com" /><author><name>Johan Sundström</name><uri>http://www.blogger.com/profile/04076097346172610543</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://ecmanaut.blogspot.com/2011/07/optimized-svgs-at-gistgithubcom.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkMAQns4eSp7ImA9WhZUEUU.&quot;"><id>tag:blogger.com,1999:blog-15626356.post-2482992080593249833</id><published>2011-06-04T04:28:00.000-07:00</published><updated>2011-06-04T04:54:03.531-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-06-04T04:54:03.531-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="SVG" /><category scheme="http://www.blogger.com/atom/ns#" term="github" /><title>Draw your own Github SVGs, step by step</title><content type="html">I SVG:ified and played a little further with the logo material from the recently published &lt;a href="https://github.com/blog/868-who-is-github-anyway"&gt;Github about page&lt;/a&gt;, and then tonight I figured it would be fun to visualize the elegant process by which a raw SVG image is built up, piece by piece, by rather basic building blocks. With just a little bit of javascript magic to help you, here is how you piece together your own github schwag from scratch (works like a charm in Chrome, Firefox 4, and presumably any other modern browser that can handle inline SVG images&lt;noscript&gt; - if you do not see them in your feed reader despite a modern browser, or want to try the interactive behaviour, &lt;a href="http://ecmanaut.blogspot.com/2011/06/draw-your-own-github-svgs-step-by-step.html"&gt;head over to the blog post itself&lt;/a&gt;&lt;/noscript&gt;):&lt;div style="max-width: 90%; margin: 0 auto;"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" viewBox="-0.2 -1 379 334" height="70%"&gt;&lt;path id="puddle" fill="#9CDAF1" d="m296.94 295.43c0 20.533-47.56 37.176-106.22 37.176-58.67 0-106.23-16.643-106.23-37.176s47.558-37.18 106.23-37.18c58.66 0 106.22 16.65 106.22 37.18z"/&gt;&lt;g id="shadow-legs" fill="#7DBBE6"&gt;&lt;path d="m161.85 331.22v-26.5c0-3.422-.619-6.284-1.653-8.701 6.853 5.322 7.316 18.695 7.316 18.695v17.004c6.166.481 12.534.773 19.053.861l-.172-16.92c-.944-23.13-20.769-25.961-20.769-25.961-7.245-1.645-7.137 1.991-6.409 4.34-7.108-12.122-26.158-10.556-26.158-10.556-6.611 2.357-.475 6.607-.475 6.607 10.387 3.775 11.33 15.105 11.33 15.105v23.622c5.72.98 11.71 1.79 17.94 2.4z"/&gt;&lt;path d="m245.4 283.48s-19.053-1.566-26.16 10.559c.728-2.35.839-5.989-6.408-4.343 0 0-19.824 2.832-20.768 25.961l-.174 16.946c6.509-.025 12.876-.254 19.054-.671v-17.219s.465-13.373 7.316-18.695c-1.034 2.417-1.653 5.278-1.653 8.701v26.775c6.214-.544 12.211-1.279 17.937-2.188v-24.113s.944-11.33 11.33-15.105c0-.01 6.13-4.26-.48-6.62z"/&gt;&lt;/g&gt;&lt;path id="cat" d="m378.18 141.32l.28-1.389c-31.162-6.231-63.141-6.294-82.487-5.49 3.178-11.451 4.134-24.627 4.134-39.32 0-21.073-7.917-37.931-20.77-50.759 2.246-7.25 5.246-23.351-2.996-43.963 0 0-14.541-4.617-47.431 17.396-12.884-3.22-26.596-4.81-40.328-4.81-15.109 0-30.376 1.924-44.615 5.83-33.94-23.154-48.923-18.411-48.923-18.411-9.78 24.457-3.733 42.566-1.896 47.063-11.495 12.406-18.513 28.243-18.513 47.659 0 14.658 1.669 27.808 5.745 39.237-19.511-.71-50.323-.437-80.373 5.572l.276 1.389c30.231-6.046 61.237-6.256 80.629-5.522.898 2.366 1.899 4.661 3.021 6.879-19.177.618-51.922 3.062-83.303 11.915l.387 1.36c31.629-8.918 64.658-11.301 83.649-11.882 11.458 21.358 34.048 35.152 74.236 39.484-5.704 3.833-11.523 10.349-13.881 21.374-7.773 3.718-32.379 12.793-47.142-12.599 0 0-8.264-15.109-24.082-16.292 0 0-15.344-.235-1.059 9.562 0 0 10.267 4.838 17.351 23.019 0 0 9.241 31.01 53.835 21.061v32.032s-.943 11.33-11.33 15.105c0 0-6.137 4.249.475 6.606 0 0 28.792 2.361 28.792-21.238v-34.929s-1.142-13.852 5.663-18.667v57.371s-.47 13.688-7.551 18.881c0 0-4.723 8.494 5.663 6.137 0 0 19.824-2.832 20.769-25.961l.449-58.06h4.765l.453 58.06c.943 23.129 20.768 25.961 20.768 25.961 10.383 2.357 5.663-6.137 5.663-6.137-7.08-5.193-7.551-18.881-7.551-18.881v-56.876c6.801 5.296 5.663 18.171 5.663 18.171v34.929c0 23.6 28.793 21.238 28.793 21.238 6.606-2.357.474-6.606.474-6.606-10.386-3.775-11.33-15.105-11.33-15.105v-45.786c0-17.854-7.518-27.309-14.87-32.3 42.859-4.25 63.426-18.089 72.903-39.591 18.773.516 52.557 2.803 84.873 11.919l.384-1.36c-32.131-9.063-65.692-11.408-84.655-11.96.898-2.172 1.682-4.431 2.378-6.755 19.25-.80 51.38-.79 82.66 5.46z"/&gt;&lt;path id="face" fill="#F4CBB2" d="m258.19 94.132c9.231 8.363 14.631 18.462 14.631 29.343 0 50.804-37.872 52.181-84.585 52.181-46.721 0-84.589-7.035-84.589-52.181 0-10.809 5.324-20.845 14.441-29.174 15.208-13.881 40.946-6.531 70.147-6.531 29.07-.004 54.72-7.429 69.95 6.357z"/&gt;&lt;path id="eyes" fill="#FFF" d="m160.1 126.06 c0 13.994-7.88 25.336-17.6 25.336-9.72 0-17.6-11.342-17.6-25.336 0-13.992 7.88-25.33 17.6-25.33 9.72.01 17.6 11.34 17.6 25.33z m94.43 0 c0 13.994-7.88 25.336-17.6 25.336-9.72 0-17.6-11.342-17.6-25.336 0-13.992 7.88-25.33 17.6-25.33 9.72.01 17.6 11.34 17.6 25.33z"/&gt;&lt;g fill="#AD5C51"&gt;&lt;path id="pupils" d="m154.46 126.38 c0 9.328-5.26 16.887-11.734 16.887s-11.733-7.559-11.733-16.887c0-9.331 5.255-16.894 11.733-16.894 6.47 0 11.73 7.56 11.73 16.89z m94.42 0 c0 9.328-5.26 16.887-11.734 16.887s-11.733-7.559-11.733-16.887c0-9.331 5.255-16.894 11.733-16.894 6.47 0 11.73 7.56 11.73 16.89z"/&gt;&lt;circle id="nose" cx="188.5" cy="148.56" r="4.401"/&gt;&lt;path id="mouth" d="m178.23 159.69c-.26-.738.128-1.545.861-1.805.737-.26 1.546.128 1.805.861 1.134 3.198 4.167 5.346 7.551 5.346s6.417-2.147 7.551-5.346c.26-.738 1.067-1.121 1.805-.861s1.121 1.067.862 1.805c-1.529 4.324-5.639 7.229-10.218 7.229s-8.68-2.89-10.21-7.22z"/&gt;&lt;/g&gt;&lt;path id="octo" fill="#C3E4D8" d="m80.641 179.82 c0 1.174-1.376 2.122-3.07 2.122-1.693 0-3.07-.948-3.07-2.122 0-1.175 1.377-2.127 3.07-2.127 1.694 0 3.07.95 3.07 2.13z m8.5 4.72 c0 1.174-1.376 2.122-3.07 2.122-1.693 0-3.07-.948-3.07-2.122 0-1.175 1.377-2.127 3.07-2.127 1.694 0 3.07.95 3.07 2.13z m5.193 6.14 c0 1.174-1.376 2.122-3.07 2.122-1.693 0-3.07-.948-3.07-2.122 0-1.175 1.377-2.127 3.07-2.127 1.694 0 3.07.95 3.07 2.13z m4.72 7.08 c0 1.174-1.376 2.122-3.07 2.122-1.693 0-3.07-.948-3.07-2.122 0-1.175 1.377-2.127 3.07-2.127 1.694 0 3.07.95 3.07 2.13z m5.188 6.61 c0 1.174-1.376 2.122-3.07 2.122-1.693 0-3.07-.948-3.07-2.122 0-1.175 1.377-2.127 3.07-2.127 1.694 0 3.07.95 3.07 2.13z m7.09 5.66 c0 1.174-1.376 2.122-3.07 2.122-1.693 0-3.07-.948-3.07-2.122 0-1.175 1.377-2.127 3.07-2.127 1.694 0 3.07.95 3.07 2.13z m9.91 3.78 c0 1.174-1.376 2.122-3.07 2.122-1.693 0-3.07-.948-3.07-2.122 0-1.175 1.377-2.127 3.07-2.127 1.694 0 3.07.95 3.07 2.13z m9.87 0 c0 1.174-1.376 2.122-3.07 2.122-1.693 0-3.07-.948-3.07-2.122 0-1.175 1.377-2.127 3.07-2.127 1.694 0 3.07.95 3.07 2.13z m10.01 -1.64 c0 1.174-1.376 2.122-3.07 2.122-1.693 0-3.07-.948-3.07-2.122 0-1.175 1.377-2.127 3.07-2.127 1.694 0 3.07.95 3.07 2.13z"/&gt;&lt;path id="drop" fill="#9CDAF1" d="m69.369 186.12l-3.066 10.683s-.8 3.861 2.84 4.546c3.8-.074 3.486-3.627 3.223-4.781z"/&gt;&lt;/svg&gt;&lt;center&gt;&lt;button id="step" onclick="step(this)" style="margin: 1em 0 1em"&gt;Redraw the octocat SVG image step by step&lt;/button&gt;&lt;div id="next_step" style="margin: 0 0 1em"&gt;&amp;nbsp;&lt;/div&gt;&lt;/center&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" viewBox="-0.147 -0.544 242 108" height="20%"&gt;&lt;g id="github" class="collegiate-regular"&gt;&lt;path d="m30.908 28.692c3.732 0 8.047-.933 12.946-2.799v12.013c-1.089.389-2.644.816-4.666 1.283.622 1.788.933 3.46.933 5.015 0 4.977-1.497 9.311-4.49 13.004s-6.862 5.891-11.605 6.59c-3.11.467-4.665 2.139-4.665 5.016 0 1.011.505 2.021 1.516 3.032 1.322 1.478 3.266 2.411 5.832 2.8 11.12 1.71 16.679 6.337 16.679 13.879 0 12.053-7.192 18.079-21.577 18.079-5.91 0-10.77-1.05-14.579-3.149-4.822-2.64-7.232-6.799-7.232-12.475 0-6.531 3.616-11.002 10.847-13.412v-.233c-2.644-1.633-3.965-4.121-3.965-7.465 0-4.354 1.244-7.076 3.732-8.164v-.233c-2.488-.855-4.705-2.8-6.648-5.832-2.178-3.267-3.266-6.766-3.266-10.498 0-5.599 1.983-10.264 5.948-13.996 3.81-3.499 8.359-5.249 13.646-5.249 3.81 0 7.348.933 10.614 2.799zm.467 61.35c0-3.966-3.266-5.948-9.797-5.948-6.298 0-9.447 2.061-9.447 6.182 0 4.043 3.421 6.064 10.264 6.064 5.986 0 8.98-2.099 8.98-6.298zm-17.962-44.788c0 5.365 2.449 8.048 7.348 8.048 4.743 0 7.115-2.722 7.115-8.165 0-2.255-.544-4.199-1.633-5.832-1.322-1.788-3.149-2.683-5.482-2.683-4.899.001-7.348 2.878-7.348 8.632z"/&gt;&lt;path d="m56.222 17.378c-2.255 0-4.179-.855-5.773-2.566-1.594-1.71-2.391-3.732-2.391-6.065 0-2.411.797-4.471 2.391-6.182 1.594-1.71 3.518-2.565 5.773-2.565 2.177 0 4.063.855 5.657 2.566s2.391 3.771 2.391 6.182c0 2.333-.797 4.354-2.391 6.065-1.594 1.71-3.48 2.565-5.657 2.565z"/&gt;&lt;path d="m49.574 78.262c.155-1.555.233-4.198.233-7.931v-36.274c0-3.654-.078-6.182-.233-7.581h13.18c-.156 1.478-.233 3.927-.233 7.348v35.807c0 3.966.078 6.843.233 8.631h-13.18z"/&gt;&lt;path d="m86.888 26.476h10.147v11.314c-.389 0-1.108-.039-2.158-.117s-2.041-.117-2.974-.117h-5.015v21.694c0 5.21 1.71 7.814 5.132 7.814 2.411 0 4.587-.66 6.532-1.982v11.663c-2.877 1.556-6.337 2.333-10.381 2.333-5.676 0-9.603-2.021-11.78-6.064-1.633-3.033-2.45-7.814-2.45-14.347v-20.877h.117v-.233l-1.75-.116c-1.011 0-2.333.116-3.965.35v-11.315h5.715v-4.549c0-2.177-.117-3.927-.35-5.249h13.529c-.233 1.478-.35 3.149-.35 5.015v4.783z"/&gt;&lt;path d="m127.86 26.126c-3.343 0-6.842 1.167-10.497 3.499v-20.411c0-4.432.078-7.348.233-8.748h-13.296c.233 1.244.35 4.16.35 8.748v61.7c0 3.576-.117 6.026-.35 7.348h13.53c0-.233-.078-1.186-.233-2.857-.155-1.672-.233-3.169-.233-4.49v-28.693c2.722-2.566 5.365-3.849 7.931-3.849 2.955 0 5.21 1.477 6.765 4.432 1.166 2.333 1.75 5.249 1.75 8.748l-.117 15.745c0 2.645-.194 6.299-.583 10.964h14.112c-.311-1.943-.466-5.521-.466-10.73v-15.979c0-6.765-1.516-12.519-4.549-17.262-3.42-5.443-8.2-8.165-14.34-8.165z"/&gt;&lt;path d="m169.15 78.729c-6.143 0-10.691-2.722-13.646-8.165-2.333-4.432-3.499-10.225-3.499-17.378v-15.979c0-5.288-.155-8.864-.466-10.73h13.996c-.233 1.71-.389 5.365-.467 10.964l-.116 15.746c0 4.432.505 7.62 1.516 9.563 1.167 2.411 3.305 3.616 6.415 3.616 2.177 0 4.626-1.283 7.348-3.849v-28.693c0-1.322-.078-2.838-.233-4.549-.156-1.711-.233-2.644-.233-2.799h13.529c-.155 1.322-.233 3.771-.233 7.348v35.69c0 4.587.078 7.503.233 8.747h-12.72v-4.198c-3.58 3.11-7.39 4.666-11.43 4.666z"/&gt;&lt;path d="m221.64 78.611c-4.198 0-7.697-1.516-10.497-4.548v4.198h-12.363c.233-1.321.351-3.771.351-7.348v-61.7c0-4.588-.117-7.503-.351-8.748h13.297c-.156 1.399-.233 4.315-.233 8.748v20.294c3.576-2.255 7.076-3.383 10.497-3.383 6.143 0 10.964 2.722 14.463 8.165 2.954 4.743 4.432 10.497 4.432 17.262 0 6.92-1.555 12.946-4.665 18.078-3.74 5.989-8.72 8.982-14.94 8.982zm-1.75-40.238c-2.566 0-5.249 1.283-8.048 3.849v20.178c2.488 2.41 4.938 3.616 7.348 3.616 3.032 0 5.326-1.672 6.882-5.016 1.244-2.644 1.866-5.793 1.866-9.447 0-8.787-2.68-13.18-8.05-13.18z"/&gt;&lt;/g&gt;&lt;g id="social" class="futura-heavy"&gt;&lt;path d="m58.661 89.441c-.74-1.004-1.691-1.639-2.986-1.639-1.242 0-2.431.952-2.431 2.247 0 3.356 7.902 1.955 7.902 8.642 0 3.991-2.484 6.818-6.554 6.818-2.749 0-4.757-1.585-6.131-3.885l2.511-2.458c.528 1.533 1.929 2.907 3.594 2.907 1.585 0 2.563-1.348 2.563-2.881 0-2.062-1.903-2.643-3.462-3.25-2.564-1.058-4.44-2.353-4.44-5.444 0-3.304 2.458-5.973 5.814-5.973 1.771 0 4.229.872 5.444 2.22l-1.824 2.699z"/&gt;&lt;path d="m72.083 105.51c-6.079 0-9.858-4.651-9.858-10.519 0-5.92 3.912-10.465 9.858-10.465s9.858 4.545 9.858 10.465c0 5.869-3.779 10.519-9.858 10.519zm0-17.152c-3.673 0-5.841 3.25-5.841 6.475 0 3.065 1.533 6.845 5.841 6.845s5.84-3.779 5.84-6.845c.001-3.227-2.166-6.477-5.84-6.477z"/&gt;&lt;path d="m97.16 90.34c-1.083-1.321-2.722-2.114-4.387-2.114-3.727 0-5.867 3.436-5.867 6.872 0 3.356 2.22 6.712 5.841 6.712 1.665 0 3.33-.872 4.414-2.113v4.624c-1.454.688-2.907 1.189-4.52 1.189-5.603 0-9.752-4.836-9.752-10.333 0-5.656 3.991-10.65 9.832-10.65 1.559 0 3.092.423 4.44 1.162v4.651z"/&gt;&lt;path d="m103.61 104.98h-3.885v-19.925h3.885v19.925z"/&gt;&lt;path d="m110.5 100.78l-1.639 4.202h-4.096l7.77-20.455h3.013l7.559 20.455h-4.149l-1.533-4.202h-6.92zm3.36-10.414h-.053l-2.194 7.242h4.731l-2.49-7.242z"/&gt;&lt;path d="m128.18 101.6h5.497v3.383h-9.382v-19.925h3.885v16.545z"/&gt;&lt;/g&gt;&lt;g id="coding" class="futura-heavy"&gt;&lt;path d="m155.87 90.34c-1.083-1.321-2.722-2.114-4.387-2.114-3.727 0-5.867 3.436-5.867 6.872 0 3.356 2.22 6.712 5.841 6.712 1.665 0 3.33-.872 4.414-2.113v4.624c-1.454.688-2.907 1.189-4.52 1.189-5.603 0-9.752-4.836-9.752-10.333 0-5.656 3.991-10.65 9.832-10.65 1.559 0 3.092.423 4.44 1.162v4.651z"/&gt;&lt;path d="m167.34 105.51c-6.079 0-9.858-4.651-9.858-10.519 0-5.92 3.912-10.465 9.858-10.465s9.857 4.545 9.857 10.465c0 5.869-3.78 10.519-9.86 10.519zm0-17.152c-3.674 0-5.841 3.25-5.841 6.475 0 3.065 1.533 6.845 5.841 6.845s5.841-3.779 5.841-6.845c0-3.227-2.17-6.477-5.84-6.477z"/&gt;&lt;path d="m179.1 85.055h5.551c5.761 0 9.619 4.308 9.619 9.989 0 5.604-3.964 9.938-9.646 9.938h-5.523v-19.925zm3.88 16.545h.634c4.783 0 6.634-2.643 6.634-6.581 0-4.334-2.22-6.58-6.634-6.58h-.634v13.161z"/&gt;&lt;path d="m200.05 104.98h-3.886v-19.925h3.886v19.925z"/&gt;&lt;path d="m202.88 84.526h2.802l10.492 13.928h.053v-13.399h3.885v20.323h-2.801l-10.48-13.93h-.053v13.531h-3.886v-20.454z"/&gt;&lt;path d="m240.53 94.384v.502c0 5.629-2.881 10.624-9.064 10.624-5.814 0-9.488-4.915-9.488-10.412 0-5.683 3.779-10.571 9.726-10.571 3.383 0 6.343 1.718 7.876 4.757l-3.436 1.85c-.793-1.797-2.484-3.171-4.546-3.171-3.753 0-5.603 3.832-5.603 7.136 0 3.303 1.876 6.977 5.629 6.977 2.432 0 4.467-2.114 4.546-4.52h-4.229v-3.171h8.58z"/&gt;&lt;/g&gt;&lt;/svg&gt;&lt;/div&gt;&lt;script src="https://gist.github.com/raw/1007786/bd7ec322d9215edf08d5792149551a975f5b44bf/draw-svg.js"&gt;&lt;/script&gt;&lt;br /&gt;
&lt;br /&gt;
If all you see is a button and the description of each step, that just means your browser doesn't natively handle inline SVG, which of course is a bit of a shame. Another reason I was curious to try this is for seeing how inline SVG:s fare in feed readers. (Google Reader seems to fail.)&lt;br /&gt;
&lt;br /&gt;
Nicer source code for the images than in the page (Blogger insisted on filling all the whitespace with html junk) in these gists: &lt;a href="https://gist.github.com/raw/1007812/a97732f233379d2b39e1216adc61bd9ee553b0bf/github-logo.svg"&gt;github-logo.svg&lt;/a&gt;, &lt;a href="https://gist.github.com/raw/1007813/1f883261b243111b00d932d6033a8b538b1ecae7/octocat.svg"&gt;octocat.svg&lt;/a&gt;. gist.github.com currently doesn't serve .svg files as &lt;code&gt;image/svg&lt;/code&gt;, so you'll have to save them locally first to see them rendered.&lt;br /&gt;
&lt;br /&gt;
Source code for the step-by-step drawing is &lt;a href="https://gist.github.com/1007786"&gt;in this gist&lt;/a&gt;; MIT licensed, if you want to fork away, adopt, adapt or whatnot. Have fun! I did. :-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15626356-2482992080593249833?l=ecmanaut.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/V_FNyGo220A24N5mDrNmhUK5AM8/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/V_FNyGo220A24N5mDrNmhUK5AM8/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/V_FNyGo220A24N5mDrNmhUK5AM8/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/V_FNyGo220A24N5mDrNmhUK5AM8/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/xxBcs/~4/uO1yX3r87N8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://ecmanaut.blogspot.com/feeds/2482992080593249833/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=15626356&amp;postID=2482992080593249833" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/15626356/posts/default/2482992080593249833?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/15626356/posts/default/2482992080593249833?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/xxBcs/~3/uO1yX3r87N8/draw-your-own-github-svgs-step-by-step.html" title="Draw your own Github SVGs, step by step" /><author><name>Johan Sundström</name><uri>http://www.blogger.com/profile/04076097346172610543</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://ecmanaut.blogspot.com/2011/06/draw-your-own-github-svgs-step-by-step.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkMBSX09fyp7ImA9WhZVF0U.&quot;"><id>tag:blogger.com,1999:blog-15626356.post-7764322370965799632</id><published>2011-05-29T23:18:00.000-07:00</published><updated>2011-05-30T12:40:58.367-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-05-30T12:40:58.367-07:00</app:edited><title>Add-on hosting: Mozilla vs Google vs Opera</title><content type="html">I habitually develop browser user scripts to stream-line things for myself (and others) on the web – and a half random scattering of them tends to end up proper add-ons, when I think the benefit of them being easy to find, install and reuse by others merits the added work for myself of packaging them and submitting them to an add-ons gallery.&lt;br /&gt;
&lt;br /&gt;
This happens rarely enough for me to forget some details of the process (yet often enough to be annoying), hence this post to document salient parts of it, applaud parts of where hosts worked things out really well, and note where there are holes to patch up. (I don't cover Safari since I have not made any Safari add-ons.)&lt;br /&gt;
&lt;br /&gt;
&lt;hr&gt;&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-oCAXDQdo0CY/TeMUNTWtQII/AAAAAAAAAOQ/lprF0rJcldY/s1600/public-greasemonkey-panel-ff.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="176" width="320" alt="Firefox add-on page" src="http://4.bp.blogspot.com/-oCAXDQdo0CY/TeMUNTWtQII/AAAAAAAAAOQ/lprF0rJcldY/s320/public-greasemonkey-panel-ff.png" /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
(&lt;a href="https://addons.mozilla.org/en-US/firefox/addon/greasemonkey/"&gt;screenshot taken here&lt;/a&gt;)&lt;/div&gt;&lt;br /&gt;
&lt;h4&gt;Firefox add-ons: &lt;a href="http://addons.mozilla.org/"&gt;addons.mozilla.org&lt;/a&gt;, a k a AMO&lt;/h4&gt;&lt;br /&gt;
&lt;b&gt;&lt;i&gt;Your&lt;/i&gt; add-ons are listed here:&lt;/b&gt; &lt;a href="https://addons.mozilla.org/en-US/developers/addons"&gt;addons.mozilla.org/en-US/developers/addons&lt;/a&gt;&lt;br /&gt;
&lt;b&gt;Add-on URL:&lt;/b&gt; addons.mozilla.org/en-US/firefox/addon/&lt;i&gt;your-configurable-addon-slug&lt;/i&gt;&lt;br /&gt;
&lt;b&gt;Public data:&lt;/b&gt; current version, last update time, compatible browser versions, website and, optionally: &lt;b&gt;all add-on detail metrics, if the developer wants to share them&lt;/b&gt; (excellent!)&lt;br /&gt;
&lt;b&gt;Public metrics:&lt;/b&gt; total download count, average rating, number of ratings&lt;br /&gt;
&lt;b&gt;Detail metrics:&lt;/b&gt; TONS: mainly installation rate and active installed user base over time, broken down by all sorts of interesting properties or in aggregate, graphed and downloadable in csv format. Notable omission: add-on page traffic stats. Public example: &lt;a href="https://addons.mozilla.org/en-US/statistics/addon/748"&gt;Greasemonkey stats&lt;/a&gt;&lt;br /&gt;
&lt;b&gt;Developer page linked from the public add-on page when you're logged in:&lt;/b&gt; NO&lt;br /&gt;
&lt;b&gt;Release process:&lt;/b&gt; Manual review process that can take a really long time, as AMO often is under-staffed, and hasn't successfully incentivized developer participation in the process to an extent as to make it not so.&lt;br /&gt;
&lt;br /&gt;
Summary: great stats and an ambition to make information public and transparent.&lt;br /&gt;
&lt;br /&gt;
&lt;hr&gt;&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-4XNd-LPWcEA/TeMWDJ0pnZI/AAAAAAAAAOY/1lhbCJWux3U/s1600/public-github-improved-panel-cr.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="154" width="320" alt="Chrome add-on page" src="http://3.bp.blogspot.com/-4XNd-LPWcEA/TeMWDJ0pnZI/AAAAAAAAAOY/1lhbCJWux3U/s320/public-github-improved-panel-cr.png" /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
(&lt;a href="https://chrome.google.com/webstore/detail/nkbnmpfpclijlllipmfbkkednidgngaa"&gt;screenshot taken here&lt;/a&gt;)&lt;/div&gt;&lt;br /&gt;
&lt;h4&gt;Chrome add-ons: &lt;a href="https://chrome.google.com/webstore/"&gt;chrome.google.com/webstore&lt;/a&gt;, or the Chrome Web Store&lt;br /&gt;
Previously lived at &lt;a href="https://chrome.google.com/extensions"&gt;chrome.google.com/extensions&lt;/a&gt;, the Chrome extensions gallery&lt;/h4&gt;&lt;br /&gt;
&lt;b&gt;&lt;i&gt;Your&lt;/i&gt; add-ons are listed here:&lt;/b&gt; &lt;a href="https://chrome.google.com/webstore/developer/dashboard"&gt;chrome.google.com/webstore/developer/dashboard&lt;/a&gt;&lt;br /&gt;
&lt;b&gt;Add-on URL:&lt;/b&gt; chrome.google.com/webstore/detail/&lt;i&gt;your-addon-signature&lt;/i&gt;[/optional-add-on-slug]&lt;br /&gt;
&lt;b&gt;Public data:&lt;/b&gt; current version, last update time, &lt;b&gt;if installed: a checkmark and the sign "Installed", instead of the "Install" button&lt;/b&gt; (excellent!)&lt;br /&gt;
&lt;b&gt;Public metrics:&lt;/b&gt; total download count, average rating, number of ratings&lt;br /&gt;
&lt;b&gt;Detail metrics:&lt;/b&gt; If you jump through the relatively tiny hoop of creating and tying a new Google Analytics account to your add-on, you get detailed add-on page traffic stats, over in Google Analytics. Notabe omission: all metrics about your installed user base :-/&lt;br /&gt;
&lt;b&gt;Developer page linked from the public add-on page when you're logged in:&lt;/b&gt; NO&lt;br /&gt;
&lt;b&gt;Release process:&lt;/b&gt; Automated review process, making yourself the only release blocker, in practice. This is bloody awesome!&lt;br /&gt;
&lt;br /&gt;
In summary: A really delightful release process that doesn't waste your time. The metrics part is really disappointingly missing the most interesting data; I hope that will improve with time. There are other essential missing docs too: to find out that you can self host your add-on AND publish it in the chrome web store, with the same add-on id, you need excellent Google fu, or this secret knowledge:&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;first (before your initial web store submission) build your add-on locally&lt;/li&gt;
&lt;li&gt;store the .pem file in some good location&lt;/li&gt;
&lt;li&gt;rename it &lt;tt&gt;key.pem&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;copy that .pem file into the add-on directory&lt;/li&gt;
&lt;li&gt;zip up that directory (so the top level of the zip file only has one directory)&lt;/li&gt;
&lt;li&gt;NOW (and for all later versions, IIRC) upload this zip file to the Chrome Web Store&lt;/li&gt;
&lt;li&gt;…and it will use your add-on signature, instead of that of Google's secret .pem&lt;/li&gt;
&lt;/ul&gt;&lt;br /&gt;
&lt;hr&gt;&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-SUFo9AQoNxk/TeMmY2UmRFI/AAAAAAAAAOg/E1LmXjpQlFM/s1600/pubilc-github-improved-op.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="47" width="320" alt="Opera add-on page" src="http://3.bp.blogspot.com/-SUFo9AQoNxk/TeMmY2UmRFI/AAAAAAAAAOg/E1LmXjpQlFM/s320/pubilc-github-improved-op.png" /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
(slightly de-horizontalized &lt;a href="https://addons.opera.com/addons/extensions/details/github-improved/"&gt;screenshot taken here&lt;/a&gt;)&lt;/div&gt;&lt;br /&gt;
&lt;h4&gt;Opera add-ons: &lt;a href="https://addons.opera.com/addons/extensions/"&gt;addons.opera.com/addons/extensions&lt;/a&gt;&lt;/h4&gt;&lt;br /&gt;
&lt;b&gt;&lt;i&gt;Your&lt;/i&gt; add-ons are listed here:&lt;/b&gt; &lt;a href="https://addons.opera.com/developer/"&gt;addons.opera.com/developer&lt;/a&gt; (this page is near &lt;i&gt;impossible&lt;/i&gt; to find by navigation, and was the reason I created this blog post :-)&lt;br /&gt;
&lt;b&gt;Add-on public URL:&lt;/b&gt; addons.opera.com/addons/extensions/details/&lt;i&gt;addon-slug&lt;/i&gt;[/&lt;i&gt;version&lt;/i&gt; (redirects visitors here)]&lt;br /&gt;
&lt;b&gt;Add-on developer URL:&lt;/b&gt; addons.opera.com/developer/extensions/details/&lt;i&gt;addon-slug&lt;/i&gt;/&lt;i&gt;version&lt;/i&gt; (no redirect help, but links to all other versions)]&lt;br /&gt;
&lt;b&gt;Public data:&lt;/b&gt; current version, last update time, &lt;b&gt;add-on size&lt;/b&gt; (excellent!)&lt;br /&gt;
&lt;b&gt;Public metrics:&lt;/b&gt; total download count, average rating, number of ratings&lt;br /&gt;
&lt;b&gt;Detail metrics:&lt;/b&gt; NONE. Notabe omission: all data about your installed user base, AND add-on page traffic :-(&lt;br /&gt;
&lt;b&gt;Developer page linked from the public add-on page when you're logged in:&lt;/b&gt; NO&lt;br /&gt;
&lt;b&gt;Release process:&lt;/b&gt; Manual review process, rewarding the behaviour of publishing as little data about your add-on as possible, since each bit of data is a plausible blocker. (Example: it is a bad thing to link to your development site on github, unless it is a repository that only has Opera-addon-centric stuff in it, and not, say, covers the source code used to build add-ons all browsers it caters.)&lt;br /&gt;
&lt;br /&gt;
Summary: young; still a far cry from easy to find your way around. I accidentally managed to log in via my email address (after having reset the password), which had gotten the same password as the account nickname I had published from before, but was otherwise treated as another account, with its own (empty) list of add-ons. So I first found no way to upgrade my existing add-on and just uploaded a new one. When I found the mistake, there was no way to abort the review process I had started (but I could edit it to add some reviewer notes for the probably equally confused reviewer). What probably looks like a really well integrated set of connected Opera sites to an Opera employee is a huge maze of web pages, none related to publishing your add-on, to an add-on developer.&lt;br /&gt;
&lt;br /&gt;
All of these hosting sites have developer log-in of some sort, yet fail to link the developer's admin view from the public add-on page. For Opera, this hurts really badly, as there is so much Opera noise around, which does not try to help you publish your add-on; for the others, it's a smaller nuisance (it's also entirely possible that I learned where to find the "Developer Hub" and "Developer Dashboard" links long ago enough to now find them near intuitive).&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Update:&lt;/b&gt; I just found Opera's dashboard link! Your logged-in name is the link that takes you to your dashboard of add-ons. And it only took knowing the wanted url, opening a web console and typing &lt;code&gt;[].slice.call(document.links).filter(function(a){ return a.href == "https://addons.opera.com/developer/"; })&lt;/code&gt; in it. What do you know? :-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15626356-7764322370965799632?l=ecmanaut.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/8OzV3aPQXt3Jutz2F2n_HGHTjEw/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/8OzV3aPQXt3Jutz2F2n_HGHTjEw/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/8OzV3aPQXt3Jutz2F2n_HGHTjEw/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/8OzV3aPQXt3Jutz2F2n_HGHTjEw/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/xxBcs/~4/Sa1s3IyPmHQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://ecmanaut.blogspot.com/feeds/7764322370965799632/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=15626356&amp;postID=7764322370965799632" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/15626356/posts/default/7764322370965799632?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/15626356/posts/default/7764322370965799632?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/xxBcs/~3/Sa1s3IyPmHQ/add-on-hosting-mozilla-vs-google-vs.html" title="Add-on hosting: Mozilla vs Google vs Opera" /><author><name>Johan Sundström</name><uri>http://www.blogger.com/profile/04076097346172610543</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-oCAXDQdo0CY/TeMUNTWtQII/AAAAAAAAAOQ/lprF0rJcldY/s72-c/public-greasemonkey-panel-ff.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://ecmanaut.blogspot.com/2011/05/add-on-hosting-mozilla-vs-google-vs.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUEASHkyeyp7ImA9WhZUEUU.&quot;"><id>tag:blogger.com,1999:blog-15626356.post-2391817911746825560</id><published>2011-05-28T02:47:00.000-07:00</published><updated>2011-06-04T04:40:49.793-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-06-04T04:40:49.793-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="extension" /><category scheme="http://www.blogger.com/atom/ns#" term="github" /><category scheme="http://www.blogger.com/atom/ns#" term="Chrome" /><category scheme="http://www.blogger.com/atom/ns#" term="Opera" /><title>Github Improved 1.7</title><content type="html">After a whole year in development as a user script (&lt;a href="http://ecmanaut.blogspot.com/2010/08/friendlier-github-commits-pages.html"&gt;initial mention&lt;/a&gt;, formerly known as "Github: unfold commit history"), a brief test-drive as an &lt;a href="https://addons.opera.com/addons/extensions/details/github-improved/"&gt;Opera extension&lt;/a&gt; at &lt;a href="http://ecmanaut.blogspot.com/2010/12/opera-11-extensions-add-on-con.html"&gt;the 2010 add-on con&lt;/a&gt;, I finished up the missing bits and pieces to make today's &lt;a href="https://chrome.google.com/webstore/detail/nkbnmpfpclijlllipmfbkkednidgngaa"&gt;Github Improved! chrome extension&lt;/a&gt; available in the Chrome Gallery / Web Store (1.7 now also available in the &lt;a href="https://addons.opera.com/addons/extensions/details/github-improved/"&gt;Opera extension gallery&lt;/a&gt;).&lt;br /&gt;
&lt;br /&gt;
New since last release is the little tag delta (&amp;Delta;) links that let you instantly see what happened between, say, &lt;a href="https://github.com/greasemonkey/greasemonkey/commits/0.9.5"&gt;Greasemonkey 0.9.5&lt;/a&gt; and the previous release tag (it recognizes anything where the only thing differing between tags are their numeric parts, which also means it's not going to handle fancy 1.6rc1 type tag names littered with semantic non-numeric parts):&lt;br /&gt;
&lt;br /&gt;
&lt;img src="https://lh3.googleusercontent.com/JCJFUNc-0dwcDX2VyOjMWz8shFzBQTnm_jhiM6Wew8uAIz9xb1yo5GmBqbstKaY3t_oAmtM6Pw=s400-e365-h275" width="400" height="275" style="display: block; margin: 0 auto; text-align: center;"&gt;&lt;br /&gt;
&lt;br /&gt;
And, as prior users may find even more importantly, that it doesn't hog any shifted keyboard shortcuts, which for some reason had the side effect of making arrow up pull in a pageful of diffs.&lt;br /&gt;
&lt;br /&gt;
Full documentation of all features, and a few screenshots, is available on the &lt;a href="https://chrome.google.com/webstore/detail/nkbnmpfpclijlllipmfbkkednidgngaa"&gt;Chrome Web Store page&lt;/a&gt;. I also take every opportunity to mention that it really shines best together with the &lt;a href="https://chrome.google.com/webstore/detail/aeolcjbaammbkgaiagooljfdepnjmkfd"&gt;AutoPatchWork&lt;/a&gt; extension, or something equivalent which unfolds the commit history pagination as you scroll off page. Enjoy!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15626356-2391817911746825560?l=ecmanaut.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/QW-t5bFFQ5qLIgkzXx4OeZQI3DU/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/QW-t5bFFQ5qLIgkzXx4OeZQI3DU/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/QW-t5bFFQ5qLIgkzXx4OeZQI3DU/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/QW-t5bFFQ5qLIgkzXx4OeZQI3DU/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/xxBcs/~4/hQMEDpHMQsY" height="1" width="1"/&gt;</content><link rel="related" href="https://chrome.google.com/webstore/detail/nkbnmpfpclijlllipmfbkkednidgngaa" title="Github Improved 1.7" /><link rel="replies" type="application/atom+xml" href="http://ecmanaut.blogspot.com/feeds/2391817911746825560/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=15626356&amp;postID=2391817911746825560" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/15626356/posts/default/2391817911746825560?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/15626356/posts/default/2391817911746825560?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/xxBcs/~3/hQMEDpHMQsY/github-improved-17.html" title="Github Improved 1.7" /><author><name>Johan Sundström</name><uri>http://www.blogger.com/profile/04076097346172610543</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://ecmanaut.blogspot.com/2011/05/github-improved-17.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0UFQnY9fip7ImA9WhZVEE4.&quot;"><id>tag:blogger.com,1999:blog-15626356.post-2168912183907757919</id><published>2011-05-21T20:33:00.000-07:00</published><updated>2011-05-21T20:33:33.866-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-05-21T20:33:33.866-07:00</app:edited><title>Google Closure Library bookmarklet</title><content type="html">Any self-respecting javascript library should have a debug bookmarklet that lets you load it into a page, so you can tinker with it (the library, or the page, for that matter) without any messy overhead like downloading the most recent version, building it with the specific flags and sub-components you want, saving the current page, adding library setup code to it, and reloading that page before you can do squat. I found &lt;a href="http://code.google.com/closure/library/"&gt;Google Closure Library&lt;/a&gt; a bit lacking in that regard, so here's my take on it:&lt;br /&gt;
&lt;br /&gt;
&lt;script src="https://gist.github.com/985137.js?file=google-closure-library.js"&gt;&lt;/script&gt;&lt;noscript&gt;&lt;a href="https://gist.github.com/985137"&gt;gist.github.com/985137&lt;/a&gt;&lt;/noscript&gt;&lt;br /&gt;
It has two modes of operation; if all you want to do is load the &lt;code&gt;goog&lt;/code&gt; object into the current page (or overwrite the one you already have with one that has a different set of &lt;code&gt;goog.require()&lt;/code&gt;s), just customize which those requires should be, and you're set; it creates an iframe, in which it loads the library (&lt;code&gt;goog.require&lt;/code&gt; only works during page parsing time, as it uses &lt;code&gt;document.write()&lt;/code&gt; to load its dependencies), and then overwrites the top window's &lt;code&gt;goog&lt;/code&gt; identifier.&lt;br /&gt;
&lt;br /&gt;
The second mode is good for writing your own bookmarklets making use of some Closure Library tools; provide your own function, and it will instead get called with the freshly loaded &lt;code&gt;goog&lt;/code&gt; object, once it's ready. At the moment, I have only played with this in Google Chrome, but feel free to fork away on github, if you tinker in additional improvements for other browsers.&lt;br /&gt;
&lt;br /&gt;
Finally, here's a bookmarklet version to save or play with, which will prompt you for just which closure dependencies you want to load: &lt;a href="javascript:(function(f){var q=prompt('Please name your goog.require:s','goog.ui.TableSorter, goog.net.XhrIo'),r=q&amp;amp;&amp;amp;q.split(/,\s*/),i=r.length&amp;amp;&amp;amp;document.body.appendChild(document.createElement('iframe'));if(i){i.src='about:blank';i.style.display='none';i.contentWindow.f=f;i.contentDocument.write('&amp;lt;script src=http://closure-library.googlecode.com/svn/trunk/closure/goog/base.js&amp;gt;&amp;lt;/script&amp;gt;&amp;lt;script src=http://closure-library.googlecode.com/svn/trunk/closure/goog/deps.js&amp;gt;&amp;lt;/script&amp;gt;&amp;lt;script&amp;gt;'+JSON.stringify(r)+'.forEach(goog.require);&amp;lt;/script&amp;gt;&amp;lt;script&amp;gt;'+(f?'f.call(parent,goog)':'parent.goog=goog')+';&amp;lt;/script&amp;gt;');}})();"&gt;closure&lt;/a&gt; – drag it to your bookmarks toolbar or equivalent if you want to keep it around. Enjoy!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15626356-2168912183907757919?l=ecmanaut.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/vTlIfANJBTwQBkiIo2P8XE26Q5M/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/vTlIfANJBTwQBkiIo2P8XE26Q5M/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/vTlIfANJBTwQBkiIo2P8XE26Q5M/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/vTlIfANJBTwQBkiIo2P8XE26Q5M/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/xxBcs/~4/Tgbhm5mHg8M" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://ecmanaut.blogspot.com/feeds/2168912183907757919/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=15626356&amp;postID=2168912183907757919" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/15626356/posts/default/2168912183907757919?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/15626356/posts/default/2168912183907757919?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/xxBcs/~3/Tgbhm5mHg8M/google-closure-library-bookmarklet.html" title="Google Closure Library bookmarklet" /><author><name>Johan Sundström</name><uri>http://www.blogger.com/profile/04076097346172610543</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://ecmanaut.blogspot.com/2011/05/google-closure-library-bookmarklet.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEQMQXo7eSp7ImA9WhZVEE0.&quot;"><id>tag:blogger.com,1999:blog-15626356.post-42494361135222072</id><published>2011-05-21T12:15:00.000-07:00</published><updated>2011-05-21T12:33:00.401-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-05-21T12:33:00.401-07:00</app:edited><title>A "No News is Good News" Tsunami Feed</title><content type="html">I have subscribed to the &lt;a href="http://wcatwc.arh.noaa.gov/"&gt;NOAA/NWS/West Coast and Alaska Tsunami Warning Center&lt;/a&gt;'s &lt;a href="http://wcatwc.arh.noaa.gov/rss/tsunamirss.xml"&gt;feed of ahead-of-time tsunami warnings&lt;/a&gt; for the U.S. West Coast, Alaska, and British Columbia coastal regions (&lt;a href="http://wcatwc.arh.noaa.gov/2011/05/21/lljefm/01/messagelljefm-01.htm"&gt;example information statement&lt;/a&gt;) for some time. Most, like this one, are "wolf-cry" statements stemming from some seismic activity somewhere that &lt;i&gt;won't&lt;/i&gt; generate any tsunami, marked with the all-important body phrase "The magnitude is such that a tsunami &lt;strong&gt;WILL NOT&lt;/strong&gt; be generated" - meaning I don't really care about them.&lt;br /&gt;
&lt;br /&gt;
Today I made a &lt;a href="http://pipes.yahoo.com/pipes/pipe.info?_id=25e365289cdbcf9c639d6b05854fc5d6"&gt;Yahoo pipe&lt;/a&gt;, filtering away those from the feed. Here is the resulting feed, containing only &lt;a href="http://pipes.yahoo.com/pipes/pipe.run?_id=25e365289cdbcf9c639d6b05854fc5d6&amp;_render=rss"&gt;positive tsunami warning statements&lt;/a&gt;. Behind the scenes, it's created by the simple YQL statement &lt;code&gt;select * from rss where url="http://wcatwc.arh.noaa.gov/rss/tsunamirss.xml" and description  like "%tsunami &amp;lt;strong&amp;gt;WILL NOT&amp;lt;/strong&amp;gt; be%"&lt;/code&gt; (there's some newline or similar after "be" in the original feed, and it doesn't seem like YQL does any whitespace normalization, but this matches well enough to filter the stuff).&lt;br /&gt;
&lt;br /&gt;
The resulting feed is my enrapturing contribution to today's supposed end of the world. You may note that the feed is currently (and hopefully still, by the time you read this :-) empty - which is, of course, good news. Enjoy!&lt;br /&gt;
&lt;br /&gt;
On a related hacker's note, it would be really handy to extend Google Reader with a "filter this feed" feature that created these more on the fly, without mucking about for an hour in the Yahoo Pipes interface, and then changed the old subscription to the new feed.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15626356-42494361135222072?l=ecmanaut.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/Rc6X9eNUKFNjWWeFksoxZOoy2F0/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Rc6X9eNUKFNjWWeFksoxZOoy2F0/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/Rc6X9eNUKFNjWWeFksoxZOoy2F0/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Rc6X9eNUKFNjWWeFksoxZOoy2F0/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/xxBcs/~4/PcVyyaL0bk0" height="1" width="1"/&gt;</content><link rel="related" href="http://pipes.yahoo.com/pipes/pipe.run?_id=25e365289cdbcf9c639d6b05854fc5d6&amp;_render=rss" title="A &quot;No News is Good News&quot; Tsunami Feed" /><link rel="replies" type="application/atom+xml" href="http://ecmanaut.blogspot.com/feeds/42494361135222072/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=15626356&amp;postID=42494361135222072" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/15626356/posts/default/42494361135222072?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/15626356/posts/default/42494361135222072?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/xxBcs/~3/PcVyyaL0bk0/no-news-is-good-news-tsunami-feed.html" title="A &quot;No News is Good News&quot; Tsunami Feed" /><author><name>Johan Sundström</name><uri>http://www.blogger.com/profile/04076097346172610543</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://ecmanaut.blogspot.com/2011/05/no-news-is-good-news-tsunami-feed.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkQHQHgycCp7ImA9WhZWFUs.&quot;"><id>tag:blogger.com,1999:blog-15626356.post-7074935802337298378</id><published>2011-05-16T00:59:00.000-07:00</published><updated>2011-05-16T08:38:51.698-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-05-16T08:38:51.698-07:00</app:edited><title>Chrome + NaCl + libmodplug + ... = tracker modules on the web</title><content type="html">Some notes I took while looking into how to build a &lt;tt&gt;libmikmod_x86_32.nexe&lt;/tt&gt; and &lt;tt&gt;libmikmod_x86_64.nexe&lt;/tt&gt; to get Chrome tracker module playing support from javascript (the work seems to be done already in naclports) via NativeClient, for all the MOD, S3M, XM, IT, 669, AMF, AMS, DBM, DMF, DSM, FAR, MDL, MED, MTM, OKT, PTM, STM, ULT, UMX, MT2 and PSM formats:&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;In a Chrome 11 profile, go to &lt;tt&gt;about:flags&lt;/tt&gt;, and click &lt;b&gt;Enable&lt;/b&gt; under "Native Client", and then the "Relaunch Now" button at the bottom (alternatively: start the session with the &lt;tt&gt;--enable-nacl&lt;/tt&gt; command-line flag)&lt;/li&gt;
&lt;li&gt;&lt;a href="http://code.google.com/chrome/nativeclient/docs/download.html"&gt;Download the NaCl SDK&lt;/a&gt; (for Chrome 11, in my case; eventually the ABI will supposedly freeze and cover a wider range of versions)&lt;/li&gt;
&lt;li&gt;&lt;a href="http://dev.chromium.org/developers/how-tos/install-depot-tools"&gt;Download &lt;tt&gt;depot_tools&lt;/tt&gt;&lt;/a&gt;, extract it and &lt;tt&gt;export NACL_SDK_ROOT=$PWD&lt;/tt&gt; in that directory (&lt;a href="http://code.google.com/chrome/nativeclient/docs/technical_overview.html"&gt;technical overview here&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="http://code.google.com/p/naclports/wiki/HowTo_Checkout?tm=4"&gt;Check out &lt;tt&gt;naclports&lt;/tt&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Probably optional: comment out all the &lt;tt&gt;RunInstallScript&lt;/tt&gt; lines in &lt;tt&gt;naclports/src/packages/nacl-install-all-bitsize.sh&lt;/tt&gt; except the one you're interested in (in my case: &lt;tt&gt;RunInstallScript libmodplug-0.8.7 nacl-libmodplug-0.8.7.sh&lt;/tt&gt;)&lt;/li&gt;
&lt;li&gt;Run &lt;tt&gt;nacl-install-all-bitsize.sh 64&lt;/tt&gt; (or 32 for a 32-bit build), which, in my case, built &lt;tt&gt;$NACL_SDK_ROOT/toolchain/mac_x86/nacl64/usr/lib/libmodplug.a&lt;/tt&gt;&lt;!--

If you ever happen to want to link against installed libraries
in a given directory, LIBDIR, you must either use libtool, and
specify the full pathname of the library, or use the `-LLIBDIR'
flag during linking and do at least one of the following:
   - add LIBDIR to the `LD_RUN_PATH' environment variable
     during linking
   - use the `-Wl,--rpath -Wl,LIBDIR' linker flag

See any operating system documentation about shared libraries for
more information, such as the ld(1) and ld.so(8) manual pages.

--&gt;&lt;/li&gt;
&lt;li&gt;About here my research petered out, as I found &lt;a href="http://www.enoie.net/nacltest/xm_player.html"&gt;this smaller hack for XM-only playback&lt;/a&gt; by some forthcoming Japanese fellow (&lt;a href="http://git.sourceforge.jp/view?p=nacltest/xmplayer.git"&gt;git repository here&lt;/a&gt;; &lt;a href="http://translate.google.com/translate?js=n&amp;prev=_t&amp;hl=en&amp;ie=UTF-8&amp;layout=2&amp;eotf=1&amp;sl=ja&amp;tl=en&amp;u=http%3A%2F%2Fgit.sourceforge.jp%2Fview%3Fp%3Dnacltest%2Fxmplayer.git"&gt;English translation of same page&lt;/a&gt; c/o Google Translate), which has basic functionality&lt;/li&gt;
&lt;li&gt;If you got curious about my original venue and proceeded further, I'd love to hear about it, especially if you managed to build the final nexe:s; do post a comment!&lt;/li&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15626356-7074935802337298378?l=ecmanaut.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/ojjInMcOfpdBGDpgyEv8gu-CCC4/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/ojjInMcOfpdBGDpgyEv8gu-CCC4/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/ojjInMcOfpdBGDpgyEv8gu-CCC4/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/ojjInMcOfpdBGDpgyEv8gu-CCC4/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/xxBcs/~4/acqjrcizrgQ" height="1" width="1"/&gt;</content><link rel="related" href="http://www.enoie.net/nacltest/xm_player.html" title="Chrome + NaCl + libmodplug + ... = tracker modules on the web" /><link rel="replies" type="application/atom+xml" href="http://ecmanaut.blogspot.com/feeds/7074935802337298378/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=15626356&amp;postID=7074935802337298378" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/15626356/posts/default/7074935802337298378?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/15626356/posts/default/7074935802337298378?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/xxBcs/~3/acqjrcizrgQ/chrome-nacl-libmodplug-tracker-modules.html" title="Chrome + NaCl + libmodplug + ... = tracker modules on the web" /><author><name>Johan Sundström</name><uri>http://www.blogger.com/profile/04076097346172610543</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://ecmanaut.blogspot.com/2011/05/chrome-nacl-libmodplug-tracker-modules.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkUAR387fyp7ImA9WhZXFU0.&quot;"><id>tag:blogger.com,1999:blog-15626356.post-1066629977208526497</id><published>2011-05-04T02:03:00.000-07:00</published><updated>2011-05-04T02:10:46.107-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-05-04T02:10:46.107-07:00</app:edited><title>Github tag and branch labels</title><content type="html">I just made a little update to my &lt;a href="https://github.com/johan/github-improved/raw/master/unfold_commit_history.user.js"&gt;github improved!&lt;/a&gt; user script; now it shows you branch and tag labels in the commits view, like this:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-V9t9csi4e_s/TcEPv6usolI/AAAAAAAAAM8/cVz7nPEyjO8/s1600/Screen%2Bshot%2B2011-05-04%2Bat%2B00.14.20.png" imageanchor="1" style="clear: both; margin:0 auto 1em;"&gt;&lt;img border="0" height="162" width="200" src="http://3.bp.blogspot.com/-V9t9csi4e_s/TcEPv6usolI/AAAAAAAAAM8/cVz7nPEyjO8/s200/Screen%2Bshot%2B2011-05-04%2Bat%2B00.14.20.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
There's been some more mystery meat features slipping in there too somewhat unannounced; if you click a committer icon a little filter panel opens on top that lets you see how many commits in the view were by whom, and if you click one of those, hide those commits. I got the idea when I was playing with &lt;a href="https://chrome.google.com/extensions/detail/aeolcjbaammbkgaiagooljfdepnjmkfd"&gt;Autopatchwork&lt;/a&gt; at some point, unpaginating a whole repository's worth of commits and wanted to slice and dice the view a bit, get aggregate stats and the like. This is what Greasemonkey's early history (from &lt;a href="https://github.com/greasemonkey/greasemonkey/commits/0.8"&gt;0.8&lt;/a&gt; and back) looks like, in terms of authors (not committers) involved, for example:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-eEHfX71W8AU/TcEXnRkz5PI/AAAAAAAAANE/_VBwIEHlJ1U/s1600/gm-0.8.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="86" width="200" src="http://4.bp.blogspot.com/-eEHfX71W8AU/TcEXnRkz5PI/AAAAAAAAANE/_VBwIEHlJ1U/s200/gm-0.8.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
Autopatchwork could use some more coverage on the English-speaking web, by the way, because of its neat way of aggregating user data from contributors. Instead of a dedicated backend server someone maintains for the script to work, it's using a wiki-like JSON database for public domain content: &lt;a href="service"&gt;Wedata.net&lt;/a&gt;; define your json schema and let anyone that wants to fill in, edit and co-maintain the data (here: unpagination url regexps and node xpaths). The editing process looks a bit &lt;a href="http://userscripts.org/topics/69730"&gt;like this&lt;/a&gt;. I am especially glad to have found it, as I've been wanting a service like that for a long time but not really wanted to host it, and having a public cloud sync point for mini-applications like this to update their localStorage copies of the data from is a neat trick.&lt;br /&gt;
&lt;br /&gt;
Anyway, happy githubbing! As with so many little features before it, I already can't fathom going back to a github without this feature (and I've only been using it since yesternight). It helps a lot seeing what went into which release at a glance, without doing all sorts of manual work. It would be nice for it to &lt;a href="https://github.com/johan/github-improved/issues/1"&gt;mark branch-off points&lt;/a&gt; too, but it would require some kind of merge-base type api end-point, for digging up where a branch's closest common ancestor is to all other branches. Maybe time for devising a neat response format and crafting a little api feature request.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15626356-1066629977208526497?l=ecmanaut.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/uT6hgi1IGpvm2lP9SJv_piQLJ8g/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/uT6hgi1IGpvm2lP9SJv_piQLJ8g/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/uT6hgi1IGpvm2lP9SJv_piQLJ8g/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/uT6hgi1IGpvm2lP9SJv_piQLJ8g/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/xxBcs/~4/8oB99c5Xe8Y" height="1" width="1"/&gt;</content><link rel="related" href="https://github.com/johan/github-improved/raw/master/unfold_commit_history.user.js" title="Github tag and branch labels" /><link rel="replies" type="application/atom+xml" href="http://ecmanaut.blogspot.com/feeds/1066629977208526497/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=15626356&amp;postID=1066629977208526497" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/15626356/posts/default/1066629977208526497?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/15626356/posts/default/1066629977208526497?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/xxBcs/~3/8oB99c5Xe8Y/github-tag-and-branch-labels.html" title="Github tag and branch labels" /><author><name>Johan Sundström</name><uri>http://www.blogger.com/profile/04076097346172610543</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/-V9t9csi4e_s/TcEPv6usolI/AAAAAAAAAM8/cVz7nPEyjO8/s72-c/Screen%2Bshot%2B2011-05-04%2Bat%2B00.14.20.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://ecmanaut.blogspot.com/2011/05/github-tag-and-branch-labels.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DU8DQ30zfip7ImA9WhZSGU8.&quot;"><id>tag:blogger.com,1999:blog-15626356.post-3994444714320320130</id><published>2011-04-03T02:22:00.000-07:00</published><updated>2011-04-04T07:37:52.386-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-04-04T07:37:52.386-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="ruby" /><category scheme="http://www.blogger.com/atom/ns#" term="tools" /><title>gravatar.rb</title><content type="html">I made myself a little command-line tool &lt;a href="https://gist.github.com/raw/900312/c2ae65d0b3362e42cf3524084fc740d8027b3ef9/gravatar.rb"&gt;gravatar.rb&lt;/a&gt; today, which eats email addresses and outputs "gravatar-url email@address" lines, for all email addresses that has a customized gravatar created.&lt;br /&gt;
&lt;br /&gt;
It's fun to run &lt;code&gt;git log|gravatar&lt;/code&gt; for projects you've got checked out; here's &lt;a href="https://github.com/yui/yui3"&gt;yui3&lt;/a&gt;:&lt;br /&gt;
&lt;img style="margin: 0.5em; float: left;" src="https://secure.gravatar.com/avatar/05243ae612fb4dcfb151e08489f334b0?s=80" width="80" height="80" title="davglass / gmail.com"&gt;&lt;img style="margin: 0.5em; float: left;" src="https://secure.gravatar.com/avatar/683e9380d7cc0724a35dadfb4eeb142b?s=80" width="80" height="80" title="ryan / wonko.com"&gt;&lt;img style="margin: 0.5em; float: left;" src="https://secure.gravatar.com/avatar/4479397d42c17503323ae88bf8932e42?s=80" width="80" height="80" title="adamoore / yahoo-inc.com"&gt;&lt;img style="margin: 0.5em; float: left;" src="https://secure.gravatar.com/avatar/fc2ccaa63b7dd76df705d48b5468a45e?s=80" width="80" height="80" title="lsmith / yahoo-inc.com"&gt;&lt;img style="margin: 0.5em; float: left;" src="https://secure.gravatar.com/avatar/f3f746d4b8201c3692001cb8922fff98?s=80" width="80" height="80" title="matt.sweeney / yahoo.com"&gt;&lt;img style="margin: 0.5em; float: left;" src="https://secure.gravatar.com/avatar/45926e3669f5a09802a52e86529d5514?s=80" width="80" height="80" title="allenrabinovich / yahoo.com"&gt;&lt;img style="margin: 0.5em; float: left;" src="https://secure.gravatar.com/avatar/42327de520e674a6d1686845b30778d0?s=80" width="80" height="80" title="eduardo.lundgren / liferay.com"&gt;&lt;img style="margin: 0.5em; float: left;" src="https://secure.gravatar.com/avatar/e16471e70e174182f5db53cea5c572c6?s=80" width="80" height="80" title="pcavit / gmail.com"&gt;&lt;img style="margin: 0.5em; float: left;" src="https://secure.gravatar.com/avatar/c5e59f67101f60459b52161284605b9a?s=80" width="80" height="80" title="foxxtrot / foxxtrot.net"&gt;&lt;img style="margin: 0.5em; float: left;" src="https://secure.gravatar.com/avatar/27690fd3101effe494907ee7f30bbf81?s=80" width="80" height="80" title="eduardolundgren / gmail.com"&gt;&lt;img style="margin: 0.5em; float: left;" src="https://secure.gravatar.com/avatar/05a8346601d9cdd6a8b62a91f29cd771?s=80" width="80" height="80" title="me / reidburke.com"&gt;&lt;img style="margin: 0.5em; float: left;" src="https://secure.gravatar.com/avatar/af34a0de54b2b7a34cc6d7196ef12fc0?s=80" width="80" height="80" title="build / yuilibrary.com"&gt;&lt;img style="margin: 0.5em; float: left;" src="https://secure.gravatar.com/avatar/6960eab88e6e00020d2751e48019cd59?s=80" width="80" height="80" title="gmoothart / gmail.com"&gt;&lt;img style="margin: 0.5em; float: left;" src="https://secure.gravatar.com/avatar/e2da054104d4992438195d8bb02f431c?s=80" width="80" height="80" title="curtis / curtisharvey.com"&gt;&lt;img style="margin: 0.5em; float: left;" src="https://secure.gravatar.com/avatar/f071cb9c72c08020c83a0838b192145a?s=80" width="80" height="80" title="nzakas / yahoo-inc.com"&gt;&lt;img style="margin: 0.5em; float: left;" src="https://secure.gravatar.com/avatar/f9c6936e3a1c4e3d7995817d1f9baf9e?s=80" width="80" height="80" title="ericmiraglia / yahoo.com"&gt;&lt;img style="margin: 0.5em; float: left;" src="https://secure.gravatar.com/avatar/2e54bc99b92e95d0f56da3a7e7aa0e6d?s=80" width="80" height="80" title="ryan / ryancannon.com"&gt;&lt;img style="margin: 0.5em; float: left;" src="https://secure.gravatar.com/avatar/cf33841918d90fe941f522dde5ee4ff0?s=80" width="80" height="80" title="eferraiuolo / gmail.com"&gt;&lt;img style="margin: 0.5em; float: left;" src="https://secure.gravatar.com/avatar/8fa21a16e24905fba4413501e3afb36e?s=80" width="80" height="80" title="erikvvold / gmail.com"&gt;&lt;img style="margin: 0.5em; float: left;" src="https://secure.gravatar.com/avatar/b16b03a19c743c89c573b0af67d06ed1?s=80" width="80" height="80" title="floydian / phphorizons.com"&gt;&lt;img style="margin: 0.5em; float: left;" src="https://secure.gravatar.com/avatar/df4fd1f9aa463884decd65f5ea9d9584?s=80" width="80" height="80" title="kloots / yahoo-inc.com"&gt;&lt;img style="margin: 0.5em; float: left;" src="https://secure.gravatar.com/avatar/dea8cffd5294dcd41e75fdec4c2e604e?s=80" width="80" height="80" title="i / foohack.com"&gt;&lt;img style="margin: 0.5em; float: left;" src="https://secure.gravatar.com/avatar/ea69517363a0aabf9bf09ed7ce1c5ea3?s=80" width="80" height="80" title="mattesnider / gmail.com"&gt;&lt;img style="margin: 0.5em; float: left;" src="https://secure.gravatar.com/avatar/8233cc93c34d23ce58c0096fb07375c0?s=80" width="80" height="80" title="julien.lecomte / gmail.com"&gt;&lt;img style="margin: 0.5em; float: left;" src="https://secure.gravatar.com/avatar/ea077fdc95c2959ca28b052853b4175e?s=80" width="80" height="80" title="nicholas.c.zakas / nczonline.net"&gt;&lt;img style="margin: 0.5em; float: left;" src="https://secure.gravatar.com/avatar/fef48709416e18e4ccb263b248fd88e1?s=80" width="80" height="80" title="caridy / gmail.com"&gt;&lt;img style="margin: 0.5em; float: left;" src="https://secure.gravatar.com/avatar/a96c9331b6ebb3aa112aa7b5e9dad912?s=80" width="80" height="80" title="philip / bluesmoon.info"&gt;&lt;img style="margin: 0.5em; float: left;" src="https://secure.gravatar.com/avatar/cb952c516490d47a3946a5a7889e713d?s=80" width="80" height="80" title="natek / yahoo-inc.com"&gt;&lt;img style="margin: 0.5em; float: left;" src="https://secure.gravatar.com/avatar/d5c18055c50c5b34b0163e0bf0dbf59f?s=80" width="80" height="80" title="dav.glass / yahoo.com"&gt;&lt;img style="margin: 0.5em; float: left;" src="https://secure.gravatar.com/avatar/119d3c7cbf44bd80c473688ad63591b1?s=80" width="80" height="80" title="msweeney / yahoo-inc.com"&gt;&lt;br /&gt;
&lt;br /&gt;
(People showing up more than once either have multiple email addresses registered with gravatar that they commit via or borrow someone else's picture. :-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15626356-3994444714320320130?l=ecmanaut.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/kETegz3w96c_tCYA78-MWWSh0ns/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/kETegz3w96c_tCYA78-MWWSh0ns/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/kETegz3w96c_tCYA78-MWWSh0ns/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/kETegz3w96c_tCYA78-MWWSh0ns/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/xxBcs/~4/EphO9XZbWx4" height="1" width="1"/&gt;</content><link rel="related" href="https://gist.github.com/raw/900312/c2ae65d0b3362e42cf3524084fc740d8027b3ef9/gravatar.rb" title="gravatar.rb" /><link rel="replies" type="application/atom+xml" href="http://ecmanaut.blogspot.com/feeds/3994444714320320130/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=15626356&amp;postID=3994444714320320130" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/15626356/posts/default/3994444714320320130?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/15626356/posts/default/3994444714320320130?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/xxBcs/~3/EphO9XZbWx4/gravatarrb.html" title="gravatar.rb" /><author><name>Johan Sundström</name><uri>http://www.blogger.com/profile/04076097346172610543</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://ecmanaut.blogspot.com/2011/04/gravatarrb.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DU4FQ3czcSp7ImA9WhZSGU8.&quot;"><id>tag:blogger.com,1999:blog-15626356.post-7223986581350964714</id><published>2011-03-29T00:46:00.001-07:00</published><updated>2011-04-04T07:38:32.989-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-04-04T07:38:32.989-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="mac" /><category scheme="http://www.blogger.com/atom/ns#" term="perl" /><title>Installing perl modules on Snow Leopard and Homebrew</title><content type="html">&lt;b&gt;Preamble:&lt;/b&gt; this post is a great read if you really want to have your Perl stuff in &lt;code&gt;/usr/local&lt;/code&gt;, instead of in &lt;code&gt;/Library/Perl&lt;/code&gt;, the &lt;a href="https://github.com/mxcl/homebrew/wiki/Gems%2C-Eggs-and-Perl-Modules"&gt;MacOS X way&lt;/a&gt;. Otherwise, maybe not so much! (The error I had stumbled on, which made me think cpan didn't just work was, apparently, that I at some point had used sudo cpan, and gotten permissions on things out of whack. If cpan was a little bit more helpful, chances are I would have figured it out sooner -- but let's not toss a blog post that was fun to write and still has a few useful nuggets, despite being built on an otherwise shoddy fundament. :-)&lt;br /&gt;
&lt;br /&gt;
First up: this isn't any more &lt;a href="http://mxcl.github.com/homebrew/"&gt;Homebrew&lt;/a&gt; specific than that I use the perl Apple ships with Snow Leopard (5.10 at this time of writing, for 10.6.7 - I'm on a Macbook Air myself), with all its built-in &lt;a href="http://www.manpagez.com/man/1/perlmacosx/"&gt;DTrace and MacOS integration goodness&lt;/a&gt;. Read that fine page for authoritative data; I neither am not pretend to be a perl savant.&lt;br /&gt;
&lt;br /&gt;
Using the system perl is how Homebrew prefers it – unlike some other packaging systems I shall not mention here, as a service to other fine people trying to google for "perl mac snow leopard -this -that". Should you for any reason wish to mention those in comments on this post, you may call them "Funk" and "Warts" (or "MacWarts"). I may delete your comment if you don't. (Nothing personal; just sayin'. And you might as well not, anyway, I am unlikely to be able to help you.)&lt;br /&gt;
&lt;br /&gt;
Anyway, so I want my perl modules installed in &lt;code&gt;/usr/local&lt;/code&gt;, and I want them in my &lt;code&gt;@INC&lt;/code&gt; when I run &lt;code&gt;/usr/bin/perl&lt;/code&gt; and it's a shame that the system perl only looks in any of these, right?&lt;br /&gt;
&lt;pre&gt;/Library/Perl/Updates/5.10.0/darwin-thread-multi-2level
/Library/Perl/Updates/5.10.0
/System/Library/Perl/5.10.0/darwin-thread-multi-2level
/System/Library/Perl/5.10.0
/Library/Perl/5.10.0/darwin-thread-multi-2level
/Library/Perl/5.10.0
/Network/Library/Perl/5.10.0/darwin-thread-multi-2level
/Network/Library/Perl/5.10.0
/Network/Library/Perl
/System/Library/Perl/Extras/5.10.0/darwin-thread-multi-2level
/System/Library/Perl/Extras/5.10.0&lt;/pre&gt;&lt;br /&gt;
Wrong! (I &lt;i&gt;told&lt;/i&gt; you: read &lt;a href="http://www.manpagez.com/man/1/perlmacosx/"&gt;this fine manual written by knowledgeable people&lt;/a&gt;!) Still, a neat thing they describe is that the MacOS X perl installation will happily read &lt;code&gt;/Library/Perl/5.10.0/AppendToPath&lt;/code&gt; and &lt;code&gt;/Library/Perl/5.10.0/PrependToPath&lt;/code&gt; and append / prepend any directories they list (one line per path, normal unix style) to &lt;code&gt;@INC&lt;/code&gt;. Or, of course, any other version than 5.10.0 – &lt;code&gt;perl -v&lt;/code&gt; will tell you what you've got installed. So, as root, I appended &lt;code&gt;/usr/local/lib/perl5/site_perl/&lt;/code&gt; to my &lt;code&gt;AppendToPath&lt;/code&gt;.&lt;br /&gt;
&lt;br /&gt;
Next up, assuming you've already made a mess trying to install stuff with cpan (I had), you may want to do what I did, which is &lt;code&gt;rm -rf ~/.cpan&lt;/code&gt; (which permanently nukes it; should you want to be able to undo that, you of course instead move it aside somewhere – you're solely responsible for your actions here, as always). Then run &lt;code&gt;cpan&lt;/code&gt;. It'll ask you tons of questions you might not know the answer to any better than I did if you say no, or give slightly okay defaults if you say yes. Some frustrating experimentation later, I came down with this recipe, which worked for me; first yes it, and then when you get the prompt, type &lt;code&gt;o conf&lt;/code&gt;. It'll probably look a bit like this, if the defaults remain about the same:&lt;br /&gt;
&lt;pre&gt;cpan[1]&amp;gt; o conf
$CPAN::Config options from '/Users/jhs/.cpan/CPAN/MyConfig.pm':
    commit             [Commit changes to disk]
    defaults           [Reload defaults from disk]
    help               [Short help about 'o conf' usage]
    init               [Interactive setting of all options]

    applypatch         []
    auto_commit        [0]
    build_cache        [100]
    build_dir          [/Users/jhs/.cpan/build]
    build_dir_reuse    [1]
    build_requires_install_policy [ask/yes]
    bzip2              [/usr/bin/bzip2]
    cache_metadata     [1]
    check_sigs         [0]
    colorize_debug     undef
    colorize_output    undef
    colorize_print     undef
    colorize_warn      undef
    commandnumber_in_prompt [1]
    commands_quote     undef
    cpan_home          [/Users/jhs/.cpan]
    curl               [/usr/bin/curl]
    dontload_hash      undef
    dontload_list      undef
    ftp                [/usr/bin/ftp]
    ftp_passive        [1]
    ftp_proxy          []
    getcwd             [cwd]
    gpg                []
    gzip               [/usr/bin/gzip]
    histfile           [/Users/jhs/.cpan/histfile]
    histsize           [100]
    http_proxy         []
    inactivity_timeout [0]
    index_expire       [1]
    inhibit_startup_message [0]
    keep_source_where  [/Users/jhs/.cpan/sources]
    load_module_verbosity [v]
    lynx               []
    make               [/usr/bin/make]
    make_arg           []
    make_install_arg   []
    make_install_make_command [/usr/bin/make]
    makepl_arg         []
    mbuild_arg         []
    mbuild_install_arg []
    mbuild_install_build_command [./Build]
    mbuildpl_arg       []
    ncftp              []
    ncftpget           []
    no_proxy           []
    pager              [/usr/bin/less]
    password           undef
    patch              [/usr/bin/patch]
    prefer_installer   [MB]
    prefs_dir          [/Users/jhs/.cpan/prefs]
    prerequisites_policy [ask]
    proxy_pass         undef
    proxy_user         undef
    randomize_urllist  undef
    scan_cache         [atstart]
    shell              [/bin/zsh]
    show_unparsable_versions [0]
    show_upload_date   [0]
    show_zero_versions [0]
    tar                [/usr/bin/tar]
    tar_verbosity      [v]
    term_is_latin      [1]
    term_ornaments     [1]
    test_report        [0]
    unzip              [/usr/bin/unzip]
    urllist           
    use_sqlite         [0]
    username           undef
    wait_list          undef
    wget               [/usr/local/bin/wget]
    yaml_load_code     [0]
    yaml_module        [YAML]


cpan[2]&amp;gt;&lt;/pre&gt;&lt;br /&gt;
Then paste this little snippet, which sets most things right (it's a good decade to use a UTF-8 terminal):&lt;br /&gt;
&lt;pre&gt;o conf term_is_latin 0
o conf check_sigs 1
o conf make_arg -j3
o conf make_install_arg -j3
o conf makepl_arg PREFIX=/usr/local
o conf mbuildpl_arg --install_base /usr/local
o conf commit&lt;/pre&gt;&lt;br /&gt;
This will have perl use two cores when compiling modules, and use &lt;code&gt;Module::Signature&lt;/code&gt; if you install it, which seemed like a nice enough idea (at least if you have gpg installed; you may want to skip the check_sigs part, or install it first, if not -- via &lt;code&gt;brew install gpgme&lt;/code&gt; for instance). And, most importantly, it'll put stuff in &lt;code&gt;/usr/local&lt;/code&gt; at installation time, so perl will find it at invocation time. (Some day, that might just work right out of the box, in MacOS too.)&lt;br /&gt;
&lt;br /&gt;
And that's it. Try it with &lt;code&gt;cpan Module::Signature&lt;/code&gt; for instance, if you enabled that and you'll eventually end up with a fatter &lt;code&gt;/usr/local/lib/perl5/site_perl&lt;/code&gt;. You are encouraged to drop other helpful tips here, especially if you know a thing or two about perl or cpan that I totally should have mentioned. Happy hacking! :-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15626356-7223986581350964714?l=ecmanaut.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/kTd5fdO18IMIKcWPTD8EOFQs_mA/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/kTd5fdO18IMIKcWPTD8EOFQs_mA/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/kTd5fdO18IMIKcWPTD8EOFQs_mA/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/kTd5fdO18IMIKcWPTD8EOFQs_mA/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/xxBcs/~4/Z9X7Mb-7R_o" height="1" width="1"/&gt;</content><link rel="related" href="http://www.manpagez.com/man/1/perlmacosx/" title="Installing perl modules on Snow Leopard and Homebrew" /><link rel="replies" type="application/atom+xml" href="http://ecmanaut.blogspot.com/feeds/7223986581350964714/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=15626356&amp;postID=7223986581350964714" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/15626356/posts/default/7223986581350964714?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/15626356/posts/default/7223986581350964714?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/xxBcs/~3/Z9X7Mb-7R_o/installing-perl-modules-on-snow-leopard.html" title="Installing perl modules on Snow Leopard and Homebrew" /><author><name>Johan Sundström</name><uri>http://www.blogger.com/profile/04076097346172610543</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://ecmanaut.blogspot.com/2011/03/installing-perl-modules-on-snow-leopard.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkQFR38ycSp7ImA9Wx9WEE4.&quot;"><id>tag:blogger.com,1999:blog-15626356.post-1340572036312610847</id><published>2011-01-14T00:50:00.000-08:00</published><updated>2011-01-14T10:38:36.199-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-01-14T10:38:36.199-08:00</app:edited><title>Musings on DNA, code and otherwise</title><content type="html">From college days, I recall microbiology as one of the more fascinating fields I never opted to pursue, but still developed a latent interest in. The evolved, highly complex and cross-connected execution context of biology, at the deepest levels where it meets (or indeed &lt;i&gt;is&lt;/i&gt;) the realities of chemistry and physics speaks to my geek genes. There are so many levels of exciting, beautiful and interesting stories, events and developments woven together and buried in genome! Not to mention it is open source!&lt;br /&gt;
&lt;br /&gt;
You want to grok something? &lt;abbr title="Use the source, Luke"&gt;UTSL&lt;/abbr&gt;! If you don't yet understand it, it's because you are not knowledgeable enough. Go learn! Experiment. Think hard. Figure it out. And then share what you learned, so others can reach longer, make it do more, be more efficient, go faster, taste better, or what have you. I think choosing mad computer science over mad genetics was more of a cultural thing gut draw towards openness; away from the lock-ins of lawyers of looming heavy corporations protecting the intellectual off-spring stemming from the money invested into powering their geeks' forays into the unknown, and toward the almost open eco system of what today amounts to the web and places like github, where people promiscuously and chaotically spin off of each others' work making stuff better together, for fun and profit.&lt;br /&gt;
&lt;br /&gt;
But back to genetic code, as inspired by a read of an article on &lt;a href="http://discovermagazine.com/2010/jun/03-the-insanity-virus"&gt;MS, schizophrenia and bipolar disorder as related to endogenous retroviruses&lt;/a&gt; (meaning stuff we all carry as common heritage, though not activated in most of us). One of the things we were taught in my classes was about the huge amount of introns (DNA between genes that is seemingly not active, as it isn't observed to ever get transcripted into proteins -- which is essentially how microbiological code execution happens) observed in all living organisms (about 98% of human DNA is &lt;a href="http://en.wikipedia.org/wiki/Noncoding_DNA"&gt;non-coding DNA&lt;/a&gt;). Of course the depth level of the insights we absorbed were rather meagre, and although omnipresent easy-access Wikipedia was not yet around, it felt fairly obvious that the rest, at the very least, would end up having all sorts of other functions or effects under conditions and circumstances that would relate to it somehow. If you have ever researched (or exploited) a buffer overflow in some program, you probably know that wherever the program pointer accidentally ends up, whatever junk or data happens to be in that memory region is suddenly, for all intents and purposes (or despite them :-), is now code! Maybe it will do something interesting. Or nefarious. Probably nefarious, really.&lt;br /&gt;
&lt;br /&gt;
Biology, chemistry and physics, of course, just add a gazillion more dimensions to "functions and effects of things", while also imposing a bus-load of peculiar constraints, and introducing still more environmental conditions from the rather chaotic virtual machine of physics, chemistry and biology (being three different zoom levels at which things happen to shoot your code in the foot) combined.&lt;br /&gt;
&lt;br /&gt;
If you thought debugging code is hard, it's actually a delightful walk in the park, for the most part -- free of all sorts of concerns like the ethics of feeding useful test arrays into your debugger, that your test subjects can't keep dying all the time until you figure it out, and so on, and that we're probably not debugging software that co-evolved on a planetary scale, over a couple of billion years, but was probably caused by, at the very most, a couple of decades worth of ingenuity from probably less than thousands (or at most millions) of humans, all more or less acting with actual intents, often worthy of words like "design" and "intent". We're kind of lucky, that way! And oftentimes, the whole code base is even your very own damn fault! And you could even know full well what every line of your code is supposed to do, even though you might not yet have discovered all the things it should probably also do to work under the conditions it'll be subject to when unforgiving users run it. (Even yourself!)&lt;br /&gt;
&lt;br /&gt;
I wonder how far into the future we have to go to see iLife speaking to the creative class doing justice to its name, providing us with the tools to be creative with the workings of micro- (or, for that matter, even macro-)organisms, in the same manner it's letting today's happy amateurs go wild with arts like graphics, music and video. Lots of people have rather rigid ideas about what amounts to art, science, work, life style, communication and so many other arbitrary things you can do for whichever reasons propel you, based, among other things, on rules, rulers or methods used in each field, motivations behind them, et cetera. Try breaking a few; you end up in far more interesting places. And make and bring friends, along the way!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15626356-1340572036312610847?l=ecmanaut.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/Rdn0pzk-_ZNaw3pgRr7eV91NAU4/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Rdn0pzk-_ZNaw3pgRr7eV91NAU4/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/Rdn0pzk-_ZNaw3pgRr7eV91NAU4/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Rdn0pzk-_ZNaw3pgRr7eV91NAU4/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/xxBcs/~4/PiOUPgvqRTU" height="1" width="1"/&gt;</content><link rel="related" href="http://discovermagazine.com/2010/jun/03-the-insanity-virus" title="Musings on DNA, code and otherwise" /><link rel="replies" type="application/atom+xml" href="http://ecmanaut.blogspot.com/feeds/1340572036312610847/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=15626356&amp;postID=1340572036312610847" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/15626356/posts/default/1340572036312610847?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/15626356/posts/default/1340572036312610847?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/xxBcs/~3/PiOUPgvqRTU/musings-on-dna-code-and-otherwise.html" title="Musings on DNA, code and otherwise" /><author><name>Johan Sundström</name><uri>http://www.blogger.com/profile/04076097346172610543</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://ecmanaut.blogspot.com/2011/01/musings-on-dna-code-and-otherwise.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkcFQ3g4eyp7ImA9WhZSGU8.&quot;"><id>tag:blogger.com,1999:blog-15626356.post-3334980042714149346</id><published>2011-01-09T01:06:00.001-08:00</published><updated>2011-04-04T07:40:12.633-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-04-04T07:40:12.633-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="opera extensions" /><category scheme="http://www.blogger.com/atom/ns#" term="chrome extensions" /><category scheme="http://www.blogger.com/atom/ns#" term="emacs" /><category scheme="http://www.blogger.com/atom/ns#" term="firefox extensions" /><title>Reading Chrome, Firefox and Opera extensions in Emacs</title><content type="html">If you're a fan of emacs' archive-mode that lets you load &lt;a href="http://en.wikipedia.org/wiki/ZIP_(file_format)"&gt;zip files&lt;/a&gt; and the like as it lets you load regular directories, and know that Firefox xpi, Chrome crx and Opera oex extensions are really just thinly wrapped zip files under the hood, you might expect Emacs to grok them, just the same. I did, and was a little surprised when it didn't plain work. (So maybe I'm running an old Emacs build?)&lt;br /&gt;
&lt;br /&gt;
Anyway, I looked into the matter and did a little poking about to see what setup would do the trick. In the case of Firefox and Opera, it's really easy, as the xpi and oex "formats" only amount to changing the filename extension and making sure you have the right files in there -- so all you have to do is make sure that &lt;code&gt;("\\.xpi\\'" . archive-mode)&lt;/code&gt; exists in your &lt;code&gt;auto-mode-alist&lt;/code&gt;, and &lt;code&gt;("\\.xpi\\'" . no-conversion)&lt;/code&gt; in your &lt;code&gt;auto-coding-alist&lt;/code&gt; (there is a little snippet for your &lt;code&gt;.emacs&lt;/code&gt; at the end of this post), and the corresponding oex variant.&lt;br /&gt;
&lt;br /&gt;
In the Chrome case (which prepends a &lt;a href="http://code.google.com/chrome/extensions/crx.html"&gt;Chrome header&lt;/a&gt; with a format version, an RSA public key and signature from the extension author), besides the corresponding crx change for same variables, I also had to patch the &lt;code&gt;lisp/arc-mode.el&lt;/code&gt; file lightly:&lt;br /&gt;
&lt;br /&gt;
&lt;iframe src="http://pastebin.com/embed_iframe.php?i=h2TUYMxC" style="border: none; width: 100%"&gt;&lt;a href="http://pastebin.com/h2TUYMxC"&gt;arc-mode.el.patch at pastebin&lt;/a&gt;&lt;/iframe&gt;&lt;br /&gt;
&lt;br /&gt;
If you try loading a crx and find it already works, someone upstream already applied the same or a better patch than mine to your installation, but otherwise, read on. To find where it is on your system, type &lt;code&gt;C-h archive-mode &amp;lt;return&amp;gt;&lt;/code&gt; and follow the &lt;code&gt;archive-mode is a compiled Lisp function in `&lt;b&gt;arc-mode.el&lt;/b&gt;'.&lt;/code&gt; link, apply the patch and &lt;code&gt;M-x byte-compile-file&lt;/code&gt; the result again.&lt;br /&gt;
&lt;br /&gt;
The &lt;code&gt;.emacs&lt;/code&gt; snippet that makes it all kick in automagically:&lt;br /&gt;
&lt;br /&gt;
&lt;iframe src="http://pastebin.com/embed_iframe.php?i=NajyvP9w" style="border: none; width: 100%"&gt;&lt;a href="http://pastebin.com/NajyvP9w"&gt;.emacs snippet at pastebin&lt;/a&gt;&lt;/iframe&gt;&lt;br /&gt;
&lt;br /&gt;
Note that for the Chrome extension case, you won't be able to edit and save any of the contents in place, as you can with plain zip (xpi, oex) files; the magic to remove/re-add public keys and signatures will be somebody else's late Saturday hack to complete. :) Enjoy!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15626356-3334980042714149346?l=ecmanaut.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/nWN70Mmou68XpNs8yUotUd8tsRI/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/nWN70Mmou68XpNs8yUotUd8tsRI/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/nWN70Mmou68XpNs8yUotUd8tsRI/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/nWN70Mmou68XpNs8yUotUd8tsRI/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/xxBcs/~4/uSV5YPtXNiE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://ecmanaut.blogspot.com/feeds/3334980042714149346/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=15626356&amp;postID=3334980042714149346" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/15626356/posts/default/3334980042714149346?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/15626356/posts/default/3334980042714149346?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/xxBcs/~3/uSV5YPtXNiE/reading-chrome-firefox-and-opera.html" title="Reading Chrome, Firefox and Opera extensions in Emacs" /><author><name>Johan Sundström</name><uri>http://www.blogger.com/profile/04076097346172610543</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://ecmanaut.blogspot.com/2011/01/reading-chrome-firefox-and-opera.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkcDRXk-fip7ImA9WhZSGU8.&quot;"><id>tag:blogger.com,1999:blog-15626356.post-9030700602642742326</id><published>2010-12-26T16:13:00.000-08:00</published><updated>2011-04-04T07:41:14.756-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-04-04T07:41:14.756-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="reference" /><category scheme="http://www.blogger.com/atom/ns#" term="Firebug" /><title>Vintage Firefox</title><content type="html">When I occasionally need to check how far back a feature was introduced in Firefox, it usually turns out I only have the last few versions installed, and takes a while before I find where mozilla.org hit them, so here goes: a complete archive of the latest (mac -- tweak the urls or browse yourself for Linux, Windows or otherwise) release of every major version of Firefox from 0.8 to date (at current time of writing, 3.6.13 is the most recent Firefox released) off of &lt;a href="ftp://ftp.mozilla.org/pub/mozilla.org/firefox/releases/"&gt;ftp://ftp.mozilla.org/pub/mozilla.org/firefox/releases/&lt;/a&gt;, where mozilla.org hosts them, and the Firebug releases you need to do any useful web development work with them:&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href="ftp://ftp.mozilla.org/pub/mozilla.org/firefox/releases/4.0b8/mac/en-US/Firefox%204.0%20Beta%208.dmg"&gt;Firefox 4.0 beta 8&lt;/a&gt; (Gecko 2 / &lt;a href="http://getfirebug.com/releases/firebug/1.7X/firebug-1.7X.0a7.xpi" title="Firefox 3.6 .. 4.0.* | any Toolkit 1.9.2 .. 2.0.0.* application"&gt;Firebug 1.7X.0a7&lt;/a&gt;)&lt;br /&gt;
Note: as neither of is released yet, consider both links outdated when you read this (the Firebug xpi especially is in development, as hinted by the X)&lt;/li&gt;
&lt;li&gt;&lt;a href="ftp://ftp.mozilla.org/pub/mozilla.org/firefox/releases/3.6.13/mac/en-US/Firefox%203.6.13.dmg"&gt;Firefox 3.6.13&lt;/a&gt; (Gecko 1.9.2 / &lt;a href="http://getfirebug.com/releases/firebug/1.6/firebug-1.6.0.xpi" title="Firefox 3.6 .. 3.6.*"&gt;Firebug 1.6.0&lt;/a&gt; or &lt;a href="http://getfirebug.com/releases/firebug/1.5/firebug-1.5.4.xpi" title="Firefox 3.5 .. 3.6.* | any Toolkit 1.9.1 .. 1.9.2.* application"&gt;1.5.4&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="ftp://ftp.mozilla.org/pub/mozilla.org/firefox/releases/3.5.16/mac/en-US/Firefox%203.5.16.dmg"&gt;Firefox 3.5.16&lt;/a&gt; (Gecko 1.9.1 / &lt;a href="http://getfirebug.com/releases/firebug/1.5/firebug-1.5.4.xpi" title="Firefox 3.5 .. 3.6.* | any Toolkit 1.9.1 .. 1.9.2.* application"&gt;Firebug 1.5.4&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="ftp://ftp.mozilla.org/pub/mozilla.org/firefox/releases/3.0.19-real-real/mac/en-US/Firefox%203.0.19.dmg"&gt;Firefox 3.0.19&lt;/a&gt; (Gecko 1.9 / &lt;a href="http://getfirebug.com/releases/firebug/1.4/firebug-1.4.5.xpi" title="Firefox 3.0 .. 3.6.*"&gt;Firebug 1.4.5&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="ftp://ftp.mozilla.org/pub/mozilla.org/firefox/releases/2.0.0.20/mac/en-US/Firefox%202.0.0.20.dmg"&gt;Firefox 2.0.0.20&lt;/a&gt; (Gecko 1.8.1 / &lt;a href="http://getfirebug.com/releases/firebug/1.3/firebug-1.3.4b2.xpi" title="Firefox 1.5 .. 3.9"&gt;Firebug 1.3.4b2&lt;/a&gt;, &lt;a href="http://getfirebug.com/releases/firebug/1.2/firebug-1.2.0.xpi" title="Firefox 1.5 .. 3.0.*"&gt;1.2.0&lt;/a&gt; or &lt;a href="Firefox 1.5 .. 2.0.0.*; last Joe Hewitt release"&gt;Firebug 1.0.5&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="ftp://ftp.mozilla.org/pub/mozilla.org/firefox/releases/1.5.0.12/mac/en-US/Firefox%201.5.0.12.dmg"&gt;Firefox 1.5.0.12&lt;/a&gt; (Gecko 1.8 / &lt;a href="http://getfirebug.com/releases/firebug1.05.xpi" title="Firefox 1.5 .. 2.0.0.*; last Joe Hewitt release"&gt;Firebug 1.05&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="ftp://ftp.mozilla.org/pub/mozilla.org/firefox/releases/1.0.8/mac/en-US/Firefox%201.0.8.dmg"&gt;Firefox 1.0.8&lt;/a&gt; (Gecko 1.7)&lt;/li&gt;
&lt;li&gt;&lt;a href="ftp://ftp.mozilla.org/pub/mozilla.org/firefox/releases/0.9.3/firefox-0.9.3-mac.dmg.gz"&gt;Firefox 0.9.3&lt;/a&gt; (Gecko 0.9)&lt;/li&gt;
&lt;li&gt;&lt;a href="ftp://ftp.mozilla.org/pub/mozilla.org/firefox/releases/0.8/firefox-0.8-mac.dmg.gz"&gt;Firefox 0.8&lt;/a&gt; (Gecko 0.8)&lt;/li&gt;
&lt;/ul&gt;&lt;br /&gt;
(Corresponding Gecko and Firebug versions, the second and third most messy to find Firefox entity, from the &lt;a href="https://developer.mozilla.org/en/Gecko"&gt;Gecko page on MDC&lt;/a&gt; and the install.rdf of the corresponding Firebug xpi:s archived at &lt;a href="http://getfirebug.com/"&gt;getfirebug.com&lt;/a&gt;.)&lt;br /&gt;
&lt;br /&gt;
Never ever download and install Firefox from any other site! There is a huge, shady "pay per install" market of people bundling other people's software with malware (bot nets, typically); read all about it from &lt;a href="http://www.symantec.com/content/en/us/enterprise/media/security_response/whitepapers/pay_per_install.pdf"&gt;Symantec&lt;/a&gt; (pdf) or &lt;a href="http://www.blackhat.com/presentations/bh-dc-10/Stevens_Kevin/BlackHat-DC-2010-Stevens-Underground-wp.pdf" title="The Underground Economy of the Pay-Per-Install (PPI) Business"&gt;Kevin Stevens&lt;/a&gt; (also pdf, the latter from &lt;a href="http://www.blackhat.com/html/bh-dc-10/bh-dc-10-briefings.html"&gt;Black Hat DC 2010&lt;/a&gt;). This goes for all executable programs you download and install on your machine; if you have no reason to trust the source, get it from a source you do trust.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15626356-9030700602642742326?l=ecmanaut.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/bO05164dVkmunXqWz9xCSxnXxFM/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/bO05164dVkmunXqWz9xCSxnXxFM/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/bO05164dVkmunXqWz9xCSxnXxFM/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/bO05164dVkmunXqWz9xCSxnXxFM/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/xxBcs/~4/S5lj0w7q9Ps" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://ecmanaut.blogspot.com/feeds/9030700602642742326/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=15626356&amp;postID=9030700602642742326" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/15626356/posts/default/9030700602642742326?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/15626356/posts/default/9030700602642742326?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/xxBcs/~3/S5lj0w7q9Ps/vintage-firefox.html" title="Vintage Firefox" /><author><name>Johan Sundström</name><uri>http://www.blogger.com/profile/04076097346172610543</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://ecmanaut.blogspot.com/2010/12/vintage-firefox.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkcASXs_fSp7ImA9WhZSGU8.&quot;"><id>tag:blogger.com,1999:blog-15626356.post-7125742892016250691</id><published>2010-12-12T00:40:00.000-08:00</published><updated>2011-04-04T07:40:48.545-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-04-04T07:40:48.545-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="opera extensions" /><title>Opera 11 extensions @ Add-on-Con</title><content type="html">I attended &lt;a href="http://add-on-con.com/"&gt;Add-on-Con&lt;/a&gt; this year again (I think I missed last year's), and figured I should sum up some of the interesting and/or useful stuff I picked up on while there. What I found most gratifying was the upcoming &lt;a href="http://www.opera.com/addons/extensions/develop/"&gt;Opera (11) add-on API&lt;/a&gt;, which takes on the same approach as the Chrome and Safari herd, with the clean, HTML5 / postMessage / content script based design we have grown to expect, with optional background and popup pages. (Mozilla kind of wants to get there too, but does not expect to have anything remotely near it for at least another year, and I don't think it's even on any road maps yet.)&lt;br /&gt;
&lt;br /&gt;
In Opera's current version, they don't go quite as far as does Chrome with its process separation, so an extension's popup can actually read from and write to &lt;code&gt;localStorage&lt;/code&gt; from the same origin as its background page (which lets you simplify the message passing a little if you're not aiming for easy porting). Your content script runs in its own global object, but it has a &lt;code&gt;window&lt;/code&gt; reference to the current window object, as the page sees it, and in the interest of not automatically leaking your script's guts into the page's global scope, it is not in the inheritance chain, so you actually have to use long references like &lt;code&gt;window.document&lt;/code&gt; and &lt;code&gt;window.localStorage&lt;/code&gt; to access them. (I tried assigning &lt;code&gt;this.__proto__ = window;&lt;/code&gt;, which in theory should import all window properties in my content script's scope, and while that seemed to allow the former, it still failed on the latter, so I guess I hit unsupported stuff or beta bugs.)&lt;br /&gt;
&lt;br /&gt;
To try it out, I made my &lt;a href="https://github.com/johan/github-improved/"&gt;github improved&lt;/a&gt; user script an &lt;a href="https://addons.opera.com/addons/extensions/details/github-improved/"&gt;Opera 11 extension&lt;/a&gt;. Run &lt;code&gt;rake&lt;/code&gt; to build the zipped-up oex from the content script if you &lt;a href="https://github.com/johan/github-improved/"&gt;check out or fork the codebase&lt;/a&gt;, which puts the content script in &lt;code&gt;includes/&lt;/code&gt; (all scripts in &lt;code&gt;includes/&lt;/code&gt; with a &lt;code&gt;// ==UserScript==&lt;/code&gt; block with Greasemonkey-style &lt;code&gt;@include&lt;/code&gt; / &lt;code&gt;@exclude&lt;/code&gt; rules run, not at the &lt;code&gt;DOMContentLoaded&lt;/code&gt; event, but at page start, so you have to set your own &lt;code&gt;DOMContentLoaded&lt;/code&gt; listener in a browser forked section if you want to execute under the same page conditions under Opera as in Firefox or a Chrome content script set to load at page ready).&lt;br /&gt;
&lt;br /&gt;
Touting standards, Opera decided that a browser extension is essentially a Widget, and reused the &lt;a href="http://www.w3.org/TR/widgets/"&gt;W3C Widget standard&lt;/a&gt; they helped coin a while back, making its manifest sit in &lt;code&gt;config.xml&lt;/code&gt; in the oex (a zip file) root directory (and emphasized that it also means you have to have an &lt;code&gt;index.html&lt;/code&gt; next to it – the background page – but that it can be empty, if you like). For instance:&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;
&amp;lt;widget xmlns="http://www.w3.org/ns/widgets" version="1.0.0-0"&amp;gt;
  &amp;lt;name&amp;gt;Github improved&amp;lt;/name&amp;gt;
  &amp;lt;icon src="icon.png"/&amp;gt;
  &amp;lt;author href="http://ecmanaut.blogspot.com/"&amp;gt;Johan Sundström&amp;lt;/author&amp;gt;
  &amp;lt;description xml:lang="en"&amp;gt;Adds github changeset unfolding and other site improvements.&amp;lt;/description&amp;gt;
&amp;lt;/widget&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
This also means that you can use Widget storage and config-based preference init, if you like. It indeed even seems to be the recommended way, as that gets you unlimited storage (actually: the same total cap Opera sets for itself globally), whereas your background page's &lt;code&gt;localStorage&lt;/code&gt; gets subjected to the same arbitrary per-domain storage size cap that web sites are.&lt;br /&gt;
&lt;br /&gt;
As for extension distribution, they of course have their own extension gallery you may want to submit your things to, and like all human-driven approval processes, they have a slightly anal process to get through first. Essentially, the less you can state about your add-on, the fewer opportunities you'll have to fail their test criteria; I was advised by the presenters not to add an add-on homepage, for example.&lt;br /&gt;
&lt;br /&gt;
Currently, every submission attempt of yours in the approval process requires you to update your version number, so you can't aim for releasing a final 1.0 and treat all the attempts on the way there as release candidate 1 through N; my test add-on went through three revisions before coming out, and ended up named 1.0.0-0 in the end. It also was required to list change notes, that are reflected on the download page even when for an add-on that never existed before. Badly implemented good intentions also featured in the insistent numerous-stage wizard walking you through many steps every time (including screen shots, icons, et c), but there is at least the option to copy data from a previous version.&lt;br /&gt;
&lt;br /&gt;
I think I may make Opera extensions of some of the extension-worthy hacks I do, but having tried the Chrome extension gallery's really smooth process, showing how it should be done, I don't think I'll have the patience to jump through Opera's hoops very often unless they improve notably.&lt;br /&gt;
&lt;br /&gt;
To me, the bottom line is that Opera's add-on system doesn't make it prohibitively difficult to support Opera too, if you are already making an add-on for Chrome that does not rely on lots of deeper-integration Chrome API:s. It still surprises me that while they have the best technical user javascript implementation (and first too) a browser has ever had, they gave it the worst UI (a config switch listing a directory into which you yourself drop user scripts manually, after having modded them to add a &lt;code&gt;DOMContentLoaded&lt;/code&gt; event listener to start the main part of the script) ever. Their js hooks still thorougly beat both Greasemonkey and Chrome, yet the lack of installation when visiting a &lt;code&gt;*.user.js&lt;/code&gt; file locks that feature set in for only the really expert of browser users.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15626356-7125742892016250691?l=ecmanaut.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/hJWV0QDavDUuh8iCAxV07vnY3QI/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/hJWV0QDavDUuh8iCAxV07vnY3QI/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/hJWV0QDavDUuh8iCAxV07vnY3QI/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/hJWV0QDavDUuh8iCAxV07vnY3QI/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/xxBcs/~4/9Nk1yawhPs4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://ecmanaut.blogspot.com/feeds/7125742892016250691/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=15626356&amp;postID=7125742892016250691" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/15626356/posts/default/7125742892016250691?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/15626356/posts/default/7125742892016250691?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/xxBcs/~3/9Nk1yawhPs4/opera-11-extensions-add-on-con.html" title="Opera 11 extensions @ Add-on-Con" /><author><name>Johan Sundström</name><uri>http://www.blogger.com/profile/04076097346172610543</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://ecmanaut.blogspot.com/2010/12/opera-11-extensions-add-on-con.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0AFRHw8eSp7ImA9Wx5XGUk.&quot;"><id>tag:blogger.com,1999:blog-15626356.post-1824040395613080461</id><published>2010-09-19T18:21:00.000-07:00</published><updated>2010-09-19T18:21:55.271-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-09-19T18:21:55.271-07:00</app:edited><title>Comfy browser performance testing</title><content type="html">I have been poking around with some performance tests and profiling lately, first with Steve Souders' &lt;a href="http://www.browserscope.org/"&gt;Browserscope&lt;/a&gt;, which gets the job done, at some convenience cost of setting up a publicly hosted web page and tying it to a Google account (that you might have to first create), and, for loading performance, different ways of organizing script tags, images, iframes, style sheets and so on, &lt;a href="http://stevesouders.com/cuzillion/"&gt;Cuzillion&lt;/a&gt;, by same author.&lt;br /&gt;
&lt;br /&gt;
Today, I found and toyed around a bit with &lt;a href="http://jsperf.com/"&gt;jsperf.com&lt;/a&gt; by &lt;a href="http://mathiasbynens.be/"&gt;Mathias Bynens&lt;/a&gt;, which does much of the boring setup job for you, when it comes to micro-benchmarking some snippet of javascript versus another, assuming the thing you want to test is synchronous, and doesn't involve complex preconditions. (I wonder what makes Array copying using a &lt;a href="http://jsperf.com/vs-array-conversion/9#run"&gt;saved Array.prototype.slice&lt;/a&gt; significantly slower than the other more evenly performance-matched variants?) As should always be stated when mentioning benchmarks and optimization, this kind of micro-benchmarking is less relevant than finding your code's hot spots and picking better algorithms where relevant. That said, it's still academic fun to play with this kind of thing.&lt;br /&gt;
&lt;br /&gt;
For this kind of small test, jsperf.com does all the Browserscope setup work for you, and lets others improve (fork) your test after the fact, adding versions you didn't think of yourself that do the same thing. I have a vague plan of trying to make it run some performance tests for a little code snippet I wrought up recently that does a deep copy of a nested (JSON:able) structure from a parent window where there may be crud on &lt;code&gt;Object.prototype&lt;/code&gt; (the code should run in an iframe free of such), to benchmark vs a mere &lt;code&gt;JSON.parse(JSON.stringify(taintedObject)&lt;/code&gt;, which would also clean away the crud:&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;&lt;code&gt;var _slice = [].slice, _toString = Object.prototype.toString;
function array(arrayish) {
  return _slice.call(arrayish, 0);
}

function isArray(obj) {
  return '[object Array]' === _toString.call(obj);
}

// Take a nested structure from a hostile window (presumably full of crap in its
// Object.prototype, et cetera) and return a cleaned-up version with this window
// object's (pure) Array and Object constructors.
function deepClone(obj) {
  if ('object' !== typeof obj) return obj;
  if (null === obj) return null;
  if (isArray(obj)) return array(obj).map(deepClone);
  var clean = {};
  for (var key in obj)
    if (obj.hasOwnProperty(key))
      clean[key] = deepClone(obj[key]);
  return clean;
}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
What surprised me about the above code, when testing it on the kinds of payloads it would typically handle (data somewhat heavy on largeish strings), was that it actually was a bit faster than using the browser native JSON codecs, whereas, for larger inputs, native code always won out. Sometimes you just have to test stuff, to find out what wins.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15626356-1824040395613080461?l=ecmanaut.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/GISnCdlRY9MklucbqI8ivqMz7gg/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/GISnCdlRY9MklucbqI8ivqMz7gg/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/GISnCdlRY9MklucbqI8ivqMz7gg/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/GISnCdlRY9MklucbqI8ivqMz7gg/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/xxBcs/~4/ZubA_4Gb2EQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://ecmanaut.blogspot.com/feeds/1824040395613080461/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=15626356&amp;postID=1824040395613080461" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/15626356/posts/default/1824040395613080461?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/15626356/posts/default/1824040395613080461?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/xxBcs/~3/ZubA_4Gb2EQ/comfy-browser-performance-testing.html" title="Comfy browser performance testing" /><author><name>Johan Sundström</name><uri>http://www.blogger.com/profile/04076097346172610543</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://ecmanaut.blogspot.com/2010/09/comfy-browser-performance-testing.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkACRHo6eyp7ImA9WhZSGU8.&quot;"><id>tag:blogger.com,1999:blog-15626356.post-1021536268443343401</id><published>2010-09-13T08:22:00.000-07:00</published><updated>2011-04-04T07:52:45.413-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-04-04T07:52:45.413-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="JSON" /><category scheme="http://www.blogger.com/atom/ns#" term="firefox extensions" /><title>JSONView with copy &amp; paste support</title><content type="html">Last weekend I picked up &lt;a href="http://jsonview.com/"&gt;Ben Hollis' JSONView&lt;/a&gt; extension to tinker it to keep JSON viewed through it copy-and-paste:able, both as a whole and in part. It was rather fun work and within some few hours I had a patch that did the trick, and a few other ones to boot:&lt;br /&gt;
&lt;br /&gt;
&lt;script src="http://gist.github.com/577395.js?file=jsonview-0.5.copy.paste.json"&gt;&lt;/script&gt;&lt;noscript&gt;&lt;a href="http://1.bp.blogspot.com/_mSA70aKq5R0/TI48rtcOHgI/AAAAAAAAALE/5ZdVotLeoQo/s1600/jsonview-0.5.copy.paste.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="227" src="http://1.bp.blogspot.com/_mSA70aKq5R0/TI48rtcOHgI/AAAAAAAAALE/5ZdVotLeoQo/s320/jsonview-0.5.copy.paste.gif" width="320" /&gt;&lt;/a&gt;&lt;/noscript&gt;&lt;br /&gt;
&lt;br /&gt;
I sent Ben a patch, but not having heard anything back, I figured I might as well share the results here too, as it's all MIT licensed goodness (as is my patched version, of course). You can either download an &lt;a href="http://www.lysator.liu.se/~jhs/jsonview-0.5.copy.paste.xpi"&gt;installable xpi build&lt;/a&gt;, or &lt;a href="http://github.com/johan/jsonview-firefox/tree/johan"&gt;fork my repository from github&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
My edits are all on a branch named after my github user -- a practice I can recommend, when mirroring some svn upstream repository (with git-svn, for instance); it simplifies the process of tracking vendor updates to a mere &lt;code&gt;git svn rebase&lt;/code&gt; on master (for you -- git-svn, sadly, is not able to push its metadata about the non-git upstream to github) and lets other people reuse your pristine vendor branch for their own purposes.&lt;br /&gt;
&lt;br /&gt;
Enjoy your easier-to-handle JSON! I guess next step would be to integrate these improvements into &lt;a href="http://github.com/jamiew/jsonview-chrome"&gt;the Chrome fork&lt;/a&gt; Jamie Wilkinson is maintaining. Any takers?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15626356-1021536268443343401?l=ecmanaut.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/TH17jCjmwOzOVgyb4eA5_uS695c/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/TH17jCjmwOzOVgyb4eA5_uS695c/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/TH17jCjmwOzOVgyb4eA5_uS695c/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/TH17jCjmwOzOVgyb4eA5_uS695c/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/xxBcs/~4/1u6ijM47R3I" height="1" width="1"/&gt;</content><link rel="related" href="http://www.lysator.liu.se/~jhs/jsonview-0.5.copy.paste.xpi" title="JSONView with copy &amp; paste support" /><link rel="replies" type="application/atom+xml" href="http://ecmanaut.blogspot.com/feeds/1021536268443343401/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=15626356&amp;postID=1021536268443343401" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/15626356/posts/default/1021536268443343401?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/15626356/posts/default/1021536268443343401?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/xxBcs/~3/1u6ijM47R3I/jsonview-with-copy-paste-support.html" title="JSONView with copy &amp; paste support" /><author><name>Johan Sundström</name><uri>http://www.blogger.com/profile/04076097346172610543</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/_mSA70aKq5R0/TI48rtcOHgI/AAAAAAAAALE/5ZdVotLeoQo/s72-c/jsonview-0.5.copy.paste.gif" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://ecmanaut.blogspot.com/2010/09/jsonview-with-copy-paste-support.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0AARX84fSp7ImA9Wx5RFUQ.&quot;"><id>tag:blogger.com,1999:blog-15626356.post-5091271779578372353</id><published>2010-08-23T03:55:00.000-07:00</published><updated>2010-08-23T14:42:24.135-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-08-23T14:42:24.135-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Greasemonkey" /><category scheme="http://www.blogger.com/atom/ns#" term="github" /><category scheme="http://www.blogger.com/atom/ns#" term="Chrome" /><title>Friendlier github commits pages</title><content type="html">I figured I should announce the news of &lt;a href="http://userscripts.org/scripts/show/76422"&gt;a much improved github commits page&lt;/a&gt; I have been tinkering with for a while, that lets you unfold full details about commits (individually, or in batch) without leaving the page. A screenshot of what the &lt;a href="http://github.com/greasemonkey/greasemonkey/commits/master"&gt;Greasemonkey master branch commits&lt;/a&gt; might look like with a few unfolded:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_mSA70aKq5R0/THJCTbbPwSI/AAAAAAAAAK0/QREKrx72zqw/s1600/github-gm-master.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_mSA70aKq5R0/THJCTbbPwSI/AAAAAAAAAK0/QREKrx72zqw/s320/github-gm-master.png" alt="screenshot of github commits page with the user script active" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
Usage is intuitive; just click anywhere in a commit that isn't already a link, and the commit will load in place (unless already loaded) and unfold its whole changeset, or refold itself again, when clicked a second time. Similarly, individual files changed can be folded and unfolded much the same way, though only by clicking their headers (I often want to copy and paste stuff from diffs, so no click magic there). To unfold or refold every commit on the page, either hit "f", or click the "(un)fold all commits" link at the top or bottom right of the page.&lt;br /&gt;
&lt;br /&gt;
This user script (&lt;a href="http://userscripts.org/scripts/source/76422.user.js"&gt;install link&lt;/a&gt;, &lt;a href="http://userscripts.org/scripts/show/76422"&gt;userscript.org page&lt;/a&gt; with docs and complete change log) is incidentally compatible with extensions like &lt;a href="http://autopagerize.net/"&gt;AutoPagerize&lt;/a&gt; too, in case you prefer scrolling for content to finding and clicking "Older" (h) and "Newer" (l). And if you just want to try it out without installing anything, &lt;a href="javascript:__RUNS_IN_PAGE_SCOPE__=true;void(function(u){var d=document,t=d.createElement('script'),p=d.getElementsByTagName('head')[0] || d.body;t.type='text/javascript';t.async=true;t.src=u;p.appendChild(t)})('http://userscripts.org/scripts/source/76422.user.js?bookmarklet');"&gt;try this bookmarklet&lt;/a&gt; on any github &lt;a href="http://github.com/greasemonkey/greasemonkey/commits/master"&gt;commits page&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
And it's all done by a hundred lines of jQuery, about a dozen lines of css and another dozen lines of Greasemonkey / Chrome portability code that breaks out of their respective sandbox environments to run what the script needs to run in the context of the web page itself.&lt;br /&gt;
&lt;br /&gt;
That latter piece is useful too, by the way, modeled on a trick &lt;a href="http://arantius.com/"&gt;Anthony Lieuallen&lt;/a&gt; came up with for the Greasemonkey wiki at some point. This is what it looks like, including full docs:&lt;br /&gt;
&lt;br /&gt;
&lt;script src="http://gist.github.com/545223.js?file=sandbox-breaker.js"&gt;&lt;/script&gt;&lt;noscript&gt;(&lt;a href="http://gist.github.com/545223"&gt;gist link&lt;/a&gt; for feed readers)&lt;/noscript&gt;&lt;br /&gt;
The above-referred jQuery is already loaded by github's page template, so I don't need to bother grabbing or shipping one of my own. If you are hacking a more hostile site, and run Greasemonkey you might want to add a &lt;code&gt;// @require http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js&lt;/code&gt; line to your script header instead (I haven't tested, but if you try to run jQuery in the mozilla javascript sandbox anything beyond really basic stuff fails due to the &lt;a href="http://commons.oreilly.com/wiki/index.php/Greasemonkey_Hacks/Getting_Started#Avoid_Common_Pitfalls"&gt;common pitfalls&lt;/a&gt; that jQuery, sanely, does not much attempt to evade).&lt;br /&gt;
&lt;br /&gt;
All above code is freely poachable (read: MIT license) &lt;a href="http://github.com/johan/github-improvements/"&gt;at github&lt;/a&gt;, with as much or little attribution as you like. I would of course be especially happy to see the github people adopt this for their default page templates, as it's really useful stuff. Share and enjoy!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15626356-5091271779578372353?l=ecmanaut.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/jKclnGC6K70-tsKAiXMBUqHVtbs/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/jKclnGC6K70-tsKAiXMBUqHVtbs/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/jKclnGC6K70-tsKAiXMBUqHVtbs/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/jKclnGC6K70-tsKAiXMBUqHVtbs/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/xxBcs/~4/mX0ywVG9kDw" height="1" width="1"/&gt;</content><link rel="related" href="http://userscripts.org/scripts/review/76422" title="Friendlier github commits pages" /><link rel="replies" type="application/atom+xml" href="http://ecmanaut.blogspot.com/feeds/5091271779578372353/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=15626356&amp;postID=5091271779578372353" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/15626356/posts/default/5091271779578372353?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/15626356/posts/default/5091271779578372353?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/xxBcs/~3/mX0ywVG9kDw/friendlier-github-commits-pages.html" title="Friendlier github commits pages" /><author><name>Johan Sundström</name><uri>http://www.blogger.com/profile/04076097346172610543</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/_mSA70aKq5R0/THJCTbbPwSI/AAAAAAAAAK0/QREKrx72zqw/s72-c/github-gm-master.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://ecmanaut.blogspot.com/2010/08/friendlier-github-commits-pages.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0UBQn84cCp7ImA9Wx5TE0w.&quot;"><id>tag:blogger.com,1999:blog-15626356.post-4896125614882272072</id><published>2010-07-28T03:00:00.001-07:00</published><updated>2010-07-28T03:00:53.138-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-07-28T03:00:53.138-07:00</app:edited><title>Showing inline HTML comments of Paul Graham's</title><content type="html">I browsed a few of the older of &lt;a href="http://www.paulgraham.com/articles.html"&gt;Paul Graham's Essays&lt;/a&gt; tonight, dug up my &lt;a href="http://userscripts.org/scripts/show/6954"&gt;Paul Graham click-to-inline footnotes&lt;/a&gt; user-script, which wasn't installed in this Google Chrome profile (&lt;a href="http://userscripts.org/scripts/source/6954.user.js"&gt;install link here&lt;/a&gt;), and peeked at the source of a few of the essays which it still doesn't grok.&lt;br /&gt;
&lt;br /&gt;
In doing so, I happened upon some HTML comments -- the next level of shaved-off cutting-floor material left around for our prying eyes, of you will -- many of which were interesting, much like his foot-notes. So I hacked up a new version of the script, which inlines those too, showing them as little &amp;lt;a&amp;gt;, &amp;lt;b&amp;gt;, &amp;lt;c&amp;gt;, onward -- expanding to something looking like an HTML comment when clicked.&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://userscripts.org/scripts/source/6954.user.js"&gt;Share and enjoy!&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
To test drive the new feature, you might want to re-read &lt;a href="http://www.paulgraham.com/bronze.html"&gt;Why Smart People Have Bad Ideas&lt;/a&gt;, &lt;a href="http://www.paulgraham.com/venturecapital.html"&gt;A Unified Theory of VC Suckage&lt;/a&gt; and &lt;a href="http://www.paulgraham.com/essay.html"&gt;The Age of the Essay&lt;/a&gt;. (And before anyone mentions it: no, I didn't actually get to making it augment his old-style [non-]markup for footnotes. Maybe next time. ;-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15626356-4896125614882272072?l=ecmanaut.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/rAWR8c8tCHE3iLfkZG1sO8eS7tE/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/rAWR8c8tCHE3iLfkZG1sO8eS7tE/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/rAWR8c8tCHE3iLfkZG1sO8eS7tE/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/rAWR8c8tCHE3iLfkZG1sO8eS7tE/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/xxBcs/~4/QUcNRGCn3yE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://ecmanaut.blogspot.com/feeds/4896125614882272072/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=15626356&amp;postID=4896125614882272072" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/15626356/posts/default/4896125614882272072?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/15626356/posts/default/4896125614882272072?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/xxBcs/~3/QUcNRGCn3yE/showing-inline-html-comments-of-paul.html" title="Showing inline HTML comments of Paul Graham's" /><author><name>Johan Sundström</name><uri>http://www.blogger.com/profile/04076097346172610543</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://ecmanaut.blogspot.com/2010/07/showing-inline-html-comments-of-paul.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkQFQno8cCp7ImA9WhZSGU8.&quot;"><id>tag:blogger.com,1999:blog-15626356.post-5038860889973985855</id><published>2010-07-14T22:59:00.000-07:00</published><updated>2011-04-04T07:45:13.478-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-04-04T07:45:13.478-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="SVG" /><title>Optimizing SVGs</title><content type="html">The other night I came across this cool &lt;a href="http://www.zo.utexas.edu/faculty/antisense/DownloadfilesToL.html"&gt;Tree of Life&lt;/a&gt; page, featuring some pdfs and images of the family relationship of all life on Earth. Great stuff. Among them, this simplified rendition divided into about a hundred sub-families, and their relations:&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://2.bp.blogspot.com/_mSA70aKq5R0/TD6WVXq0LwI/AAAAAAAAAKY/nS977Qbv14w/s1600/tree-of-life.jpg" style="text-align: center; margin: 0 auto; display: block;"&gt;&lt;img border="0"src="http://2.bp.blogspot.com/_mSA70aKq5R0/TD6WVXq0LwI/AAAAAAAAAKY/nS977Qbv14w/s320/tree-of-life.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;
You see our really ancient common heritage starting at 0 radians, progressing through evolution towards the really highly evolved creatures at two pi radians; birds, crocodiles, turtles and (you are here!) mammals (but in reverse order; sorry -- us mammals are not the last cry in evolution in all ways conceivable :-).&lt;br /&gt;
&lt;br /&gt;
I liked it, but it felt wrong that it was trapped in a pdf; this kind of thing should really be a Scalable Vector Graphics image (SVG, henceforth) with cut-and-pastable text, and both readable and hackable right in the page source, for people like you and me that like to poke around in things.&lt;br /&gt;
&lt;br /&gt;
So I made an exercise turning it into a somewhat nice SVG, to see both how small I could make it, without much effort, and where browsers are at in terms of rendering an inline SVG, these days. I haven't actually tested yet, so it'll be a fun surprise for me too, upon publishing this post. And if your browser doesn't render it, you still had the rasterized version above, or the source &lt;a href="http://www.zo.utexas.edu/faculty/antisense/TreeofLife2.pdf"&gt;pdf&lt;/a&gt; (35008 bytes long).&lt;br /&gt;
&lt;br /&gt;
Oh, and for the curious, there's a public git repository of &lt;a href="http://github.com/johan/tree-of-life.svg/commits/"&gt;all the changes on github&lt;/a&gt;, one step at a time, from the first version (where it's helpful to have a friend that has Adobe Illustrator, for instance, to do an initial machine translation of the pdf to a workable yet messy SVG). For reference, this page does not embed the minimized &lt;a href="http://github.com/johan/tree-of-life.svg/raw/9e9bc50d2a4f55c74479fff3f7a9cac421845f00/tree-of-life.svg"&gt;end result&lt;/a&gt;, which weighed in at 14852 bytes (or 6038, &lt;a href="http://github.com/johan/tree-of-life.svg/raw/9e9bc50d2a4f55c74479fff3f7a9cac421845f00/tree-of-life.svgz"&gt;gzipped to an svgz&lt;/a&gt;).&lt;br /&gt;
&lt;br /&gt;
(I consider those cheating, as the line data itself has been compressed somewhat beyond the point where it's still hackable.)&lt;br /&gt;
&lt;br /&gt;
If you want to play around with this kind of thing, and get familiar with hand-editing SVG files, I can whole-heartedly recommend &lt;a href="http://intertwingly.net/blog/"&gt;Sam Ruby&lt;/a&gt;'s great library of &lt;a href="http://intertwingly.net/svg/"&gt;sub-kilobyte hand-made SVG:s&lt;/a&gt;. While I can't find a statement to attest to it at the moment, I believe they are all freely MIT licensed (I think I asked him in person at SVG Open 2009), encouraging you to learn from and play with them. It is a great resource if you want to start playing with this yourself and want to pick up on some of the tricks of the trade, since they, on average, contain pretty much 100% signal, 0% noise.&lt;br /&gt;
&lt;br /&gt;
Oh, and the &lt;a href="http://www.w3.org/TR/SVG/"&gt;SVG specification&lt;/a&gt; when you are curious about something specific. If you want to learn a minimal subset only that can do almost everything, look at the &lt;a href="http://www.w3.org/TR/SVG/paths.html"&gt;&lt;code&gt;&amp;lt;path d="turtle graphics here"/&amp;gt;&lt;/code&gt;&lt;/a&gt; attribute.&lt;br /&gt;
&lt;br /&gt;
And here is the outcome of my own craftsmanship, for the browsers that get it:&lt;br /&gt;
&lt;br /&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" viewBox="33 170 569 470"&gt;&lt;g fill="none" stroke="#000" font-family="ArialMT" font-size="9"&gt; &lt;line x1="310.66" y1="399.811" x2="306" y2="396"/&gt; &lt;line x1="420.085" y1="404.212" x2="312.005" y2="396.432"/&gt; &lt;path d="M312.005,396.432 c-0.184,2.536-1.939,4.684-4.389,5.367"/&gt; &lt;line x1="307.616" y1="401.799" x2="309.232" y2="407.598"/&gt; &lt;line x1="456.5" y1="396" x2="420.38" y2="396"/&gt; &lt;path d="M420.38,396 c0,5.482-0.394,10.957-1.179,16.382"/&gt; &lt;line x1="419.201" y1="412.382" x2="425.158" y2="413.244"/&gt; &lt;line x1="456.185" y1="405.742" x2="426.147" y2="403.794"/&gt; &lt;path d="M426.147,403.794 c-0.41,6.326-1.32,12.61-2.72,18.794"/&gt; &lt;line x1="423.428" y1="422.588" x2="429.299" y2="423.917"/&gt; &lt;line x1="455.239" y1="415.442" x2="431.36" y2="412.332"/&gt; &lt;path d="M431.36,412.332 c-1.014,7.788-2.753,15.464-5.19,22.929"/&gt; &lt;line x1="426.169" y1="435.261" x2="431.892" y2="437.13"/&gt; &lt;line x1="446.783" y1="428.476" x2="435.051" y2="425.77"/&gt; &lt;path d="M435.051,425.77 c-1.769,7.668-4.217,15.163-7.316,22.396"/&gt; &lt;line x1="427.734" y1="448.165" x2="433.267" y2="450.536"/&gt; &lt;line x1="453.667" y1="425.062" x2="447.761" y2="423.899"/&gt; &lt;path d="M447.761,423.899 c-0.603,3.062-1.304,6.103-2.104,9.118"/&gt; &lt;line x1="445.657" y1="433.018" x2="451.477" y2="434.56"/&gt; &lt;line x1="441.407" y1="446.391" x2="435.766" y2="444.291"/&gt; &lt;path d="M435.766,444.291 c-1.564,4.204-3.332,8.329-5.297,12.361"/&gt; &lt;line x1="430.469" y1="456.652" x2="441.292" y2="461.926"/&gt; &lt;line x1="448.676" y1="443.896" x2="442.969" y2="441.979"/&gt; &lt;path d="M442.969,441.979 c-0.993,2.958-2.081,5.882-3.265,8.771"/&gt; &lt;line x1="439.705" y1="450.749" x2="445.275" y2="453.03"/&gt; &lt;line x1="429.128" y1="471.59" x2="316.261" y2="402.299"/&gt; &lt;path d="M316.261,402.299 c-3.298,5.372-10.182,7.291-15.784,4.399"/&gt; &lt;line x1="300.477" y1="406.698" x2="297.715" y2="412.048"/&gt; &lt;line x1="436.741" y1="470.545" x2="431.511" y2="467.563"/&gt; &lt;path d="M431.512,467.563 c-1.545,2.71-3.178,5.37-4.896,7.974"/&gt; &lt;line x1="426.616" y1="475.538" x2="431.642" y2="478.852"/&gt; &lt;line x1="396.567" y1="492.633" x2="318.351" y2="409.177"/&gt; &lt;path d="M318.35,409.177 c-7.276,6.821-18.706,6.451-25.526-0.826c-3.719-3.968-5.452-9.399-4.718-14.788"/&gt; &lt;line x1="288.105" y1="393.563" x2="282.14" y2="392.751"/&gt; &lt;line x1="426.015" y1="486.811" x2="411.613" y2="475.914"/&gt; &lt;path d="M411.613,475.914 c-9.081,12.001-20.14,22.365-32.704,30.65"/&gt; &lt;line x1="378.909" y1="506.564" x2="382.224" y2="511.591"/&gt; &lt;line x1="403.11" y1="494.695" x2="398.888" y2="490.404"/&gt; &lt;line x1="412.214" y1="493.944" x2="407.789" y2="489.863"/&gt; &lt;path d="M407.788,489.863 c-3.041,3.297-6.239,6.445-9.586,9.432"/&gt; &lt;line x1="398.202" y1="499.295" x2="406.221" y2="508.277"/&gt; &lt;line x1="419.886" y1="494.389" x2="415.33" y2="490.453"/&gt; &lt;path d="M415.33,490.453 c-2.04,2.361-4.155,4.655-6.343,6.879"/&gt; &lt;line x1="408.986" y1="497.332" x2="413.277" y2="501.555"/&gt; &lt;line x1="391.302" y1="512.611" x2="387.747" y2="507.752"/&gt; &lt;path d="M387.747,507.752 c-3.62,2.648-7.367,5.119-11.227,7.403"/&gt; &lt;line x1="376.521" y1="515.155" x2="382.652" y2="525.517"/&gt; &lt;line x1="398.742" y1="514.529" x2="395.032" y2="509.788"/&gt; &lt;path d="M395.033,509.788 c-2.457,1.923-4.977,3.765-7.553,5.523"/&gt; &lt;line x1="387.48" y1="515.312" x2="390.875" y2="520.283"/&gt; &lt;line x1="266.181" y1="432.741" x2="292.727" y2="408.247"/&gt; &lt;line x1="264.506" y1="439.615" x2="268.655" y2="435.253"/&gt; &lt;path d="M268.655,435.254 c-1.704-1.621-3.3-3.352-4.779-5.181"/&gt; &lt;line x1="263.876" y1="430.074" x2="188.989" y2="490.65"/&gt; &lt;line x1="263.589" y1="446.856" x2="267.444" y2="442.233"/&gt; &lt;path d="M267.445,442.233 c-2.016-1.682-3.921-3.493-5.701-5.423"/&gt; &lt;line x1="261.744" y1="436.811" x2="195.36" y2="498.025"/&gt; &lt;line x1="263.495" y1="454.411" x2="267.037" y2="449.544"/&gt; &lt;path d="M267.037,449.544 c-2.357-1.716-4.599-3.585-6.71-5.596"/&gt; &lt;line x1="260.327" y1="443.948" x2="202.196" y2="504.973"/&gt; &lt;line x1="264.31" y1="462.231" x2="267.517" y2="457.137"/&gt; &lt;path d="M267.517,457.137 c-2.743-1.727-5.366-3.635-7.852-5.714"/&gt; &lt;line x1="259.665" y1="451.423" x2="209.468" y2="511.464"/&gt; &lt;line x1="266.184" y1="470.282" x2="269.028" y2="464.976"/&gt; &lt;path d="M269.028,464.976 c-3.209-1.72-6.294-3.662-9.233-5.812"/&gt; &lt;line x1="259.795" y1="459.164" x2="217.144" y2="517.471"/&gt; &lt;line x1="269.401" y1="478.551" x2="271.841" y2="473.048"/&gt; &lt;path d="M271.841,473.048 c-3.841-1.703-7.549-3.69-11.093-5.946"/&gt; &lt;line x1="260.749" y1="467.102" x2="225.193" y2="522.967"/&gt; &lt;line x1="274.551" y1="487.041" x2="276.517" y2="481.352"/&gt; &lt;path d="M276.517,481.352 c-4.822-1.666-9.495-3.737-13.968-6.192"/&gt; &lt;line x1="262.549" y1="475.158" x2="233.582" y2="527.931"/&gt; &lt;line x1="282.87" y1="495.692" x2="284.231" y2="489.828"/&gt; &lt;path d="M284.231,489.828 c-6.551-1.521-12.924-3.723-19.016-6.569"/&gt; &lt;line x1="265.215" y1="483.259" x2="242.273" y2="532.342"/&gt; &lt;line x1="296.962" y1="503.982" x2="297.464" y2="497.983"/&gt; &lt;path d="M297.465,497.983 c-9.84-0.824-19.509-3.067-28.707-6.66"/&gt; &lt;line x1="268.758" y1="491.323" x2="251.232" y2="536.182"/&gt; &lt;line x1="314.674" y1="510.051" x2="314.217" y2="504.048"/&gt; &lt;path d="M314.218,504.048 c-11.507,0.875-23.079-0.094-34.281-2.869"/&gt; &lt;line x1="279.937" y1="501.179" x2="271.249" y2="536.239"/&gt; &lt;line x1="330.921" y1="513.793" x2="329.676" y2="507.902"/&gt; &lt;path d="M329.675,507.903 c-9.905,2.096-20.046,2.866-30.155,2.293"/&gt; &lt;line x1="299.521" y1="510.196" x2="298.498" y2="528.228"/&gt; &lt;line x1="339.872" y1="517.798" x2="338.259" y2="511.998"/&gt; &lt;path d="M338.259,511.998 c-4.854,1.35-9.788,2.394-14.772,3.126"/&gt; &lt;line x1="323.485" y1="515.123" x2="327.856" y2="544.904"/&gt; &lt;line x1="349.163" y1="521.209" x2="347.201" y2="515.518"/&gt; &lt;path d="M347.201,515.518 c-4.84,1.669-9.776,3.042-14.784,4.111"/&gt; &lt;line x1="332.418" y1="519.629" x2="337.449" y2="543.177"/&gt; &lt;line x1="358.468" y1="524.134" x2="356.187" y2="518.562"/&gt; &lt;path d="M356.187,518.562 c-4.632,1.897-9.368,3.529-14.186,4.891"/&gt; &lt;line x1="342.001" y1="523.453" x2="346.91" y2="540.833"/&gt; &lt;line x1="367.178" y1="526.889" x2="364.629" y2="521.435"/&gt; &lt;path d="M364.629,521.435 c-4.063,1.899-8.218,3.601-12.445,5.096"/&gt; &lt;line x1="352.184" y1="526.53" x2="356.199" y2="537.882"/&gt; &lt;line x1="374.108" y1="530.207" x2="371.385" y2="524.839"/&gt; &lt;path d="M371.384,524.839 c-2.782,1.412-5.608,2.732-8.477,3.962"/&gt; &lt;line x1="362.907" y1="528.801" x2="365.278" y2="534.334"/&gt; &lt;line x1="306" y1="534.46" x2="306" y2="528.44"/&gt; &lt;path d="M306,528.44 c-5.006,0-10.007-0.284-14.981-0.851"/&gt; &lt;line x1="291.019" y1="527.59" x2="288.976" y2="545.534"/&gt; &lt;line x1="313.017" y1="540.31" x2="312.725" y2="534.297"/&gt; &lt;path d="M312.724,534.297 c-4.479,0.218-8.968,0.218-13.448,0"/&gt; &lt;line x1="299.276" y1="534.297" x2="298.691" y2="546.322"/&gt; &lt;line x1="318.173" y1="546.007" x2="317.686" y2="540.007"/&gt; &lt;path d="M317.686,540.007 c-3.11,0.252-6.227,0.404-9.346,0.454"/&gt; &lt;line x1="308.34" y1="540.461" x2="308.437" y2="546.48"/&gt; &lt;line x1="279.333" y1="544.118" x2="280.4" y2="538.193"/&gt; &lt;path d="M280.399,538.193 c-6.143-1.105-12.207-2.608-18.155-4.499"/&gt; &lt;line x1="262.244" y1="533.695" x2="260.421" y2="539.432"/&gt; &lt;line x1="269.801" y1="542.082" x2="271.249" y2="536.239"/&gt; &lt;line x1="187.417" y1="454.978" x2="289.83" y2="404.042"/&gt; &lt;line x1="186.845" y1="466.521" x2="192.025" y2="463.454"/&gt; &lt;path d="M192.025,463.454 c-3.279-5.54-6.149-11.311-8.588-17.268"/&gt; &lt;line x1="183.437" y1="446.187" x2="172.295" y2="450.749"/&gt; &lt;line x1="185.384" y1="475.538" x2="190.41" y2="472.224"/&gt; &lt;path d="M190.41,472.224 c-2.469-3.744-4.755-7.606-6.849-11.573"/&gt; &lt;line x1="183.561" y1="460.65" x2="172.914" y2="466.272"/&gt; &lt;line x1="183.107" y1="482.877" x2="188.023" y2="479.402"/&gt; &lt;path d="M188.023,479.402 c-1.801-2.549-3.519-5.153-5.151-7.812"/&gt; &lt;line x1="182.872" y1="471.59" x2="177.742" y2="474.74"/&gt; &lt;line x1="168.644" y1="457.511" x2="174.138" y2="455.051"/&gt; &lt;path d="M174.138,455.05 c-1.275-2.847-2.458-5.734-3.546-8.658"/&gt; &lt;line x1="170.592" y1="446.391" x2="164.95" y2="448.491"/&gt; &lt;line x1="170.597" y1="424.934" x2="288.339" y2="399.773"/&gt; &lt;line x1="166.343" y1="433.018" x2="172.162" y2="431.476"/&gt; &lt;path d="M172.162,431.475 c-1.149-4.336-2.087-8.724-2.81-13.15"/&gt; &lt;line x1="169.352" y1="418.324" x2="157.468" y2="420.265"/&gt; &lt;line x1="161.849" y1="439.25" x2="167.614" y2="437.521"/&gt; &lt;path d="M167.615,437.521 c-0.897-2.988-1.696-6.005-2.397-9.045"/&gt; &lt;line x1="165.217" y1="428.476" x2="159.351" y2="429.828"/&gt; &lt;line x1="156.21" y1="410.6" x2="282.034" y2="398.336"/&gt; &lt;path d="M282.034,398.336 c-0.364-3.732,0.149-7.497,1.497-10.996"/&gt; &lt;line x1="283.531" y1="387.34" x2="277.914" y2="385.175"/&gt; &lt;line x1="182.059" y1="371.086" x2="276.49" y2="390.068"/&gt; &lt;path d="M276.49,390.068 c0.672-3.342,1.907-6.546,3.652-9.475"/&gt; &lt;line x1="280.142" y1="380.593" x2="274.97" y2="377.512"/&gt; &lt;line x1="174.293" y1="382.085" x2="180.28" y2="382.717"/&gt; &lt;path d="M180.28,382.718 c0.825-7.81,2.376-15.526,4.633-23.048"/&gt; &lt;line x1="184.913" y1="359.67" x2="161.849" y2="352.75"/&gt; &lt;line x1="167.704" y1="389.276" x2="173.716" y2="389.568"/&gt; &lt;path d="M173.716,389.568 c0.243-5,0.77-9.982,1.576-14.922"/&gt; &lt;line x1="175.293" y1="374.646" x2="157.469" y2="371.734"/&gt; &lt;line x1="161.52" y1="396" x2="167.54" y2="396"/&gt; &lt;path d="M167.54,396 c0-4.485,0.218-8.968,0.653-13.432"/&gt; &lt;line x1="168.193" y1="382.568" x2="156.21" y2="381.4"/&gt; &lt;line x1="155.579" y1="400.873" x2="161.596" y2="400.679"/&gt; &lt;path d="M161.596,400.679 c-0.101-3.118-0.101-6.239,0-9.357"/&gt; &lt;line x1="161.596" y1="391.321" x2="155.579" y2="391.126"/&gt; &lt;line x1="159.351" y1="362.171" x2="182.815" y2="367.584"/&gt; &lt;line x1="164.95" y1="343.509" x2="272.148" y2="383.402"/&gt; &lt;path d="M272.148,383.402 c1.525-4.098,3.781-7.885,6.659-11.176"/&gt; &lt;line x1="278.807" y1="372.226" x2="274.275" y2="368.264"/&gt; &lt;line x1="184.624" y1="329.375" x2="269.06" y2="375.723"/&gt; &lt;path d="M269.059,375.723 c2.937-5.351,7.001-9.999,11.912-13.625"/&gt; &lt;line x1="280.971" y1="362.098" x2="277.395" y2="357.255"/&gt; &lt;line x1="176.12" y1="332.711" x2="181.531" y2="335.348"/&gt; &lt;path d="M181.531,335.348 c1.965-4.032,4.124-7.966,6.471-11.789"/&gt; &lt;line x1="188.002" y1="323.559" x2="177.741" y2="317.26"/&gt; &lt;line x1="168.644" y1="334.489" x2="174.138" y2="336.95"/&gt; &lt;path d="M174.138,336.95 c1.275-2.847,2.642-5.653,4.099-8.412"/&gt; &lt;line x1="178.237" y1="328.538" x2="172.913" y2="325.728"/&gt; &lt;line x1="183.107" y1="309.123" x2="266.674" y2="368.199"/&gt; &lt;path d="M266.674,368.199 c5.972-8.448,14.506-14.748,24.337-17.968"/&gt; &lt;line x1="291.012" y1="350.231" x2="289.138" y2="344.511"/&gt; &lt;line x1="196.67" y1="301.546" x2="265.001" y2="360.58"/&gt; &lt;path d="M265.001,360.58 c13.116-15.182,33.548-21.873,53.103-17.391"/&gt; &lt;line x1="318.104" y1="343.189" x2="319.45" y2="337.321"/&gt; &lt;line x1="188.988" y1="301.351" x2="193.668" y2="305.136"/&gt; &lt;path d="M193.669,305.136 c1.962-2.426,4.002-4.787,6.117-7.081"/&gt; &lt;line x1="199.786" y1="298.056" x2="195.361" y2="293.975"/&gt; &lt;line x1="285.958" y1="295.642" x2="294.21" y2="336.966"/&gt; &lt;path d="M294.211,336.966 c16.877-3.37,34.389,0.644,48.113,11.028"/&gt; &lt;line x1="342.324" y1="347.994" x2="345.956" y2="343.193"/&gt; &lt;line x1="262.122" y1="290.371" x2="266.741" y2="301.49"/&gt; &lt;path d="M266.74,301.49 c12.427-5.162,25.751-7.823,39.208-7.83"/&gt; &lt;line x1="305.948" y1="293.66" x2="305.945" y2="287.64"/&gt; &lt;line x1="243.632" y1="293.013" x2="246.75" y2="298.162"/&gt; &lt;path d="M246.75,298.162 c9.855-5.968,20.555-10.413,31.738-13.184"/&gt; &lt;line x1="278.489" y1="284.978" x2="269.801" y2="249.918"/&gt; &lt;line x1="215.482" y1="291.226" x2="227.289" y2="304.892"/&gt; &lt;path d="M227.289,304.892 c10.229-8.837,21.873-15.888,34.443-20.858"/&gt; &lt;line x1="261.732" y1="284.033" x2="259.519" y2="278.436"/&gt; &lt;line x1="202.197" y1="287.027" x2="210.5" y2="295.745"/&gt; &lt;path d="M210.501,295.745 c3.248-3.094,6.644-6.028,10.176-8.792"/&gt; &lt;line x1="220.677" y1="286.954" x2="216.967" y2="282.212"/&gt; &lt;line x1="209.468" y1="280.537" x2="213.329" y2="285.155"/&gt; &lt;path d="M213.329,285.155 c2.394-2.001,4.851-3.924,7.369-5.766"/&gt; &lt;line x1="220.699" y1="279.389" x2="217.145" y2="274.53"/&gt; &lt;line x1="248.951" y1="276.477" x2="251.544" y2="281.91"/&gt; &lt;path d="M251.544,281.91 c5.237-2.5,10.639-4.636,16.17-6.393"/&gt; &lt;line x1="267.714" y1="275.517" x2="260.421" y2="252.568"/&gt; &lt;line x1="237.418" y1="275.718" x2="240.4" y2="280.948"/&gt; &lt;path d="M240.4,280.948 c5.592-3.188,11.409-5.965,17.404-8.307"/&gt; &lt;line x1="257.804" y1="272.641" x2="251.232" y2="255.819"/&gt; &lt;line x1="225.193" y1="269.033" x2="231.659" y2="279.19"/&gt; &lt;path d="M231.658,279.19 c3.784-2.408,7.683-4.631,11.682-6.661"/&gt; &lt;line x1="243.34" y1="272.53" x2="240.616" y2="267.162"/&gt; &lt;line x1="233.582" y1="264.069" x2="236.479" y2="269.346"/&gt; &lt;path d="M236.479,269.346 c2.735-1.501,5.518-2.913,8.344-4.234"/&gt; &lt;line x1="244.822" y1="265.111" x2="242.273" y2="259.658"/&gt; &lt;line x1="288.113" y1="258.7" x2="292.001" y2="288.548"/&gt; &lt;path d="M292.001,288.548 c9.257-1.206,18.631-1.211,27.89-0.014"/&gt; &lt;line x1="319.89" y1="288.534" x2="320.662" y2="282.564"/&gt; &lt;line x1="279.333" y1="247.881" x2="281.466" y2="259.731"/&gt; &lt;path d="M281.466,259.731 c4.414-0.795,8.865-1.374,13.335-1.737"/&gt; &lt;line x1="294.801" y1="257.994" x2="294.314" y2="251.994"/&gt; &lt;line x1="288.976" y1="246.466" x2="289.657" y2="252.447"/&gt; &lt;path d="M289.657,252.447 c3.1-0.353,6.21-0.605,9.326-0.757"/&gt; &lt;line x1="298.984" y1="251.69" x2="298.692" y2="245.678"/&gt; &lt;line x1="313.017" y1="251.69" x2="311.555" y2="281.754"/&gt; &lt;path d="M311.555,281.755 c6.093,0.296,12.152,1.079,18.121,2.342"/&gt; &lt;line x1="329.675" y1="284.097" x2="330.921" y2="278.207"/&gt; &lt;line x1="308.438" y1="245.52" x2="308.34" y2="251.539"/&gt; &lt;path d="M308.34,251.539 c3.119,0.051,6.235,0.202,9.346,0.454"/&gt; &lt;line x1="317.686" y1="251.993" x2="318.173" y2="245.993"/&gt; &lt;line x1="327.856" y1="247.096" x2="323.486" y2="276.876"/&gt; &lt;path d="M323.485,276.876 c4.985,0.732,9.919,1.776,14.773,3.126"/&gt; &lt;line x1="338.259" y1="280.002" x2="339.872" y2="274.202"/&gt; &lt;line x1="337.449" y1="248.823" x2="332.418" y2="272.371"/&gt; &lt;path d="M332.418,272.371 c5.007,1.07,9.943,2.443,14.784,4.111"/&gt; &lt;line x1="347.201" y1="276.482" x2="349.163" y2="270.792"/&gt; &lt;line x1="346.91" y1="251.167" x2="342.001" y2="268.547"/&gt; &lt;path d="M342.001,268.547 c4.817,1.361,9.553,2.993,14.187,4.89"/&gt; &lt;line x1="356.187" y1="273.437" x2="358.468" y2="267.866"/&gt; &lt;line x1="356.199" y1="254.119" x2="352.184" y2="265.47"/&gt; &lt;path d="M352.184,265.469 c4.229,1.496,8.382,3.197,12.445,5.096"/&gt; &lt;line x1="364.629" y1="270.565" x2="367.178" y2="265.111"/&gt; &lt;line x1="365.278" y1="257.666" x2="362.907" y2="263.199"/&gt; &lt;path d="M362.907,263.199 c2.868,1.229,5.695,2.55,8.477,3.962"/&gt; &lt;line x1="371.384" y1="267.161" x2="374.108" y2="261.793"/&gt; &lt;line x1="383.574" y1="274.112" x2="341.555" y2="340.135"/&gt; &lt;path d="M341.555,340.135 c3.018,1.92,5.874,4.082,8.542,6.463"/&gt; &lt;line x1="350.097" y1="346.598" x2="354.105" y2="342.106"/&gt; &lt;line x1="382.652" y1="266.483" x2="379.587" y2="271.664"/&gt; &lt;path d="M379.587,271.664 c2.685,1.589,5.317,3.264,7.894,5.024"/&gt; &lt;line x1="387.48" y1="276.688" x2="390.875" y2="271.717"/&gt; &lt;line x1="398.742" y1="277.471" x2="350.517" y2="339.106"/&gt; &lt;path d="M350.517,339.106 c2.458,1.923,4.788,4.003,6.976,6.227"/&gt; &lt;line x1="357.492" y1="345.333" x2="361.783" y2="341.111"/&gt; &lt;line x1="406.221" y1="283.723" x2="358.114" y2="337.616"/&gt; &lt;path d="M358.114,337.616 c2.521,2.251,4.896,4.662,7.104,7.22"/&gt; &lt;line x1="365.219" y1="344.836" x2="369.773" y2="340.9"/&gt; &lt;line x1="413.277" y1="290.446" x2="366.076" y2="336.89"/&gt; &lt;path d="M366.075,336.89 c2.553,2.594,4.935,5.35,7.13,8.252"/&gt; &lt;line x1="373.205" y1="345.142" x2="378.005" y2="341.509"/&gt; &lt;line x1="419.886" y1="297.611" x2="374.331" y2="336.967"/&gt; &lt;path d="M374.331,336.967 c2.548,2.949,4.902,6.06,7.047,9.313"/&gt; &lt;line x1="381.379" y1="346.279" x2="386.403" y2="342.964"/&gt; &lt;line x1="426.015" y1="305.189" x2="382.811" y2="337.881"/&gt; &lt;path d="M382.81,337.881 c2.506,3.312,4.795,6.782,6.854,10.389"/&gt; &lt;line x1="389.662" y1="348.27" x2="394.892" y2="345.287"/&gt; &lt;line x1="431.642" y1="313.148" x2="391.437" y2="339.661"/&gt; &lt;path d="M391.437,339.661 c2.424,3.676,4.608,7.505,6.54,11.463"/&gt; &lt;line x1="397.976" y1="351.124" x2="403.386" y2="348.484"/&gt; &lt;line x1="436.741" y1="321.455" x2="400.134" y2="342.328"/&gt; &lt;path d="M400.134,342.327 c2.3,4.035,4.339,8.213,6.103,12.509"/&gt; &lt;line x1="406.237" y1="354.836" x2="411.806" y2="352.55"/&gt; &lt;line x1="441.292" y1="330.074" x2="408.822" y2="345.896"/&gt; &lt;path d="M408.822,345.896 c2.131,4.372,3.979,8.876,5.537,13.484"/&gt; &lt;line x1="414.359" y1="359.38" x2="420.062" y2="357.453"/&gt; &lt;line x1="445.276" y1="338.97" x2="417.421" y2="350.375"/&gt; &lt;path d="M417.421,350.375 c1.909,4.663,3.523,9.441,4.835,14.306"/&gt; &lt;line x1="422.255" y1="364.681" x2="428.068" y2="363.115"/&gt; &lt;line x1="448.676" y1="348.104" x2="425.848" y2="355.768"/&gt; &lt;path d="M425.848,355.768 c1.629,4.854,2.962,9.801,3.991,14.816"/&gt; &lt;line x1="429.839" y1="370.584" x2="435.735" y2="369.374"/&gt; &lt;line x1="451.477" y1="357.44" x2="434.02" y2="362.067"/&gt; &lt;path d="M434.02,362.067 c1.283,4.839,2.29,9.746,3.017,14.699"/&gt; &lt;line x1="437.036" y1="376.766" x2="442.992" y2="375.892"/&gt; &lt;line x1="453.667" y1="366.938" x2="441.854" y2="369.263"/&gt; &lt;path d="M441.854,369.263 c0.866,4.401,1.519,8.841,1.953,13.305"/&gt; &lt;line x1="443.807" y1="382.568" x2="449.799" y2="381.984"/&gt; &lt;line x1="455.239" y1="376.557" x2="449.27" y2="377.335"/&gt; &lt;path d="M449.27,377.335 c0.402,3.094,0.706,6.2,0.908,9.313"/&gt; &lt;line x1="450.177" y1="386.648" x2="456.184" y2="386.258"/&gt;  &lt;text transform="matrix(1 0 0 1 460 399)"&gt;Spirochaetes&lt;/text&gt; &lt;text transform="matrix(0.9979 0.0647 -0.0647 0.9979 459.4824 408.9629)"&gt;Chlamydias&lt;/text&gt; &lt;text transform="matrix(0.9916 0.1292 -0.1292 0.9916 458.3223 418.8691)"&gt;Hyperthermophilic bacteria&lt;/text&gt; &lt;text transform="matrix(0.9812 0.1931 -0.1931 0.9812 456.5225 428.6816)"&gt;Cyanobacteria&lt;/text&gt; &lt;text transform="matrix(0.9666 0.2562 -0.2562 0.9666 454.0908 438.3564)"&gt;Low-GC Gram-positives&lt;/text&gt; &lt;text transform="matrix(0.948 0.3182 -0.3182 0.948 451.04 447.8545)"&gt;High-GC Gram-positives&lt;/text&gt; &lt;text transform="matrix(0.9254 0.3789 -0.3789 0.9254 447.377 457.1328)"&gt;Deinococcus/Thermus&lt;/text&gt; &lt;text transform="matrix(0.899 0.438 -0.438 0.899 443.124 466.1553)"&gt;Proteobacteria&lt;/text&gt; &lt;text transform="matrix(0.8687 0.4953 -0.4953 0.8687 438.2969 474.8857)"&gt;Crenarchaeota&lt;/text&gt; &lt;text transform="matrix(0.8348 0.5505 -0.5505 0.8348 432.9121 483.2842)"&gt;Euryarchaeota&lt;/text&gt; &lt;text transform="matrix(0.7974 0.6034 -0.6034 0.7974 426.9961 491.3164)"&gt;Haptophytes&lt;/text&gt; &lt;text transform="matrix(0.7567 0.6537 -0.6537 0.7567 420.5723 498.9473)"&gt;Brown algae&lt;/text&gt; &lt;text transform="matrix(0.7128 0.7014 -0.7014 0.7128 413.6689 506.1475)"&gt;Diatoms&lt;/text&gt; &lt;text transform="matrix(0.6659 0.746 -0.746 0.6659 406.3125 512.8848)"&gt;Oomycetes&lt;/text&gt; &lt;text transform="matrix(0.6162 0.7876 -0.7876 0.6162 398.5371 519.1328)"&gt;Dinoflagellates&lt;/text&gt; &lt;text transform="matrix(0.564 0.8258 -0.8258 0.564 390.373 524.8652)"&gt;Apicomplexans&lt;/text&gt; &lt;text transform="matrix(0.5093 0.8606 -0.8606 0.5093 381.8535 530.0566)"&gt;Ciliates&lt;/text&gt; &lt;text transform="matrix(0.4525 0.8917 -0.8917 0.4525 373.0166 534.6855)"&gt;Eudicots&lt;/text&gt; &lt;text transform="matrix(0.3939 0.9192 -0.9192 0.3939 363.8994 538.7324)"&gt;Monocots&lt;/text&gt; &lt;text transform="matrix(0.3336 0.9427 -0.9427 0.3336 354.5391 542.1807)"&gt;Magnoliids&lt;/text&gt; &lt;text transform="matrix(0.2718 0.9623 -0.9623 0.2718 344.9736 545.0166)"&gt;Star anise&lt;/text&gt; &lt;text transform="matrix(0.209 0.9779 -0.9779 0.209 335.2471 547.2266)"&gt;Water lilies&lt;/text&gt; &lt;text transform="matrix(0.1452 0.9894 -0.9894 0.1452 325.3965 548.8047)"&gt;Amborella&lt;/text&gt; &lt;text transform="matrix(0.0809 0.9967 -0.9967 0.0809 315.4658 549.7383)"&gt;Conifers&lt;/text&gt; &lt;text transform="matrix(0.0162 1 -1 0.0162 305.4932 550.0283)"&gt;Gnetophytes&lt;/text&gt; &lt;text transform="matrix(0.0486 -0.9988 0.9988 0.0486 300.2061 576.9326)"&gt;Ginkgo&lt;/text&gt; &lt;text transform="matrix(0.1131 -0.9936 0.9936 0.1131 288.2812 578.166)"&gt;Cycads&lt;/text&gt; &lt;text transform="matrix(0.1772 -0.9842 0.9842 0.1772 277.7676 569.7461)"&gt;Ferns&lt;/text&gt; &lt;text transform="matrix(0.2405 -0.9706 0.9706 0.2405 262.4902 584.0547)"&gt;Horsetails&lt;/text&gt; &lt;text transform="matrix(0.3028 -0.953 0.953 0.3028 247.9863 588.4688)"&gt;Whisk ferns&lt;/text&gt; &lt;text transform="matrix(0.3639 -0.9314 0.9314 0.3639 214.9072 637.4023)"&gt;Club mosses and relatives&lt;/text&gt; &lt;text transform="matrix(0.4234 -0.9059 0.9059 0.4234 226.5723 573.0205)"&gt;Hornworts&lt;/text&gt; &lt;text transform="matrix(0.4812 -0.8766 0.8766 0.4812 219.6104 559.6182)"&gt;Mosses&lt;/text&gt; &lt;text transform="matrix(0.5369 -0.8436 0.8436 0.5369 204.3682 561.2754)"&gt;Liverworts&lt;/text&gt; &lt;text transform="matrix(0.5904 -0.8071 0.8071 0.5904 196.835 550.3145)"&gt;Charales&lt;/text&gt; &lt;text transform="matrix(0.6414 -0.7672 0.7672 0.6414 170.3984 562.8711)"&gt;Coleochaetales&lt;/text&gt; &lt;text transform="matrix(0.6897 -0.7241 0.7241 0.6897 166.0898 547.2285)"&gt;Chlorophytes&lt;/text&gt; &lt;text transform="matrix(0.7351 -0.6779 0.6779 0.7351 165.416 529.7188)"&gt;Red Algae&lt;/text&gt; &lt;text transform="matrix(0.7775 -0.6289 0.6289 0.7775 146.1699 529.1445)"&gt;Glaucophytes&lt;/text&gt; &lt;text transform="matrix(0.8166 -0.5773 0.5773 0.8166 137.0703 519.0957)"&gt;Kinetoplastids&lt;/text&gt; &lt;text transform="matrix(0.8522 -0.5232 0.5232 0.8522 143.9443 499.0098)"&gt;Euglenids&lt;/text&gt; &lt;text transform="matrix(0.8843 -0.4669 0.4669 0.8843 111.9717 501.8438)"&gt;Heteroloboseans&lt;/text&gt; &lt;text transform="matrix(0.9127 -0.4087 0.4087 0.9127 120.1299 482.5234)"&gt;Parabasalids&lt;/text&gt; &lt;text transform="matrix(0.9372 -0.3488 0.3488 0.9372 114.9199 470.3105)"&gt;Diplomonads&lt;/text&gt; &lt;text transform="matrix(0.9578 -0.2874 0.2874 0.9578 102.8477 460.0859)"&gt;Foraminiferans&lt;/text&gt; &lt;text transform="matrix(0.9744 -0.2248 0.2248 0.9744 110.8174 444.1035)"&gt;Cercozoans&lt;/text&gt; &lt;text transform="matrix(0.9869 -0.1612 0.1612 0.9869 106.1396 431.6904)"&gt;Radiolarians&lt;/text&gt; &lt;text transform="matrix(0.9953 -0.097 0.097 0.9953 96.2861 419.4551)"&gt;Amoebozoans&lt;/text&gt; &lt;text transform="matrix(0.9995 -0.0324 0.0324 0.9995 110.1997 405.3457)"&gt;Club Fungi&lt;/text&gt; &lt;text transform="matrix(0.9995 0.0324 -0.0324 0.9995 113.0039 392.748)"&gt;Sac Fungi&lt;/text&gt; &lt;text transform="matrix(0.9953 0.097 -0.097 0.9953 36.9819 372.793)"&gt;Arbuscular Mycorrhizal Fungi&lt;/text&gt; &lt;text transform="matrix(0.9869 0.1612 -0.1612 0.9869 80.499 362.2012)"&gt;"Zygospore Fungi"&lt;/text&gt; &lt;text transform="matrix(0.9744 0.2248 -0.2248 0.9744 117.2637 355.542)"&gt;"Chytrids"&lt;/text&gt; &lt;text transform="matrix(0.9578 0.2874 -0.2874 0.9578 106.8696 339.3867)"&gt;Microsporidia&lt;/text&gt; &lt;text transform="matrix(0.9372 0.3488 -0.3488 0.9372 94.0825 320.3389)"&gt;Choanoflagellates&lt;/text&gt; &lt;text transform="matrix(0.9127 0.4087 -0.4087 0.9127 111.2891 312.0918)"&gt;Glass sponges&lt;/text&gt; &lt;text transform="matrix(0.8843 0.4669 -0.4669 0.8843 118.0127 300.1309)"&gt;Demosponges&lt;/text&gt; &lt;text transform="matrix(0.8522 0.5232 -0.5232 0.8522 104.1602 275.6064)"&gt;Calcareous sponges&lt;/text&gt; &lt;text transform="matrix(0.8166 0.5773 -0.5773 0.8166 141.772 283.5762)"&gt;Placozoans&lt;/text&gt; &lt;text transform="matrix(0.7775 0.6289 -0.6289 0.7775 145.5068 270.0371)"&gt;Ctenophores&lt;/text&gt; &lt;text transform="matrix(0.7351 0.6779 -0.6779 0.7351 159.8779 265.335)"&gt;Cnidarians&lt;/text&gt; &lt;text transform="matrix(0.6897 0.7241 -0.7241 0.6897 169.332 256.874)"&gt;Bryozoans&lt;/text&gt; &lt;text transform="matrix(0.6414 0.7672 -0.7672 0.6414 179.2651 249.0879)"&gt;Flatworms&lt;/text&gt; &lt;text transform="matrix(0.5904 0.8071 -0.8071 0.5904 194.9448 249.2637)"&gt;Rotifers&lt;/text&gt; &lt;text transform="matrix(0.5369 0.8436 -0.8436 0.5369 190.7168 220.4482)"&gt;Ribbon worms&lt;/text&gt; &lt;text transform="matrix(0.4812 0.8766 -0.8766 0.4812 205.6895 219.4912)"&gt;Brachiopods&lt;/text&gt; &lt;text transform="matrix(0.4234 0.9059 -0.9059 0.4234 221.5596 222.4268)"&gt;Phoronids&lt;/text&gt; &lt;text transform="matrix(0.3639 0.9314 -0.9314 0.3639 234.792 221.9814)"&gt;Annelids&lt;/text&gt; &lt;text transform="matrix(0.3029 0.953 -0.953 0.3029 245.9033 216.7842)"&gt;Mollusks&lt;/text&gt; &lt;text transform="matrix(0.2405 0.9706 -0.9706 0.2405 253.5391 196.7705)"&gt;Arrow worms&lt;/text&gt; &lt;text transform="matrix(0.1772 0.9842 -0.9842 0.1772 269.0264 207.5703)"&gt;Priapulids&lt;/text&gt; &lt;text transform="matrix(0.1131 0.9936 -0.9936 0.1131 280.1699 195.6367)"&gt;Kinorhynchs&lt;/text&gt; &lt;text transform="matrix(0.0486 0.9988 -0.9988 0.0486 293.3398 197.3809)"&gt;Loriciferans&lt;/text&gt; &lt;text transform="matrix(0.0162 -1 1 0.0162 311.4941 242.0679)"&gt;Horsehair worms&lt;/text&gt; &lt;text transform="matrix(0.0809 -0.9967 0.9967 0.0809 321.4463 242.7476)"&gt;Nematodes&lt;/text&gt; &lt;text transform="matrix(0.1452 -0.9894 0.9894 0.1452 331.333 244.0684)"&gt;Tardigrades&lt;/text&gt; &lt;text transform="matrix(0.209 -0.9779 0.9779 0.209 341.1162 246.0269)"&gt;Onychophorans&lt;/text&gt; &lt;text transform="matrix(0.2718 -0.9623 0.9623 0.2718 350.75 248.6133)"&gt;Chelicerates&lt;/text&gt; &lt;text transform="matrix(0.3336 -0.9427 0.9427 0.3336 360.1953 251.8208)"&gt;Myriapods&lt;/text&gt; &lt;text transform="matrix(0.3939 -0.9192 0.9192 0.3939 369.4131 255.6309)"&gt;Crustaceans&lt;/text&gt; &lt;text transform="matrix(0.4525 -0.8917 0.8917 0.4525 378.3672 260.0298)"&gt;Hexapods&lt;/text&gt; &lt;text transform="matrix(0.5093 -0.8606 0.8606 0.5093 387.0176 265.0005)"&gt;Echinoderms&lt;/text&gt; &lt;text transform="matrix(0.564 -0.8258 0.8258 0.564 395.3271 270.5176)"&gt;Hemichordates&lt;/text&gt; &lt;text transform="matrix(0.6162 -0.7876 0.7876 0.6162 403.2617 276.563)"&gt;Cephalochordates&lt;/text&gt; &lt;text transform="matrix(0.6659 -0.746 0.746 0.6659 410.79 283.1094)"&gt;Urochordates&lt;/text&gt; &lt;text transform="matrix(0.7128 -0.7014 0.7014 0.7128 417.876 290.1294)"&gt;Hagfishes&lt;/text&gt; &lt;text transform="matrix(0.7567 -0.6537 0.6537 0.7567 424.4951 297.5928)"&gt;Lampreys&lt;/text&gt; &lt;text transform="matrix(0.7974 -0.6034 0.6034 0.7974 430.6172 305.4692)"&gt;Chondrichthyans&lt;/text&gt; &lt;text transform="matrix(0.8348 -0.5505 0.5505 0.8348 436.2148 313.7261)"&gt;Ray-finned fishes&lt;/text&gt; &lt;text transform="matrix(0.8687 -0.4953 0.4953 0.8687 441.2686 322.3276)"&gt;Lobe-finned fishes&lt;/text&gt; &lt;text transform="matrix(0.899 -0.438 0.438 0.899 445.7529 331.2373)"&gt;Lungfishes&lt;/text&gt; &lt;text transform="matrix(0.9254 -0.3789 0.3789 0.9254 449.6514 340.4199)"&gt;Amphibians&lt;/text&gt; &lt;text transform="matrix(0.948 -0.3182 0.3182 0.948 452.9482 349.834)"&gt;Mammals&lt;/text&gt; &lt;text transform="matrix(0.9666 -0.2562 0.2562 0.9666 455.6289 359.4434)"&gt;Turtles&lt;/text&gt; &lt;text transform="matrix(0.9812 -0.1931 0.1931 0.9812 457.6816 369.2051)"&gt;Lepidosaurs&lt;/text&gt; &lt;text transform="matrix(0.9916 -0.1292 0.1292 0.9916 459.0967 379.0801)"&gt;Crocodilians&lt;/text&gt; &lt;text transform="matrix(0.9979 -0.0647 0.0647 0.9979 459.8711 389.0254)"&gt;Birds&lt;/text&gt;&lt;/g&gt;&lt;/svg&gt;&lt;br /&gt;
&lt;br /&gt;
Unfortunately Blogger intersperses it with &lt;code&gt;&amp;lt;br&amp;gt;&lt;/code&gt; tags if I leave the new-lines in, so &lt;a href="http://github.com/johan/tree-of-life.svg/raw/69c07bf0262cad6bc221ad94f4936fa7f8a850da/tree-of-life.svg"&gt;see github for a cleaner version&lt;/a&gt;. No luck with my current set of browsers, with at least this doctype and HTML version. It does degrade to showing the text content of all the families, though, which a PDF wouldn't.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15626356-5038860889973985855?l=ecmanaut.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/To46WEO18tHvx3pHOqGh_5sfD4Q/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/To46WEO18tHvx3pHOqGh_5sfD4Q/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/To46WEO18tHvx3pHOqGh_5sfD4Q/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/To46WEO18tHvx3pHOqGh_5sfD4Q/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/xxBcs/~4/8Mou61rsnQ8" height="1" width="1"/&gt;</content><link rel="related" href="http://github.com/johan/tree-of-life.svg/commits/" title="Optimizing SVGs" /><link rel="replies" type="application/atom+xml" href="http://ecmanaut.blogspot.com/feeds/5038860889973985855/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=15626356&amp;postID=5038860889973985855" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/15626356/posts/default/5038860889973985855?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/15626356/posts/default/5038860889973985855?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/xxBcs/~3/8Mou61rsnQ8/optimizing-svgs.html" title="Optimizing SVGs" /><author><name>Johan Sundström</name><uri>http://www.blogger.com/profile/04076097346172610543</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/_mSA70aKq5R0/TD6WVXq0LwI/AAAAAAAAAKY/nS977Qbv14w/s72-c/tree-of-life.jpg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://ecmanaut.blogspot.com/2010/07/optimizing-svgs.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEEHQ3Y6fip7ImA9WxFbGUo.&quot;"><id>tag:blogger.com,1999:blog-15626356.post-2647551811751504638</id><published>2010-07-11T18:49:00.000-07:00</published><updated>2010-07-12T16:17:12.816-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-07-12T16:17:12.816-07:00</app:edited><title>Google styleguides for JSON APIs</title><content type="html">I just eyed through Google's dos and don'ts &lt;a href="http://google-styleguide.googlecode.com/svn/trunk/jsoncstyleguide.html"&gt;style guide for when exporting JSON APIs&lt;/a&gt;. Overall it's pretty good, ranging from the very basics of "abide by the JSON specification" (though stated at depth, presumably for the JSON illiterate, with all implications of what data types are available, what syntax is legal and the like) to how to do naming, grouping of properties, how to introduce and deprecate identifiers, what to leave out, how to represent what kinds of data, and so on.&lt;br /&gt;
&lt;br /&gt;
It of course doesn't guarantee that the outcome will be good APIs (the JSON exported by Google Spreadsheets, at least in the incarnations I peeked at some years ago, was an absolutely horrible auto-translation from XML that even mangled parts of the data due to its imperfect representation of a data grid, for instance), but it prevents does protect against many needless pitfalls.&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;Time&lt;/h2&gt;&lt;br /&gt;
Not all of its tips are great, though. The rest of this post is a rant about time, and how it's more complicated than you think (unless you have ever run across this). I specifically want to warn about its recommendation on &lt;a href="http://google-styleguide.googlecode.com/svn/trunk/jsoncstyleguide.html#Time_Duration_Property_Values"&gt;Time &lt;i&gt;Duration&lt;/i&gt; Property Values&lt;/a&gt; (my emphasis that it's talking about &lt;i&gt;amounts&lt;/i&gt; of time rather than timestamps, which ISO 8601 is great for), which it suggests to be encoded ISO 8601 style. Example (comments are of course not part of the output):&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;&lt;code&gt;{
  // three years, six months, four days, twelve hours,
  // thirty minutes, and five seconds
  "duration": "P3Y6M4DT12H30M5S"
}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;em&gt;Don't do this!&lt;/em&gt;&lt;br /&gt;
&lt;br /&gt;
That is a daft idea and/or example. Think about it for a moment. If you truly want to convey the length of a duration for a period of three years, six months, four days, twelve hours, thirty minutes and five seconds, the total number of seconds of that should be computable with perfect precision, right? To this application, after all (whatever it is) -- the number of days, hours, minutes -- and even those last five seconds -- are significant, so we should get them right.&lt;br /&gt;
&lt;br /&gt;
Here be dragons. Human readouts of time durations like the one above don't convey that information. If you talk about durations, you have to pick &lt;i&gt;one&lt;/i&gt;, &lt;i&gt;well-defined&lt;/i&gt; unit of time (or -- less usefully -- a number of units that translate to each other by well-defined rules, requiring no additional data inputs) of time, and stick to that one.&lt;br /&gt;
&lt;br /&gt;
I'd recommend picking either days, seconds, milliseconds or nanoseconds as your (one!) unit of choice, dependent on what kind of duration you represent and what kinds of likely uses it has. Declare the unit (so the property name suggests the unit, if you're kind) and stick to integers.&lt;br /&gt;
&lt;br /&gt;
Because the number of seconds in three years, six months, four days, twelve hours, thirty minutes and five seconds depends on when you start counting, and/or what you mean by "year", "month", "day" and "hour" (&lt;a href="http://www.youtube.com/watch?v=IhqzW97_47w&amp;hd=1"&gt;earth-centric time is complicated&lt;/a&gt; -- &lt;a href="http://jwz.livejournal.com/585203.html"&gt;some minutes even have more than 60 seconds&lt;/a&gt;).&lt;br /&gt;
&lt;br /&gt;
Typically, it's in reference to some specific &lt;i&gt;reference time&lt;/i&gt;, from which to increment the year by 3, the month number by six, the date by four days, and finally add another 12h, 30m and 5s. But we didn't get a reference time; we just have a duration. It's like a vector denoting a coordinate in a coordinate system. You can't tell what it points &lt;i&gt;at&lt;/i&gt;, without knowing where it points &lt;i&gt;from&lt;/i&gt;.&lt;br /&gt;
&lt;br /&gt;
And humans happily think up some well-defined case like counting from midnight this January 1st, finds that it works out to becoming 2013-06-04 12:30:05 after adding, and maybe even computes it to 108041406 seconds total and believes it's a well-defined amount of time. It just isn't; those six months only just turned out to be 182 days because 2013 isn't a leap year. If we had started counting from 2009 and ended up on 2012-06-04 12:30:05, they would have wound up 183. And if we had started counting from March 1st instead of January 1st, they would have been 185. No matter how you see that, we've suddenly got all this seemingly second-precision duration -- with a fuzz margin of plus or minus a day and a half -- a range of more than 250,000 seconds, which compares most unfavourably to advertised second-precision.&lt;br /&gt;
&lt;br /&gt;
And if you decide that &lt;i&gt;your&lt;/i&gt; years are a special 365 * 24 * 60 * 60 seconds long, then ten years from now won't be July 11th, but July 8:th. Humans might disagree.&lt;br /&gt;
&lt;br /&gt;
So if you have want to represent a duration of time, and you want the API consumer to know how long that duration is, pick a unit and pass an integer. And if, say, your first API version had a timestamp of the start of something and you want API v2 consumers to be able to tell how long after that it completed, pick a unit and pass an integer. And if you have good reason to believe that the consumer (maybe a human) is interested in the end time, pass start and stop timestamps. Programs consuming your JSON will have access to date functions that can compute the amount of time between them, or what date and time it will be after a fix number of given time units from a reference time.&lt;br /&gt;
&lt;br /&gt;
Thank you for taking your time to indulge in thinking and talking about time over JSON APIs.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15626356-2647551811751504638?l=ecmanaut.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/JEKUOUYcpbBpspD-JvxyrK9cNqo/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/JEKUOUYcpbBpspD-JvxyrK9cNqo/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/JEKUOUYcpbBpspD-JvxyrK9cNqo/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/JEKUOUYcpbBpspD-JvxyrK9cNqo/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/xxBcs/~4/o-kVx2kg7fc" height="1" width="1"/&gt;</content><link rel="related" href="http://google-styleguide.googlecode.com/svn/trunk/jsoncstyleguide.html" title="Google styleguides for JSON APIs" /><link rel="replies" type="application/atom+xml" href="http://ecmanaut.blogspot.com/feeds/2647551811751504638/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=15626356&amp;postID=2647551811751504638" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/15626356/posts/default/2647551811751504638?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/15626356/posts/default/2647551811751504638?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/xxBcs/~3/o-kVx2kg7fc/google-styleguides-for-json-apis.html" title="Google styleguides for JSON APIs" /><author><name>Johan Sundström</name><uri>http://www.blogger.com/profile/04076097346172610543</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>2</thr:total><feedburner:origLink>http://ecmanaut.blogspot.com/2010/07/google-styleguides-for-json-apis.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkMDQ3Y8fip7ImA9WhZSGU8.&quot;"><id>tag:blogger.com,1999:blog-15626356.post-5360422400158608816</id><published>2010-07-09T22:22:00.000-07:00</published><updated>2011-04-04T07:47:52.876-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-04-04T07:47:52.876-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="tools" /><category scheme="http://www.blogger.com/atom/ns#" term="mac" /><title>List hardlinks on HFS volumes</title><content type="html">This one goes out to all of you mac users out there.&lt;br /&gt;
&lt;br /&gt;
I recently made a little hack &lt;a href="http://gist.github.com/raw/470463/e504347e17dfa83f9f920e13dd9accde6e65fa57/hardlinks.zsh"&gt;hardlinks&lt;/a&gt; that takes a path (or inode) of a hardlinked file and lists the paths of all of its clones (including its own), provided it lives on an HFS volume. Usage is simple:&lt;br /&gt;
&lt;br /&gt;
&lt;code&gt;sudo hardlinks &lt;em&gt;path&lt;/em&gt;&lt;/code&gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
&lt;code&gt;sudo hardlinks -c &lt;em&gt;inode&lt;/em&gt;&lt;/code&gt;&lt;br /&gt;
&lt;br /&gt;
You need to have the &lt;a href="http://www.osxbook.com/software/hfsdebug/"&gt;hfsdebug-lite&lt;/a&gt; binary Amit Singh provides installed for it to work, and if you're on a modern mac, you need to install the Rosetta tools from your MacOS X install disk to get hfsdebug to run. (That sudo is needed for hfsdebug to access the raw device of the volume -- after that, hfsdebug drops privileges to the nobody user.)&lt;br /&gt;
&lt;br /&gt;
Source code:&lt;br /&gt;
&lt;br /&gt;
&lt;script src="http://gist.github.com/470463.js"&gt;&lt;/script&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15626356-5360422400158608816?l=ecmanaut.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/9SJhp6VjVO2VV8kbTAeqvABB9SU/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/9SJhp6VjVO2VV8kbTAeqvABB9SU/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/9SJhp6VjVO2VV8kbTAeqvABB9SU/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/9SJhp6VjVO2VV8kbTAeqvABB9SU/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/xxBcs/~4/IeW2DZZoF3Y" height="1" width="1"/&gt;</content><link rel="related" href="http://gist.github.com/470463" title="List hardlinks on HFS volumes" /><link rel="replies" type="application/atom+xml" href="http://ecmanaut.blogspot.com/feeds/5360422400158608816/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=15626356&amp;postID=5360422400158608816" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/15626356/posts/default/5360422400158608816?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/15626356/posts/default/5360422400158608816?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/xxBcs/~3/IeW2DZZoF3Y/list-hardlinks-on-hfs-volumes.html" title="List hardlinks on HFS volumes" /><author><name>Johan Sundström</name><uri>http://www.blogger.com/profile/04076097346172610543</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://ecmanaut.blogspot.com/2010/07/list-hardlinks-on-hfs-volumes.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0MMSHozeyp7ImA9WxFbFEo.&quot;"><id>tag:blogger.com,1999:blog-15626356.post-824950841831241393</id><published>2010-07-06T19:58:00.000-07:00</published><updated>2010-07-06T19:58:09.483-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-07-06T19:58:09.483-07:00</app:edited><title>A peek at Dropbox</title><content type="html">On a friend's suggestion, I had a peek at Dropbox for syncing directories between multiple computers, sharing files with people without posting email attachments, and the like. It's got many rather useful properties, but seems a little immature in the unix world; it is &lt;a href="http://forums.dropbox.com/topic.php?id=21863"&gt;unaware of file modes and symlinks&lt;/a&gt; (so symlinks will show up as real files or as nothing at all, if orphaned), making it less suitable for syncing git checkouts across multiple machines, as I was hoping to. As noted in the linked thread, though, the upcoming 0.8 release will get aware of file modes, which is a good start.&lt;br /&gt;
&lt;br /&gt;
What it does seem really good for, though, is auto-syncing preference files, data sets of stuff you want comfy access to wherever you are, breaking through NATs to sync stuff to home machines behind firewalls, and the like. One of the neater ideas I came across in the otherwise mostly uninteresting comments on &lt;a href="http://web.appstorm.net/general/giveaway/15-awesome-dropbox-tips-and-tricks-with-100-credit-giveaway/"&gt;this tips and tricks post&lt;/a&gt; was to set up a home machine to poll for torrent files dropped into some Dropbox-synced directory and start downloading them (to another directory, presumably), instead of doing the same via ssh.&lt;br /&gt;
&lt;br /&gt;
The free plan covers 2GB data stored (plus keeping 30 days of backup history), and if you sign up through a referral link (&lt;a href="https://www.dropbox.com/referrals/NTg3Nzk0Mjk5"&gt;here's mine&lt;/a&gt;), both signee and referrer get a quarter-gig extra quota.&lt;br /&gt;
&lt;br /&gt;
Their iPhone application delivers browsability of the files you sync (your own and those others share with you -- and it should be noted that "sharing" currently implements read/write access, only, so you'll want to keep backups and/or trust sharees as you trust yourself) and lets you micromanage pictures into your on-phone picture album one by one, lets you play music and video, but not add them to your on-phone music library.&lt;br /&gt;
&lt;br /&gt;
Similarly, it lets you can micromanage a picture at a time back from the device photo library to cloud storage (and connected computers), or make (now read-only), copy and email urls to any of the files in your dropbox, instead of mailing them as large attachments.&lt;br /&gt;
&lt;br /&gt;
I am not surprised that it doesn't much address the main pain points of the major data interop inconvenience that is the iPhone (App store terms probably don't allow them to), but I was more than a little surprised that it doesn't measure up to what a normal rsync does yet for typical machine-to-machine file transfers yet. It does a good job as a dual-direction sync feature for basic data between yourself and non-technical friends and relatives, though.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15626356-824950841831241393?l=ecmanaut.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/Vpk6S0Zwt0AqxkA7ZBZQO_rfz3w/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Vpk6S0Zwt0AqxkA7ZBZQO_rfz3w/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/Vpk6S0Zwt0AqxkA7ZBZQO_rfz3w/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Vpk6S0Zwt0AqxkA7ZBZQO_rfz3w/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/xxBcs/~4/MliQu-w9Uwo" height="1" width="1"/&gt;</content><link rel="related" href="https://www.dropbox.com/referrals/NTg3Nzk0Mjk5" title="A peek at Dropbox" /><link rel="replies" type="application/atom+xml" href="http://ecmanaut.blogspot.com/feeds/824950841831241393/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=15626356&amp;postID=824950841831241393" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/15626356/posts/default/824950841831241393?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/15626356/posts/default/824950841831241393?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/xxBcs/~3/MliQu-w9Uwo/peek-at-dropbox.html" title="A peek at Dropbox" /><author><name>Johan Sundström</name><uri>http://www.blogger.com/profile/04076097346172610543</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>2</thr:total><feedburner:origLink>http://ecmanaut.blogspot.com/2010/07/peek-at-dropbox.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUYARXwzcSp7ImA9WxFbE0Q.&quot;"><id>tag:blogger.com,1999:blog-15626356.post-4781595902576214112</id><published>2010-07-02T00:02:00.000-07:00</published><updated>2010-07-05T22:12:24.289-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-07-05T22:12:24.289-07:00</app:edited><title>Stop gif animations in Chrome with escape</title><content type="html">It occurred to me that one of the basic browser features still missing in Chrome, to turn off gif animations as you hit the escape key, ought to be &lt;a href="http://userscripts.org/scripts/show/80588"&gt;implementable as a tiny user script&lt;/a&gt; through canvas:&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;&lt;code&gt;document.addEventListener('keydown', freeze_gifs_on_escape, true);

function freeze_gifs_on_escape(e) {
  if (e.keyCode == 27 &amp;&amp; !e.shiftKey &amp;&amp; !e.ctrlKey &amp;&amp; !e.altKey &amp;&amp; !e.metaKey) {
    [].slice.apply(document.images).filter(is_gif_image).map(freeze_gif);
  }
}

function is_gif_image(i) {
  return /^(?!data:).*\.gif/i.test(i.src);
}

function freeze_gif(i) {
  var c = document.createElement('canvas');
  var w = c.width = i.width;
  var h = c.height = i.height;
  c.getContext('2d').drawImage(i, 0, 0, w, h);
  try {
    i.src = c.toDataURL("image/gif"); // if possible, retain all css aspects
  } catch(e) { // cross-domain -- mimic original with all its tag attributes
    for (var j = 0, a; a = i.attributes[j]; j++)
      c.setAttribute(a.name, a.value);
    i.parentNode.replaceChild(c, i);
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;s&gt;It mostly works, though for gif images loaded from another domain, we're unfortunately still out of luck. I hope Chrome will soon offer an extension flag for doing privileged canvas operations, such as drawImage, for an image loaded from another domain, like here.&lt;br /&gt;
&lt;br /&gt;
That privilege could even involve a manual extension review process in the Chrome extension gallery, for all I care; it is jarring that we can't fix user experience bugs like this due to the enforced security model.&lt;/s&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Edit:&lt;/b&gt; As suggested in the tip below, we don't really need to &lt;code&gt;.toDataURL&lt;/code&gt; the image, although that gives the best results on pages that apply css styling to img tags that we won't inherit to the canvas tag. The script has been updated to work everywhere; &lt;a href="http://userscripts.org/scripts/source/80588.user.js"&gt;direct install link here&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15626356-4781595902576214112?l=ecmanaut.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/78zDwG1edZMTO1cnV20RRWYyEfU/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/78zDwG1edZMTO1cnV20RRWYyEfU/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/78zDwG1edZMTO1cnV20RRWYyEfU/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/78zDwG1edZMTO1cnV20RRWYyEfU/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/xxBcs/~4/rEBj4llgq8w" height="1" width="1"/&gt;</content><link rel="related" href="http://userscripts.org/scripts/show/80588" title="Stop gif animations in Chrome with escape" /><link rel="replies" type="application/atom+xml" href="http://ecmanaut.blogspot.com/feeds/4781595902576214112/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=15626356&amp;postID=4781595902576214112" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/15626356/posts/default/4781595902576214112?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/15626356/posts/default/4781595902576214112?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/xxBcs/~3/rEBj4llgq8w/stop-gif-animations-in-chrome-with.html" title="Stop gif animations in Chrome with escape" /><author><name>Johan Sundström</name><uri>http://www.blogger.com/profile/04076097346172610543</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>2</thr:total><feedburner:origLink>http://ecmanaut.blogspot.com/2010/07/stop-gif-animations-in-chrome-with.html</feedburner:origLink></entry></feed>

