copy_tuner_client 0.4.1 → 0.4.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.babelrc +18 -0
- data/.eslintrc +4 -0
- data/CHANGELOG.md +6 -2
- data/Gemfile.lock +1 -1
- data/README.md +4 -4
- data/app/assets/javascripts/copyray.js +937 -409
- data/app/assets/stylesheets/copyray.css +14 -16
- data/app/views/_copy_tuner_bar.html.erb +0 -6
- data/lib/copy_tuner_client/copyray.rb +3 -20
- data/lib/copy_tuner_client/version.rb +1 -1
- data/package-lock.json +2578 -4
- data/package.json +16 -3
- data/rollup.config.js +14 -0
- data/src/copyray.js +111 -0
- data/src/copytuner_bar.js +96 -0
- data/src/main.js +42 -0
- data/src/specimen.js +63 -0
- data/src/util.js +32 -0
- metadata +10 -4
- data/coffeelint.json +0 -135
- data/src/copyray.coffee +0 -354
data/coffeelint.json
DELETED
@@ -1,135 +0,0 @@
|
|
1
|
-
{
|
2
|
-
"arrow_spacing": {
|
3
|
-
"level": "ignore"
|
4
|
-
},
|
5
|
-
"braces_spacing": {
|
6
|
-
"level": "ignore",
|
7
|
-
"spaces": 0,
|
8
|
-
"empty_object_spaces": 0
|
9
|
-
},
|
10
|
-
"camel_case_classes": {
|
11
|
-
"level": "error"
|
12
|
-
},
|
13
|
-
"coffeescript_error": {
|
14
|
-
"level": "error"
|
15
|
-
},
|
16
|
-
"colon_assignment_spacing": {
|
17
|
-
"level": "ignore",
|
18
|
-
"spacing": {
|
19
|
-
"left": 0,
|
20
|
-
"right": 0
|
21
|
-
}
|
22
|
-
},
|
23
|
-
"cyclomatic_complexity": {
|
24
|
-
"value": 10,
|
25
|
-
"level": "ignore"
|
26
|
-
},
|
27
|
-
"duplicate_key": {
|
28
|
-
"level": "error"
|
29
|
-
},
|
30
|
-
"empty_constructor_needs_parens": {
|
31
|
-
"level": "ignore"
|
32
|
-
},
|
33
|
-
"ensure_comprehensions": {
|
34
|
-
"level": "warn"
|
35
|
-
},
|
36
|
-
"eol_last": {
|
37
|
-
"level": "ignore"
|
38
|
-
},
|
39
|
-
"indentation": {
|
40
|
-
"value": 2,
|
41
|
-
"level": "error"
|
42
|
-
},
|
43
|
-
"line_endings": {
|
44
|
-
"level": "ignore",
|
45
|
-
"value": "unix"
|
46
|
-
},
|
47
|
-
"max_line_length": {
|
48
|
-
"value": 160,
|
49
|
-
"level": "error",
|
50
|
-
"limitComments": true
|
51
|
-
},
|
52
|
-
"missing_fat_arrows": {
|
53
|
-
"level": "ignore",
|
54
|
-
"is_strict": false
|
55
|
-
},
|
56
|
-
"newlines_after_classes": {
|
57
|
-
"value": 3,
|
58
|
-
"level": "ignore"
|
59
|
-
},
|
60
|
-
"no_backticks": {
|
61
|
-
"level": "error"
|
62
|
-
},
|
63
|
-
"no_debugger": {
|
64
|
-
"level": "warn",
|
65
|
-
"console": false
|
66
|
-
},
|
67
|
-
"no_empty_functions": {
|
68
|
-
"level": "ignore"
|
69
|
-
},
|
70
|
-
"no_empty_param_list": {
|
71
|
-
"level": "ignore"
|
72
|
-
},
|
73
|
-
"no_implicit_braces": {
|
74
|
-
"level": "ignore",
|
75
|
-
"strict": true
|
76
|
-
},
|
77
|
-
"no_implicit_parens": {
|
78
|
-
"strict": true,
|
79
|
-
"level": "ignore"
|
80
|
-
},
|
81
|
-
"no_interpolation_in_single_quotes": {
|
82
|
-
"level": "ignore"
|
83
|
-
},
|
84
|
-
"no_nested_string_interpolation": {
|
85
|
-
"level": "warn"
|
86
|
-
},
|
87
|
-
"no_plusplus": {
|
88
|
-
"level": "ignore"
|
89
|
-
},
|
90
|
-
"no_private_function_fat_arrows": {
|
91
|
-
"level": "warn"
|
92
|
-
},
|
93
|
-
"no_stand_alone_at": {
|
94
|
-
"level": "ignore"
|
95
|
-
},
|
96
|
-
"no_tabs": {
|
97
|
-
"level": "error"
|
98
|
-
},
|
99
|
-
"no_this": {
|
100
|
-
"level": "ignore"
|
101
|
-
},
|
102
|
-
"no_throwing_strings": {
|
103
|
-
"level": "error"
|
104
|
-
},
|
105
|
-
"no_trailing_semicolons": {
|
106
|
-
"level": "error"
|
107
|
-
},
|
108
|
-
"no_trailing_whitespace": {
|
109
|
-
"level": "error",
|
110
|
-
"allowed_in_comments": false,
|
111
|
-
"allowed_in_empty_lines": true
|
112
|
-
},
|
113
|
-
"no_unnecessary_double_quotes": {
|
114
|
-
"level": "ignore"
|
115
|
-
},
|
116
|
-
"no_unnecessary_fat_arrows": {
|
117
|
-
"level": "warn"
|
118
|
-
},
|
119
|
-
"non_empty_constructor_needs_parens": {
|
120
|
-
"level": "ignore"
|
121
|
-
},
|
122
|
-
"prefer_english_operator": {
|
123
|
-
"level": "ignore",
|
124
|
-
"doubleNotLevel": "ignore"
|
125
|
-
},
|
126
|
-
"space_operators": {
|
127
|
-
"level": "ignore"
|
128
|
-
},
|
129
|
-
"spacing_after_comma": {
|
130
|
-
"level": "ignore"
|
131
|
-
},
|
132
|
-
"transform_messes_up_line_numbers": {
|
133
|
-
"level": "warn"
|
134
|
-
}
|
135
|
-
}
|
data/src/copyray.coffee
DELETED
@@ -1,354 +0,0 @@
|
|
1
|
-
window.Copyray ?= {}
|
2
|
-
|
3
|
-
# Max CSS z-index. The overlay and copyray bar use this.
|
4
|
-
MAX_ZINDEX = 2147483647
|
5
|
-
HIDDEN_CLASS = 'copy-tuner-hidden'
|
6
|
-
|
7
|
-
isMac = navigator.platform.toUpperCase().indexOf('MAC') isnt -1
|
8
|
-
|
9
|
-
isVisible = (element) ->
|
10
|
-
!!(element.offsetWidth || element.offsetHeight || element.getClientRects().length)
|
11
|
-
|
12
|
-
getOffset = (elment) ->
|
13
|
-
box = elment.getBoundingClientRect()
|
14
|
-
{
|
15
|
-
top: box.top + window.pageYOffset - document.documentElement.clientTop,
|
16
|
-
left: box.left + window.pageXOffset - document.documentElement.clientLeft
|
17
|
-
}
|
18
|
-
|
19
|
-
# Returns all currently created Copyray.Specimen objects.
|
20
|
-
Copyray.specimens = ->
|
21
|
-
Copyray.BlurbSpecimen.all
|
22
|
-
|
23
|
-
# Looks up the stored constructor info
|
24
|
-
Copyray.constructorInfo = (constructor) ->
|
25
|
-
if window.CopyrayPaths
|
26
|
-
for own info, func of window.CopyrayPaths
|
27
|
-
return JSON.parse(info) if func == constructor
|
28
|
-
null
|
29
|
-
|
30
|
-
getAllComments = (rootElement) ->
|
31
|
-
filterNone = ->
|
32
|
-
NodeFilter.FILTER_ACCEPT
|
33
|
-
|
34
|
-
comments = []
|
35
|
-
iterator = document.createNodeIterator(rootElement, NodeFilter.SHOW_COMMENT, filterNone, false)
|
36
|
-
while (curNode = iterator.nextNode())
|
37
|
-
comments.push(curNode)
|
38
|
-
comments
|
39
|
-
|
40
|
-
# Scans the document for blurbs, creating Copyray.BlurbSpecimen for them.
|
41
|
-
Copyray.findBlurbs = -> util.bm 'findBlurbs', ->
|
42
|
-
# Find all <!-- COPYRAY START ... --> comments
|
43
|
-
comments = getAllComments(document.body).filter((comment) ->
|
44
|
-
comment.nodeValue.startsWith('COPYRAY START')
|
45
|
-
)
|
46
|
-
|
47
|
-
comments.forEach((comment) ->
|
48
|
-
[_, id, path, url] = comment.nodeValue.match(/^COPYRAY START (\d+) (\S*) (\S*)/)
|
49
|
-
blurbElement = null
|
50
|
-
el = comment.nextSibling
|
51
|
-
until !el or (el.nodeType == Node.COMMENT_NODE and el.data == "COPYRAY END #{id}")
|
52
|
-
if el.nodeType == Node.ELEMENT_NODE and el.tagName != 'SCRIPT'
|
53
|
-
blurbElement = el
|
54
|
-
break
|
55
|
-
el = el.nextSibling
|
56
|
-
|
57
|
-
# Remove COPYRAY template comments from the DOM.
|
58
|
-
el.parentNode.removeChild(el) if el?.nodeType == Node.COMMENT_NODE
|
59
|
-
comment.parentNode.removeChild(comment)
|
60
|
-
|
61
|
-
if blurbElement
|
62
|
-
# Add the template specimen
|
63
|
-
Copyray.BlurbSpecimen.add blurbElement,
|
64
|
-
name: path.split('/').slice(-1)[0]
|
65
|
-
path: path
|
66
|
-
url: url
|
67
|
-
)
|
68
|
-
|
69
|
-
# Open the given filesystem path by calling out to Copyray's server.
|
70
|
-
Copyray.open = (url) ->
|
71
|
-
window.open(url, null, 'width=700, height=600')
|
72
|
-
|
73
|
-
# Show the Copyray overlay
|
74
|
-
Copyray.show = (type = null) ->
|
75
|
-
Copyray.Overlay.instance().show(type)
|
76
|
-
Copyray.showBar()
|
77
|
-
|
78
|
-
# Hide the Copyray overlay
|
79
|
-
Copyray.hide = ->
|
80
|
-
Copyray.Overlay.instance().hide()
|
81
|
-
Copyray.hideBar()
|
82
|
-
|
83
|
-
Copyray.addToggleButton = ->
|
84
|
-
element = document.createElement('a')
|
85
|
-
element.addEventListener('click', () ->
|
86
|
-
Copyray.show()
|
87
|
-
)
|
88
|
-
element.classList.add('copyray-toggle-button')
|
89
|
-
element.textContent = 'Open CopyTuner'
|
90
|
-
document.body.appendChild(element)
|
91
|
-
|
92
|
-
# Wraps a DOM element that Copyray is tracking. This is subclassed by
|
93
|
-
# Copyray.Blurbsspecimen
|
94
|
-
class Copyray.Specimen
|
95
|
-
@add: (el, info = {}) ->
|
96
|
-
@all.push new this(el, info)
|
97
|
-
|
98
|
-
@remove: (el) ->
|
99
|
-
@find(el)?.remove()
|
100
|
-
|
101
|
-
@find: (el) ->
|
102
|
-
for specimen in @all
|
103
|
-
return specimen if specimen.el == el
|
104
|
-
null
|
105
|
-
|
106
|
-
@reset: ->
|
107
|
-
@all = []
|
108
|
-
|
109
|
-
constructor: (el, info = {}) ->
|
110
|
-
@el = el
|
111
|
-
@name = info.name
|
112
|
-
@path = info.path
|
113
|
-
@url = info.url
|
114
|
-
|
115
|
-
remove: ->
|
116
|
-
idx = @constructor.all.indexOf(this)
|
117
|
-
@constructor.all.splice(idx, 1) unless idx == -1
|
118
|
-
|
119
|
-
makeBox: ->
|
120
|
-
@bounds = util.computeBoundingBox([@el])
|
121
|
-
@box = document.createElement('div')
|
122
|
-
@box.classList.add('copyray-specimen')
|
123
|
-
@box.classList.add(@constructor.name)
|
124
|
-
for key, value of @bounds
|
125
|
-
@box.style[key] = "#{value}px"
|
126
|
-
|
127
|
-
# If the element is fixed, override the computed position with the fixed one.
|
128
|
-
if getComputedStyle(@el).position == 'fixed'
|
129
|
-
@box.css
|
130
|
-
position : 'fixed'
|
131
|
-
top : getComputedStyle(@el).top
|
132
|
-
left : getComputedStyle(@el).left
|
133
|
-
|
134
|
-
@box.addEventListener('click', =>
|
135
|
-
Copyray.open "#{@url}/blurbs/#{@path}/edit"
|
136
|
-
)
|
137
|
-
|
138
|
-
@box.appendChild(@makeLabel())
|
139
|
-
|
140
|
-
makeLabel: =>
|
141
|
-
div = document.createElement('div')
|
142
|
-
div.classList.add('copyray-specimen-handle')
|
143
|
-
div.classList.add(@constructor.name)
|
144
|
-
div.textContent = @name
|
145
|
-
div
|
146
|
-
|
147
|
-
# copy-tuner blurbs
|
148
|
-
class Copyray.BlurbSpecimen extends Copyray.Specimen
|
149
|
-
@all = []
|
150
|
-
|
151
|
-
# Singleton class for the Copyray "overlay" invoked by the keyboard shortcut
|
152
|
-
class Copyray.Overlay
|
153
|
-
@instance: ->
|
154
|
-
@singletonInstance ||= new this
|
155
|
-
|
156
|
-
constructor: ->
|
157
|
-
Copyray.Overlay.singletonInstance = this
|
158
|
-
@overlay = document.createElement('div')
|
159
|
-
@overlay.setAttribute('id', 'copyray-overlay')
|
160
|
-
@shownBoxes = []
|
161
|
-
@overlay.addEventListener('click', () =>
|
162
|
-
@hide()
|
163
|
-
)
|
164
|
-
|
165
|
-
show: (type = null) ->
|
166
|
-
@reset()
|
167
|
-
Copyray.isShowing = true
|
168
|
-
util.bm 'show', =>
|
169
|
-
unless document.body.contains(@overlay)
|
170
|
-
document.body.appendChild(@overlay)
|
171
|
-
Copyray.findBlurbs()
|
172
|
-
specimens = Copyray.specimens()
|
173
|
-
|
174
|
-
for element in specimens
|
175
|
-
element.makeBox()
|
176
|
-
# A cheap way to "order" the boxes, where boxes positioned closer to the
|
177
|
-
# bottom right of the document have a higher z-index.
|
178
|
-
element.box.style.zIndex = Math.ceil(MAX_ZINDEX*0.9 + element.bounds.top + element.bounds.left)
|
179
|
-
@shownBoxes.push element.box
|
180
|
-
document.body.appendChild(element.box)
|
181
|
-
|
182
|
-
reset: ->
|
183
|
-
$box.remove() for $box in @shownBoxes
|
184
|
-
@shownBoxes = []
|
185
|
-
|
186
|
-
hide: ->
|
187
|
-
Copyray.isShowing = false
|
188
|
-
@overlay.remove()
|
189
|
-
@reset()
|
190
|
-
Copyray.hideBar()
|
191
|
-
|
192
|
-
# Utility methods.
|
193
|
-
util =
|
194
|
-
# Benchmark a piece of code
|
195
|
-
bm: (name, fn) ->
|
196
|
-
time = new Date
|
197
|
-
result = fn()
|
198
|
-
# console.log "#{name} : #{new Date() - time}ms"
|
199
|
-
result
|
200
|
-
|
201
|
-
# elements with no parent in the set.
|
202
|
-
computeBoundingBox: (elements) ->
|
203
|
-
# Edge case: the container may not physically wrap its children, for
|
204
|
-
# example if they are floated and no clearfix is present.
|
205
|
-
if elements.length == 1 and elements[0].clientHeight
|
206
|
-
return util.computeBoundingBox(elements[0].children)
|
207
|
-
|
208
|
-
boxFrame =
|
209
|
-
top : Number.POSITIVE_INFINITY
|
210
|
-
left : Number.POSITIVE_INFINITY
|
211
|
-
right : Number.NEGATIVE_INFINITY
|
212
|
-
bottom : Number.NEGATIVE_INFINITY
|
213
|
-
|
214
|
-
Array.from(elements).forEach((element) ->
|
215
|
-
return unless isVisible(element)
|
216
|
-
frame = getOffset(element)
|
217
|
-
frame.right = frame.left + element.offsetWidth
|
218
|
-
frame.bottom = frame.top + element.offsetHeight
|
219
|
-
boxFrame.top = frame.top if frame.top < boxFrame.top
|
220
|
-
boxFrame.left = frame.left if frame.left < boxFrame.left
|
221
|
-
boxFrame.right = frame.right if frame.right > boxFrame.right
|
222
|
-
boxFrame.bottom = frame.bottom if frame.bottom > boxFrame.bottom
|
223
|
-
)
|
224
|
-
|
225
|
-
return {
|
226
|
-
left : boxFrame.left
|
227
|
-
top : boxFrame.top
|
228
|
-
width : boxFrame.right - boxFrame.left
|
229
|
-
height : boxFrame.bottom - boxFrame.top
|
230
|
-
}
|
231
|
-
|
232
|
-
Copyray.showBar = ->
|
233
|
-
document.getElementById('copy-tuner-bar').classList.remove(HIDDEN_CLASS)
|
234
|
-
document.querySelector('.copyray-toggle-button').classList.add(HIDDEN_CLASS)
|
235
|
-
Copyray.focusSearchBox()
|
236
|
-
|
237
|
-
Copyray.hideBar = ->
|
238
|
-
document.getElementById('copy-tuner-bar').classList.add(HIDDEN_CLASS)
|
239
|
-
document.querySelector('.copyray-toggle-button').classList.remove(HIDDEN_CLASS)
|
240
|
-
document.querySelector('.js-copy-tuner-bar-log-menu').classList.add(HIDDEN_CLASS)
|
241
|
-
|
242
|
-
Copyray.createLogMenu = ->
|
243
|
-
tbody = document.querySelector('.js-copy-tuner-bar-log-menu__tbody.is-not-initialized')
|
244
|
-
return unless tbody
|
245
|
-
|
246
|
-
tbody.classList.remove('is-not-initialized')
|
247
|
-
baseUrl = document.getElementById('copy-tuner-data').dataset.copyTunerUrl
|
248
|
-
log = JSON.parse(document.getElementById('copy-tuner-data').dataset.copyTunerTranslationLog)
|
249
|
-
|
250
|
-
Object.keys(log).sort().forEach((key) ->
|
251
|
-
value = log[key]
|
252
|
-
return if value == ''
|
253
|
-
|
254
|
-
url = "#{baseUrl}/blurbs/#{key}/edit"
|
255
|
-
|
256
|
-
td1 = document.createElement('td')
|
257
|
-
td1.textContent = key
|
258
|
-
|
259
|
-
td2 = document.createElement('td')
|
260
|
-
td2.textContent = value
|
261
|
-
|
262
|
-
tr = document.createElement('tr')
|
263
|
-
tr.classList.add('copy-tuner-bar-log-menu__row')
|
264
|
-
tr.classList.add('js-copy-tuner-blurb-row')
|
265
|
-
tr.dataset.url = url
|
266
|
-
|
267
|
-
tr.addEventListener('click', ({currentTarget}) ->
|
268
|
-
Copyray.open(currentTarget.dataset.url)
|
269
|
-
)
|
270
|
-
|
271
|
-
tr.appendChild(td1)
|
272
|
-
tr.appendChild(td2)
|
273
|
-
tbody.appendChild(tr)
|
274
|
-
)
|
275
|
-
|
276
|
-
Copyray.focusSearchBox = ->
|
277
|
-
document.querySelector('.js-copy-tuner-bar-search').focus()
|
278
|
-
|
279
|
-
Copyray.toggleLogMenu = ->
|
280
|
-
Copyray.createLogMenu()
|
281
|
-
document.getElementById('copy-tuner-bar-log-menu').classList.toggle(HIDDEN_CLASS)
|
282
|
-
|
283
|
-
Copyray.setupLogMenu = ->
|
284
|
-
element = document.querySelector('.js-copy-tuner-bar-open-log')
|
285
|
-
element.addEventListener('click', (event) ->
|
286
|
-
event.preventDefault()
|
287
|
-
Copyray.toggleLogMenu()
|
288
|
-
)
|
289
|
-
|
290
|
-
Copyray.setupSearchBar = ->
|
291
|
-
timer = null
|
292
|
-
lastKeyword = ''
|
293
|
-
barElement = document.querySelector('.js-copy-tuner-bar-search')
|
294
|
-
|
295
|
-
barElement.addEventListener('focus', ({target}) ->
|
296
|
-
lastKeyword = target.value
|
297
|
-
)
|
298
|
-
|
299
|
-
barElement.addEventListener('keyup', ({target}) ->
|
300
|
-
keyword = target.value.trim()
|
301
|
-
if lastKeyword != keyword
|
302
|
-
Copyray.toggleLogMenu() if !isVisible(document.getElementById('copy-tuner-bar-log-menu'))
|
303
|
-
clearTimeout(timer)
|
304
|
-
timer = setTimeout ->
|
305
|
-
rows = Array.from(document.getElementsByClassName('js-copy-tuner-blurb-row'))
|
306
|
-
if keyword == ''
|
307
|
-
rows.forEach((row) ->
|
308
|
-
row.classList.remove(HIDDEN_CLASS)
|
309
|
-
)
|
310
|
-
else
|
311
|
-
rows.forEach((row) ->
|
312
|
-
row.classList.add(HIDDEN_CLASS)
|
313
|
-
)
|
314
|
-
|
315
|
-
rows.filter((row) ->
|
316
|
-
Array.from(row.getElementsByTagName('td')).some((td) ->
|
317
|
-
td.textContent.includes(keyword)
|
318
|
-
)
|
319
|
-
).forEach((row) ->
|
320
|
-
row.classList.remove(HIDDEN_CLASS)
|
321
|
-
)
|
322
|
-
, 500
|
323
|
-
lastKeyword = keyword
|
324
|
-
)
|
325
|
-
|
326
|
-
init = ->
|
327
|
-
return if Copyray.initialized
|
328
|
-
Copyray.initialized = true
|
329
|
-
|
330
|
-
# Register keyboard shortcuts
|
331
|
-
document.addEventListener('keydown', (event) ->
|
332
|
-
# cmd + shift + k
|
333
|
-
if (isMac and event.metaKey or !isMac and event.ctrlKey) and event.shiftKey and event.keyCode is 75
|
334
|
-
if Copyray.isShowing then Copyray.hide() else Copyray.show()
|
335
|
-
if Copyray.isShowing and event.keyCode is 27 # esc
|
336
|
-
Copyray.hide()
|
337
|
-
)
|
338
|
-
|
339
|
-
# Instantiate the overlay singleton.
|
340
|
-
new Copyray.Overlay
|
341
|
-
# Go ahead and do a pass on the DOM to find templates.
|
342
|
-
Copyray.findBlurbs()
|
343
|
-
|
344
|
-
Copyray.addToggleButton()
|
345
|
-
Copyray.setupSearchBar()
|
346
|
-
Copyray.setupLogMenu()
|
347
|
-
|
348
|
-
# Ready to rock.
|
349
|
-
console?.log "Ready to Copyray. Press #{if isMac then 'cmd+shift+k' else 'ctrl+shift+k'} to scan your UI."
|
350
|
-
|
351
|
-
if document.readyState == 'complete' || document.readyState != 'loading'
|
352
|
-
init()
|
353
|
-
else
|
354
|
-
document.addEventListener('DOMContentLoaded', init)
|