This repository has been archived by the owner on Aug 11, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 8
/
index.js
159 lines (137 loc) · 4.23 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
var $ = require('jquery')
global.Handlebars = require('handlebars')
require('./annotation.js')
function AnnotationPoller (opts) {
this._installExtensions()
this.pollInterval = opts.pollInterval || 3000
this.pkg = opts.pkg // what package should we load annotations for?
this.endpoint = '/api/v1/annotations/' + this.pkg
this.annotations = {}
this.template = global.Handlebars.templates['annotation.mustache']
this.addonSelector = '#npm-addon-box'
}
AnnotationPoller.prototype._installExtensions = function () {
global.Handlebars.registerHelper('hasKey', function (obj, key, options) {
if (typeof obj === 'object' && obj[key]) {
return options.fn(this)
} else {
return options.inverse(this)
}
})
global.Handlebars.registerHelper('isArray', function (obj, options) {
if ($.isArray(obj)) {
return options.fn(this)
} else {
return options.inverse(this)
}
})
}
AnnotationPoller.prototype.start = function (loaded) {
var _this = this
var updating = false
var poll = function () {
if (updating) return
updating = true
_this.getAnnotations(function () {
updating = false
_this.renderAnnotations()
if (loaded) {
loaded()
loaded = null
}
})
}
$(document).ready(function () {
this.interval = setInterval(function () {
poll()
}, _this.pollInterval)
})
poll()
}
AnnotationPoller.prototype.stop = function () {
clearInterval(this.interval)
}
AnnotationPoller.prototype.getAnnotations = function (cb) {
var _this = this
$.getJSON(this.endpoint, function (data) {
$.each(data, function (i, annotation) {
_this.annotations[annotation.id] = annotation
})
}).always(function () {
return cb()
})
}
AnnotationPoller.prototype.renderAnnotations = function () {
var _this = this
var annotation = null
var annotationElement = null
var newAnnotationElement = null
var addonBox = $(this.addonSelector)
Object.keys(this.annotations).forEach(function (key) {
annotation = _this._applyReplacements(_this.annotations[key])
if (annotation._rendered) return
annotationElement = $('#annotation-' + annotation.id)
newAnnotationElement = _this.template(annotation)
if (annotationElement.length) {
// don't render the element unless its fingerprint has changed.
if (annotationElement.data('fingerprint') !== annotation.fingerprint) {
annotationElement.replaceWith(newAnnotationElement)
}
} else {
addonBox.append(newAnnotationElement)
}
annotation._rendered = true
})
}
AnnotationPoller.prototype._applyReplacements = function (obj) {
var _this = this
if ($.isArray(obj.rows)) {
obj.rows.forEach(function (row, i) {
var flattenedRow = []
// bold any text in between *foo* and parse newlines.
if (row.text) {
row.text = _this._escape(row.text)
row.text = row.text.replace(/\*([\s\S]+)\*/, '<strong>$1</strong>').replace(/\n/g, '<br/>')
}
// escape any HTML in links.
if ($.isArray(row.link)) {
row.link.forEach(function (l) {
if (l.url) l.url = _this._escape(l.url)
})
} else if (row.link) {
if (row.link.url) row.link.url = _this._escape(row.link.url)
}
// escape any HTML in image links.
if (row.image) {
if (!$.isArray(row.image)) {
row.image = [row.image]
}
row.image.forEach(function (img) {
if (img.url) img.url = _this._escape(img.url)
if (img.href) img.href = _this._escape(img.href)
})
}
// flatten the row object into an ordered
// set of elements. In our template we output
// the elements in the order that the keys appear.
Object.keys(row).forEach(function (key) {
var element = row[key]
if (typeof element === 'string') element = {text: element}
element['_' + key] = true
flattenedRow.push(element)
})
obj.rows[i] = flattenedRow
})
} else {
// we shouldn't allow obj.rows
// to be a non-array value.
obj.rows = []
}
return obj
}
AnnotationPoller.prototype._escape = function (text) {
return $('<div>').text(text).html()
}
module.exports = function (opts) {
return new AnnotationPoller(opts)
}