diff --git a/diff/diff.go b/diff/diff.go
new file mode 100644
index 0000000..e6c3213
--- /dev/null
+++ b/diff/diff.go
@@ -0,0 +1,96 @@
+package diff
+
+import (
+ "html"
+ "io"
+ "strings"
+)
+
+/*
+Paul's Simple Diff Algorithm v 0.1
+(C) Paul Butler 2007
+May be used and distributed under the zlib/libpng license.
+https://github.com/paulgb/simplediff/
+*/
+
+var Separator string = "\n"
+
+type Operation int8
+
+const (
+ OP_INSERTED Operation = 1
+ OP_UNCHANGED = 2
+ OP_REMOVED = 3
+)
+
+type Instruction struct {
+ Op Operation
+ Content []string
+}
+
+func (this *Instruction) RenderHTML() string {
+ switch this.Op {
+ case OP_INSERTED:
+ return `` + strings.Join(this.Content, Separator) + ``
+ case OP_REMOVED:
+ return `` + strings.Join(this.Content, Separator) + ``
+ default: //OP_UNCHANGED:
+ return strings.Join(this.Content, Separator)
+ }
+}
+
+func Diff(o, n []string) []Instruction {
+ maxl := 0
+ omax := 0
+ nmax := 0
+ matrix := make(map[int]map[int]int, len(o)+1)
+
+ for oindex, ovalue := range o {
+
+ // Find keys in new, where value matchines ovalue
+ nkeys := make([]int, 0)
+ for nindex, nvalue := range n {
+ if nvalue == ovalue {
+ nkeys = append(nkeys, nindex)
+ }
+ }
+
+ // Build diff matrix
+ for nindex, _ := range n {
+ if _, ok := matrix[oindex]; !ok {
+ matrix[oindex] = make(map[int]int, len(n)+1)
+ }
+ matrix[oindex][nindex] = matrix[oindex-1][nindex-1] + 1
+
+ if matrix[oindex][nindex] > maxl {
+ maxl = matrix[oindex][nindex]
+ omax = oindex + 1 - maxl
+ nmax = nindex + 1 - maxl
+ }
+ }
+ }
+
+ if maxl == 0 {
+ return []Instruction{
+ Instruction{OP_REMOVED, o},
+ Instruction{OP_INSERTED, n},
+ }
+ }
+
+ ret := Diff(o[0:omax], n[0:nmax])
+ if maxl != nmax {
+ ret = append(ret, Instruction{OP_UNCHANGED, n[nmax:maxl]})
+ }
+ ret = append(ret, Diff(o[0:omax+maxl], n[0:nmax+maxl])...)
+
+ return ret
+}
+
+// HtmlDiff splits o and n by newlines, and writes an HTML-safe version to the dest writer.
+func HtmlDiff(o, n string, dest io.Writer) {
+ ops := Diff(strings.Split(html.EscapeString(o), Separator), strings.Split(html.EscapeString(n), Separator))
+
+ for _, op := range ops {
+ dest.Write([]byte(op.RenderHTML()))
+ }
+}