copy_tuner_client 0.4.1 → 0.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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)
|