Skip to content

Instantly share code, notes, and snippets.

@satyr
Forked from ucnv/README.md
Created May 5, 2009 22:40
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save satyr/107259 to your computer and use it in GitHub Desktop.
Save satyr/107259 to your computer and use it in GitHub Desktop.
Diffs on Gist with google-diff-match-patch
// ==UserScript==
// @name gist diff
// @namespace http://github.com/satyr
// @description Shows diffs on Gist with google-diff-match-patch.
// @include https://gist.github.com/*
// @require https://raw.github.com/gist/105908
// @require https://google-diff-match-patch.googlecode.com/svn/trunk/javascript/diff_match_patch.js
// @fork_of http://gist.github.com/105913
// @check_also http://gist.github.com/107780
// ==/UserScript==
setTimeout(function(){
var {$} = unsafeWindow, $revs = $ ? $('#revisions li') : []
if($revs.length < 2) return
const Loader =
'<img src="//assets0.github.com/images/modules/pagehead/metabox_loader.gif"/>'
$revs.prepend('<input type="checkbox" class="diff-cb"/>')
var [exec] = $('<button id="diff-exec" accesskey="c"><u>C</u>ompare</button>')
.click(diff).prependTo('#revisions > ul')
, [last] = $('.current > input')
, ubase = 'https://raw.github.com/gist/'+ /\w+\//.exec(location.pathname)
last.checked = $('.other:first > input')[0].checked = 1
$('.diff-cb').click(function check(e){
var cs = $('.diff-cb:checked')
;(exec.disabled = cs.length < 2) || Array.forEach(cs, function(c){
if(c != this && c != last) c.checked = false
}, this)
last = this
})
function diff(){
var $view = $('#diff-view'), gists = $('.diff-cb:checked').map(function()({
href: meta($(this).siblings('.id')[0].pathname),
desc: this.parentNode.textContent.replace(/\s+/g, ' '),
})).get()
$view.length
? $view.slideUp(234, function(){ $view.html(Loader).show() })
: $view = $('<div id="diff-view">'+ Loader).prependTo('#files')
$.when.apply($, gists.map(function(g) get(g.href).pipe(tree)))
.done(function(){
var data = [
[let([h, n] = /\w{40}(?=\t?(.*))/.exec(e)) {hash: h, name: n}
for(e of r.split('\n'))]
for(r of Array.slice(arguments))]
var Q = [], htms = [], changed = data[0].length !== data[1].length
for(let x of data[0])
for(let y of data[1]){
changed || (changed = x.hash === y.hash && x.name !== y.name)
if(x.hash !== y.hash && x.name === y.name) Q.push(x, y)
}
if(changed){
let [a, b] = [[o.name for(o of os)] for(os of data)]
let diff = new Diff(b, a)
for(let k in {a:0, b:0, lcs:0}) diff[k].shift()
htms.push(
'<div class="syntax">'+
diff.lcs.map(function(n)(
n > 0
? '<p class="gi">'+ diff.b.shift() +' added</p>' :
n < 0
? '<p class="gd">'+ diff.a.shift() +' removed</p>'
: (diff.a.shift(), diff.b.shift(), '')))
.join('') +
'</div>')
}
$.when.apply($, [get(meta(o.hash)) for(o of Q)])
.done(function(){
for(let i = 1, l = Q.length; i < l; i += 2){
htms.push(format(
arguments[i-1],
arguments[i ],
gists[1].desc +' '+ Q[i ].name,
gists[0].desc +' '+ Q[i-1].name))
}
$view.hide()[0].innerHTML = htms.join('') || 'No differences'
$view.slideDown(345)
})
})
}
function get(url){
var d = $.Deferred()
setTimeout(function() GM_xmlhttpRequest({
method: 'get', url: url, onload: function(r) d.resolve(r.responseText)
}))
return d
}
function tree(data) get(meta(data))
function meta(text) ubase + /\w{40}/.exec(text) +'/meta'
function format(contentB, contentA, nameB, nameA)
'<style>del,ins{text-decoration:none}</style>'+
'<pre class="data syntax" style="font-size:88%">'+
'<div class="gd">---'+ nameB +'</div>'+
'<div class="gi">+++'+ nameA +'</div>'+
'</pre>'+
'<div class="file"><div class="data syntax"><pre>'+
let(dmp = new diff_match_patch())(
let(diffs = dmp.diff_main(contentA, contentB))(
dmp.diff_cleanupSemantic(diffs),
dmp.diff_prettyHtml(diffs).replace(/&para;/g, ''))) +
'</pre></div></div>'
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment