-
Notifications
You must be signed in to change notification settings - Fork 791
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix(link-in-text-block): take into account ancestor inline element styles #4135
base: develop
Are you sure you want to change the base?
Changes from 6 commits
bc4bf09
47bf2b5
859ffcf
c50700e
470b462
2f100c1
014585f
5ebde67
4d839b9
25b3001
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
import Color from './color'; | ||
import { getComposedParent } from '../dom'; | ||
|
||
/** | ||
* Creates a string array of fonts for given CSSStyleDeclaration object | ||
|
@@ -25,60 +26,80 @@ function _getFonts(style) { | |
* @return {Boolean} | ||
*/ | ||
function elementIsDistinct(node, ancestorNode) { | ||
var nodeStyle = window.getComputedStyle(node); | ||
const nodeStyle = window.getComputedStyle(node); | ||
|
||
// Check if the link has a background | ||
if (nodeStyle.getPropertyValue('background-image') !== 'none') { | ||
return true; | ||
} | ||
|
||
// Check if the link has a border or outline | ||
var hasBorder = ['border-bottom', 'border-top', 'outline'].reduce( | ||
straker marked this conversation as resolved.
Show resolved
Hide resolved
|
||
(result, edge) => { | ||
var borderClr = new Color(); | ||
borderClr.parseString(nodeStyle.getPropertyValue(edge + '-color')); | ||
|
||
// Check if a border/outline was specified | ||
return ( | ||
result || | ||
// or if the current border edge / outline | ||
(nodeStyle.getPropertyValue(edge + '-style') !== 'none' && | ||
parseFloat(nodeStyle.getPropertyValue(edge + '-width')) > 0 && | ||
borderClr.alpha !== 0) | ||
); | ||
}, | ||
false | ||
); | ||
const hasBorder = ['border-bottom', 'border-top', 'outline'].some(edge => { | ||
const borderClr = new Color(); | ||
borderClr.parseString(nodeStyle.getPropertyValue(edge + '-color')); | ||
|
||
// Check if a border/outline was specified | ||
return ( | ||
nodeStyle.getPropertyValue(edge + '-style') !== 'none' && | ||
parseFloat(nodeStyle.getPropertyValue(edge + '-width')) > 0 && | ||
borderClr.alpha !== 0 | ||
); | ||
}); | ||
|
||
if (hasBorder) { | ||
return true; | ||
} | ||
|
||
var parentStyle = window.getComputedStyle(ancestorNode); | ||
// Compare fonts | ||
if (_getFonts(nodeStyle)[0] !== _getFonts(parentStyle)[0]) { | ||
const ancestorStyle = window.getComputedStyle(ancestorNode); | ||
let curNode = node; | ||
while (curNode !== ancestorNode) { | ||
const curNodeStyle = window.getComputedStyle(curNode); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In the first iteration curNodeStyle === nodeStyle. Lets avoid calling this expensive function twice. |
||
|
||
// text decoration styles are not inherited so we need | ||
// to check each node from the target node to the | ||
// ancestor node | ||
const hasStyle = ['text-decoration-line', 'text-decoration-style'].some( | ||
straker marked this conversation as resolved.
Show resolved
Hide resolved
|
||
cssProp => { | ||
const ancestorValue = ancestorStyle.getPropertyValue(cssProp); | ||
const curNodeValue = curNodeStyle.getPropertyValue(cssProp); | ||
|
||
/* | ||
For logic purposes we can treat the target node and all inline ancestors as a single logic point since if any of them define a text-decoration style it will visually apply that style to the target. | ||
|
||
A target node is distinct if it defines a text-decoration and either the ancestor does not define one or the target's text-decoration is different than the ancestor. A target that does not define a text-decoration can never be distinct from the ancestor. | ||
*/ | ||
return ( | ||
curNodeValue !== 'none' && | ||
(ancestorValue === 'none' || curNodeValue !== ancestorValue) | ||
); | ||
} | ||
); | ||
|
||
if (hasStyle) { | ||
return true; | ||
} | ||
|
||
curNode = getComposedParent(curNode); | ||
} | ||
|
||
// font styles are inherited so we only need to check | ||
// the target node | ||
if (_getFonts(nodeStyle)[0] !== _getFonts(ancestorStyle)[0]) { | ||
straker marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return true; | ||
} | ||
|
||
var hasStyle = [ | ||
'text-decoration-line', | ||
'text-decoration-style', | ||
'font-weight', | ||
'font-style', | ||
'font-size' | ||
].reduce((result, cssProp) => { | ||
let hasStyle = ['font-weight', 'font-style', 'font-size'].some(cssProp => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe this stuff that inherits should go above the while loop. Also, a comment here would be nice to indicate this isn't in the while loop because it inherits. After not having thought about this for three weeks, it took me a bit to realise why you did it this way. |
||
return ( | ||
result || | ||
nodeStyle.getPropertyValue(cssProp) !== | ||
parentStyle.getPropertyValue(cssProp) | ||
ancestorStyle.getPropertyValue(cssProp) | ||
); | ||
}, false); | ||
}); | ||
|
||
var tDec = nodeStyle.getPropertyValue('text-decoration'); | ||
const tDec = nodeStyle.getPropertyValue('text-decoration'); | ||
if (tDec.split(' ').length < 3) { | ||
// old style CSS text decoration | ||
hasStyle = | ||
hasStyle || tDec !== parentStyle.getPropertyValue('text-decoration'); | ||
hasStyle || tDec !== ancestorStyle.getPropertyValue('text-decoration'); | ||
} | ||
|
||
return hasStyle; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we can just push any inline ancestor. If the element has non-link text in it is no longer a distinguishing style. Take something like the following, that should not pass because it has a bold parent:
This probably does need to do some filtering. It doesn't matter if it's just a comma or something, but whole worlds I don't think counts anymore.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The above issue was resolved for strong / underline, but not for pseudo elements. This shouldn't be passed because of that pseudoElm class:
It makes me wonder whether checking for pseudo elms should be done inside
elementIsDistinct
to avoid the repeat?