@@ -26,14 +26,13 @@ const css = `
26
26
border-radius: 100%;
27
27
background-color: red;
28
28
}
29
- .live-translator-badge-wrapper {
30
- position: relative !important;
31
- width: 0px;
32
- height: 0px;
33
- }
34
29
.live-translator-badge-container {
35
30
position: absolute !important;
31
+ background: rgba(255,255,255,0.5);
32
+ outline: solid 2px rgba(255,255,255,0.5);
33
+ border-radius: 5px;
36
34
display: flex;
35
+ gap: 2px;
37
36
z-index: 10000;
38
37
}
39
38
.live-translator-badge {
@@ -61,17 +60,16 @@ const css = `
61
60
box-shadow: 0px 0px 5px #00c0ff !important;
62
61
}
63
62
.live-translator-box {
64
- outline: solid 2px green;
65
- background: green;
66
- opacity: 0.1;
63
+ outline: solid 2px lightgreen !important;
64
+ box-shadow: 0px 0px 5px lightgreen !important;
67
65
position: absolute;
68
- border-radius: 4px ;
66
+ border-radius: 7px ;
69
67
z-index: 9999;
70
68
display: none;
71
69
}
72
70
.live-translator-box.attribute {
73
- outline: solid 2px blue ;
74
- background: blue ;
71
+ outline: solid 2px #00c0ff !important ;
72
+ box-shadow: 0px 0px 5px #00c0ff !important ;
75
73
}
76
74
`
77
75
export type TranslationMeta = {
@@ -85,6 +83,8 @@ export type TranslationMeta = {
85
83
type LiveTranslatorPluginOptions = {
86
84
translationLink : ( meta : TranslationMeta ) => string
87
85
persist ?: boolean
86
+ root ?: HTMLElement
87
+ refreshRate ?: number
88
88
}
89
89
90
90
function deepForIn ( object : Object , fn : ( value : string , key : string ) => void ) {
@@ -179,6 +179,7 @@ class LiveTranslatorManager {
179
179
_indicator : HTMLSpanElement
180
180
181
181
_box : HTMLDivElement
182
+ _wrapper : HTMLDivElement
182
183
183
184
constructor ( options : LiveTranslatorPluginOptions ) {
184
185
this . _enabled = false
@@ -212,15 +213,19 @@ class LiveTranslatorManager {
212
213
} )
213
214
document . body . appendChild ( this . _enableButton )
214
215
216
+ this . _wrapper = document . createElement ( 'div' )
217
+ this . _wrapper . classList . add ( 'live-translator-wrapper' )
218
+ document . body . prepend ( this . _wrapper )
219
+
215
220
this . _box = document . createElement ( 'div' )
216
221
this . _box . classList . add ( 'live-translator-box' )
217
- document . body . appendChild ( this . _box )
222
+ this . _wrapper . appendChild ( this . _box )
218
223
219
224
// initialize encode
220
225
// encode is moved to i18n.ts file
221
226
222
227
// initialize decode & render
223
- const throttler = throttle ( ( ) => this . render ( ) , 800 )
228
+ const throttler = throttle ( ( ) => this . render ( ) , this . _options . refreshRate || 50 )
224
229
const observer = new MutationObserver ( throttler )
225
230
observer . observe ( document . documentElement ,
226
231
{
@@ -231,12 +236,16 @@ class LiveTranslatorManager {
231
236
} ,
232
237
)
233
238
document . documentElement . addEventListener ( 'mousemove' , throttler )
234
- window . setInterval ( throttler , 1000 )
239
+ window . setInterval ( throttler , ( this . _options . refreshRate || 50 ) * 2 )
235
240
236
241
// render for the first time
237
242
this . render ( )
238
243
}
239
244
245
+ get root ( ) : HTMLElement {
246
+ return this . _options . root || document . documentElement
247
+ }
248
+
240
249
toggle ( enable ?: boolean ) {
241
250
if ( enable !== undefined ) {
242
251
this . _enabled = enable
@@ -250,11 +259,15 @@ class LiveTranslatorManager {
250
259
}
251
260
252
261
render ( ) {
253
- const badgeWrappers = document . querySelectorAll ( '.live-translator-badge-wrapper' )
262
+ if ( this . _enabled ) {
263
+ console . time ( )
264
+ }
254
265
this . _box . style . display = 'none'
255
- badgeWrappers . forEach ( ( wrapper ) => {
256
- wrapper . remove ( )
257
- } )
266
+ document .
267
+ querySelectorAll ( '.live-translator-badge-container' ) .
268
+ forEach ( ( elem ) => {
269
+ elem . remove ( )
270
+ } )
258
271
259
272
this . _indicator . style . background = this . _enabled ? 'lightgreen' : 'red'
260
273
@@ -264,14 +277,13 @@ class LiveTranslatorManager {
264
277
265
278
const re = new RegExp ( ZeroWidthEncoder . PATTERN , 'gm' )
266
279
267
- const queue = [ document . documentElement ] as Node [ ]
280
+ const queue = [ this . root ] as Node [ ]
268
281
while ( queue . length > 0 ) {
269
282
const node = queue . pop ( ) as HTMLElement
270
283
271
284
const badges = [ ] as HTMLElement [ ]
272
285
const parent = node . parentElement as HTMLElement
273
286
274
- const rect = getBoundingClientRect ( node )
275
287
if ( node instanceof Text ) {
276
288
const matches = ( node . textContent as string ) . match ( re )
277
289
for ( const match of matches ?? [ ] ) {
@@ -295,20 +307,22 @@ class LiveTranslatorManager {
295
307
}
296
308
297
309
if ( badges . length ) {
298
- let container : HTMLElement
299
- if ( node . previousElementSibling && node . previousElementSibling . classList . contains ( 'live-translator-badge-container' ) ) {
300
- container = node . previousElementSibling as HTMLElement
310
+ let position = { top : 0 , left : 0 }
311
+ if ( node instanceof Text ) {
312
+ const clientRect = getBoundingClientRect ( node )
313
+ position . top = clientRect . top + window . scrollY
314
+ position . left = clientRect . left + window . screenX
301
315
} else {
302
- const parentRect = getBoundingClientRect ( node instanceof Text ? parent : node ) ;
303
- container = document . createElement ( 'span' )
304
- container . classList . add ( 'live-translator-badge-container' )
305
- container . style . top = rect . top - parentRect . top + 'px'
306
- container . style . left = rect . left - parentRect . left + 'px'
307
- const relativeWrapper = document . createElement ( 'span' )
308
- relativeWrapper . classList . add ( 'live-translator-badge-wrapper' )
309
- relativeWrapper . appendChild ( container )
310
- parent . insertBefore ( relativeWrapper , node )
316
+ const clientRect = node . getClientRects ( ) [ 0 ]
317
+ position . top = clientRect . top + clientRect . height - 10 + window . scrollY
318
+ position . left = clientRect . left + window . screenX
311
319
}
320
+ const container = document . createElement ( 'span' )
321
+ container . classList . add ( 'live-translator-badge-container' )
322
+ container . style . top = position . top + 'px'
323
+ container . style . left = position . left + 'px'
324
+ this . _wrapper . appendChild ( container )
325
+
312
326
for ( const badge of badges ) {
313
327
container . appendChild ( badge )
314
328
}
@@ -318,6 +332,7 @@ class LiveTranslatorManager {
318
332
queue . push ( child )
319
333
}
320
334
}
335
+ console . timeEnd ( )
321
336
}
322
337
323
338
showBox ( node : Node , attribute = false ) {
0 commit comments