33 const exElmList = [ 'html' , 'title' , 'script' , 'noscript' , 'style' , 'meta' , 'link' , 'head' , 'textarea' , '#comment' ] ;
44 const blurredClassName = 'tb_blurred_class' ;
55 const keepClassName = 'tb_keep_this_class' ;
6+ const originalTitleAttributeName = 'data-tb-original-title' ;
67 const maskContainerClassName = 'tb_mask_container_class' ;
78 const textLayerClassName = 'tb_mask_text_layer_class' ;
89 const inputCloneId = 'tb_input_clone' ;
338339 } px`) ;
339340 mask . style . setProperty ( 'top' , `${ input . offsetTop + input . offsetHeight - blurredSpan . offsetHeight
340341 - ( verticalGap > 0 ? verticalGap / 2 : 0 )
341- - ( isBorderBox ? 0 : parseFloat ( inputStyle . getPropertyValue ( 'border-bottom-width' ) ) + parseFloat ( inputStyle . getPropertyValue ( 'padding-bottom' ) ) )
342+ - ( isBorderBox ? - parseFloat ( inputStyle . getPropertyValue ( 'border-top-width' ) ) : parseFloat ( inputStyle . getPropertyValue ( 'border-bottom-width' ) ) )
343+ - parseFloat ( inputStyle . getPropertyValue ( 'padding-bottom' ) )
342344 } px`) ;
343345 const maskBoundingBox = mask . getBoundingClientRect ( ) ;
344346 const tmpWidth = inputBoundingBox . width + inputBoundingBox . left - maskBoundingBox . left - parseFloat ( inputStyle . getPropertyValue ( 'border-left-width' ) ) ;
348350 ? tmpWidth
349351 : 0 } px`) ;
350352 mask . style . setProperty ( 'height' , `${ blurredBoundingBox . height } px` ) ;
351- mask . style . setProperty ( 'z-index' , `${ parseInt ( inputStyle . getPropertyValue ) + 1 } ` ) ;
353+ mask . style . setProperty ( 'z-index' , `${ parseInt ( inputStyle . getPropertyValue ( 'z-index' ) ) + 1 } ` ) ;
352354 mask . style . setProperty ( 'border' , 'none' ) ;
353355
354356 mask . style . setProperty ( 'background-color' , getBackgroundColorAlongDOMTree ( input ) ) ;
361363 if ( element == document ) return '' ;
362364 const computedStyle = getComputedStyle ( element ) ;
363365 return ( ! / (?: ^ | ) r g b a * \( * \d + * , * \d + * , * \d + * , * 0 * \) (?: $ | ) / . test ( computedStyle . getPropertyValue ( 'background-color' ) ) )
364- ? computedStyle . getPropertyValue ( 'background-color' )
366+ ? computedStyle . getPropertyValue ( 'background-color' ) . replace ( / r g b a * \( * ( \d + ) * , * ( \d + ) * , * ( \d + ) * , * [ ^ ) ] + * \) / , 'rgb($1, $2, $3)' )
365367 : getBackgroundColorAlongDOMTree ( element . parentNode ) ;
366368 }
367369 const inputOnFocus = ( e ) => {
456458 m . forEach ( ( n ) => {
457459 if ( n . classList . contains ( blurredClassName ) && n . classList . contains ( keepClassName ) ) {
458460 // restore title
459- const originalTitle = n . getAttribute ( 'data-tb-original-title' ) ;
461+ const originalTitle = n . getAttribute ( originalTitleAttributeName ) ;
460462 if ( originalTitle ) {
461463 n . setAttribute ( 'title' , originalTitle ) ;
462- n . removeAttribute ( 'data-tb-original-title' ) ;
464+ n . removeAttribute ( originalTitleAttributeName ) ;
463465 }
464466 else n . removeAttribute ( 'title' ) ;
465467
504506 console . debug ( `Took ${ Date . now ( ) - now } ms` )
505507 } ;
506508
509+ const unblurTabTitle = ( title ) => {
510+ if ( ! title ) return ;
511+ if ( title . getAttribute ( originalTitleAttributeName ) ) {
512+ title . textContent = title . getAttribute ( originalTitleAttributeName ) ;
513+ title . removeAttribute ( originalTitleAttributeName ) ;
514+ }
515+ if ( ! w . __titleObserver ) return ;
516+ w . __titleObserver . disconnect ( ) ;
517+ delete w . __titleObserver ;
518+ } ;
519+
520+ const blurTabTitleCore = ( pattern , target ) => {
521+ const title = target . textContent ;
522+ let result = title . match ( pattern ) ;
523+ while ( result ) {
524+ const mask = new Array ( result [ 0 ] . length ) . fill ( '*' ) . join ( '' ) ;
525+ target . textContent = target . textContent . replace ( result [ 0 ] , mask ) ;
526+ result = target . textContent . match ( pattern ) ;
527+ if ( ! target . getAttribute ( originalTitleAttributeName ) ) {
528+ target . setAttribute ( originalTitleAttributeName , title ) ;
529+ }
530+ }
531+ } ;
532+
533+ const blurTabTitle = ( pattern , title ) => {
534+ if ( ! title ) return ;
535+ blurTabTitleCore ( pattern , title ) ;
536+ if ( ! w . __titleObserver ) {
537+ w . __titleObserver = new MutationObserver ( ( records ) => {
538+ w . __titleObserver . disconnect ( ) ;
539+ title . removeAttribute ( originalTitleAttributeName ) ;
540+ records . forEach ( ( record ) => {
541+ blurTabTitleCore ( pattern , record . target ) ;
542+ } ) ;
543+ w . __titleObserver . observe ( title , {
544+ characterData : true , childList : true
545+ } ) ;
546+ } ) ;
547+ }
548+ w . __titleObserver . observe ( title , {
549+ characterData : true , childList : true
550+ } ) ;
551+ } ;
552+
507553 const escapeRegExp = ( str ) => {
508554 return str . replace ( / ( [ \( \) \{ \} \+ \* \? \[ \] \. \^ \$ \| \\ ] ) / g, '\\$1' ) ;
509555 } ;
515561 ) ;
516562 } ;
517563
564+ const title = document . querySelector ( 'title' ) ;
518565 chrome . storage . onChanged . addListener ( async ( changes , area ) => {
519566 if ( area !== 'local' ) return ;
520- const { status, keywords, mode, matchCase, showValue, blurInput } = ( await chrome . storage . local . get ( [ 'status' , 'keywords' , 'mode' , 'matchCase' , 'showValue' , 'blurInput' ] ) ) ;
567+ const { status, keywords, mode, matchCase, showValue, blurInput, blurTitle } = ( await chrome . storage . local . get ( [ 'status' , 'keywords' , 'mode' , 'matchCase' , 'showValue' , 'blurInput' , 'blurTitle '] ) ) ;
521568 unblur ( ) ;
569+ unblurTabTitle ( title ) ;
522570 if ( status === 'disabled' || ! keywords || keywords . trim ( ) === '' ) return ;
523- blur ( keywords2RegExp ( keywords , mode , ! ! matchCase ) , { showValue, blurInput } ) ;
571+ const pattern = keywords2RegExp ( keywords , mode , ! ! matchCase ) ;
572+ blur ( pattern , { showValue, blurInput } ) ;
573+ blurTitle && blurTabTitle ( pattern , title ) ;
524574 } ) ;
525- const { status, keywords, mode, matchCase, showValue, blurInput } = ( await chrome . storage . local . get ( [ 'status' , 'keywords' , 'mode' , 'matchCase' , 'showValue' , 'blurInput' ] ) ) ;
575+ const { status, keywords, mode, matchCase, showValue, blurInput, blurTitle } = ( await chrome . storage . local . get ( [ 'status' , 'keywords' , 'mode' , 'matchCase' , 'showValue' , 'blurInput' , 'blurTitle '] ) ) ;
526576 if ( status === 'disabled' || ! keywords || keywords . trim ( ) === '' ) return ;
527577 window . addEventListener ( 'resize' , ( ) => {
528578 inputs . forEach ( ( input ) => {
529579 input . element . dispatchEvent ( new InputEvent ( 'input' , { data : input . value } ) ) ;
530580 } ) ;
531581 } )
532- blur ( keywords2RegExp ( keywords , mode , ! ! matchCase ) , { showValue, blurInput } ) ;
582+ const pattern = keywords2RegExp ( keywords , mode , ! ! matchCase ) ;
583+ blur ( pattern , { showValue, blurInput } ) ;
584+ blurTitle && blurTabTitle ( pattern , title )
533585} ) ( ) ;
0 commit comments