dperini / nwsapi Goto Github PK
View Code? Open in Web Editor NEWFast CSS Selectors API Engine
License: MIT License
Fast CSS Selectors API Engine
License: MIT License
element.matches
can throw an unexpected error for certain selectors.
Here is an example to reproduce the issue in the browser (assuming nwsapi.js is included in a <script>
tag):
const div = document.createElement('div');
div.innerHTML = '<div class="b"><div class="c"></div></div>';
//document.documentElement.appendChild(div); // Doesn't matter if this is executed or not
const c = div.querySelector('.c');
const selector = '.a:nth-last-of-type(1) .b .c';
console.log(c.matches(selector)); // Okay with native DOM
console.log(NW.Dom.match(selector, c)); // Throws
Uncaught TypeError: Cannot read property 'parentElement' of null
at Array.Resolver (eval at compile (nwsapi.js:768), <anonymous>:3:129)
at match_assert (nwsapi.js:1351)
at Object._matches [as match] (nwsapi.js:1415)
This line https://github.com/dperini/nwsapi/blob/master/src/nwsapi.js#L519 gives an exception on IE11:
Unable to get property 'indexOf' of undefined or null reference
.
document.contentType
is undefined.
Hello! Thanks for this amazing work!
I found that the nwsapi
tries to select pseudo-classes when the given class name includes :
with preceding \
. And this naming pattern is used by famous CSS library tailwindCSS
. Is there way to handle correctly?
Thank you!
Trying with this code, but returns a void array:
NW.Dom.registerSelector('shadow', /\:(shadow)/i, (function(global) {
return function(match, source, mode, callback) {
source = 'e=e.shadowRoot;' + source;
return { 'source': source, 'status': true };
}
})(this));
console.log(NW.Dom.select("body page-1:shadow footer", document));
I ran into an issue where I was using jsdom which uses nwsapi for matching selectors and it was giving me the error SyntaxError: ':focus-visible' is not a valid selector
. It doesn't seem like I should be getting this error because in the wiki for nwsapi, it says that the :focus-visible
is supported.
Then I looked through the nwsapi repo and didn't see focus-visible
where I thought it should exist. Here with the other user actions: https://github.com/dperini/nwsapi/blob/master/src/nwsapi.js#L83
It would be great if this could be supported. Alternatively, the documentation could be updated explaining that it is actually not supported and why.
Reproduce:
<script
type="text/javascript"
src="https://cdn.jsdelivr.net/npm/[email protected]/src/nwsapi.js"
></script>
<script>
NW.Dom.match(":focus-visible", document, () => {});
</script>
Results in Uncaught DOMException: ':focus-visible' is not a valid selector
.
On another note, it looks like focus-within
throws the same error, even though it looks like it is available in the source code. Not sure why that would be though.
I found a difference between nwsapi and browsers (Firefox and Chromium). For an XML document with a capitalized element, the querySelector()
method doesn't work when searching by putting two elements in the selector.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Test case</title>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/src/nwsapi.js" onload="NW.Dom.install()"></script>
</head>
<body>
<script>
onload = function() {
const xml = '<?xml version="1.0"?><Foo><bar></bar></Foo>';
const dom = new window.DOMParser().parseFromString(xml, 'text/xml');
console.log('0. Expected [Foo]', dom.querySelectorAll('Foo')); // Passed
console.log('1. Expected []', dom.querySelectorAll('foo')); // Passed
console.log('2. Expected [bar]', dom.querySelectorAll('bar')); // Passed
console.log('3. Expected []', dom.querySelectorAll('foo bar')); // Passed
console.log('4. Expected [bar]', dom.querySelectorAll('Foo bar')); // Failed!
const xml2 = xml.toLowerCase();
const dom2 = new window.DOMParser().parseFromString(xml2, 'text/xml');
console.log('10. Expected [bar]', dom2.querySelectorAll('bar')); // Passed
console.log('11. Expected []', dom2.querySelectorAll('Bar')); // Passed
console.log('12. Expected [bar]', dom2.querySelectorAll('foo bar')); // Passed
console.log('13. Expected []', dom2.querySelectorAll('Foo bar')); // Failed!
console.log('14. Expected []', dom2.querySelectorAll('FOO bar')); // Failed!
console.log('15. Expected []', dom2.querySelectorAll('foo BAR')); // Passed
console.log('16. Expected []', dom2.querySelectorAll('FOO BAR')); // Passed
};
</script>
</body>
</html>
https://html.spec.whatwg.org/#selector-autofill
They should probably never match anything in nwsapi, but it'd be good if they didn't throw exceptions
I'm using [email protected]
, which has [email protected]
as a dependency. The following script runs without errors (it outputs true
):
const { JSDOM } = require("jsdom");
const dom = new JSDOM(`
<!DOCTYPE html>
<body>
<div class="section">
<p class="text">
<span class="important">IMPORTANT</span>
</p>
</div>
</body>
`);
const el = dom.window.document.querySelector(".section > > .important");
console.log(el.nodeName === "SPAN");
However, in a browser, .section > > .important
is an invalid selector, as shown by this JS Bin. It throws a DOMException
.
I suppose the issue is that the space between the two child combinators is converted to a wildcard selector, but that creates an inconsistency between different selector engines and environments.
See https://github.com/web-platform-tests/wpt/blob/7d99d2ca0def8468acfaee9aa15076a68efb21ca/shadow-dom/focus/focus-selector-delegatesFocus.html. Essentially, with the following setup:
<!DOCTYPE html>
<body>
<script>
const host = document.createElement("div");
host.attachShadow({ mode: "open" });
document.body.appendChild(host);
const shadowChild = document.createElement("div");
shadowChild.innerText = "foo";
shadowChild.tabIndex = 0;
host.shadowRoot.appendChild(shadowChild);
shadowChild.focus();
console.log(NW.Dom.match(shadowChild, ":focus"), "element in shadow tree matches :focus");
console.log(NW.Dom.match(host, ":focus"), "host matches :focus");
</script>
However, currently only the latter returns true, since document.activeElement
is host
. (However, host.shadowRoot.activeElement
is shadowChild
.)
The linked file has more examples, some using <slot>
.
TypeError: fragment.getElementById is not a function
at hasDuplicateId (node_modules\nwsapi\src\nwsapi.js:271:34)
at byId (node_modules\nwsapi\src\nwsapi.js:301:33)
at node_modules\nwsapi\src\nwsapi.js:252:61
at Object.Resolver [as factory] (eval at compile (node_modules\nwsapi\src\nwsapi.js:687:17), <anonymous>:3:71)
at Object._querySelectorAll [as select] (node_modules\nwsapi\src\nwsapi.js:1287:23)
at DocumentFragmentImpl.<anonymous> (lib\jsdom\living\nodes\ParentNode-impl.js:68:24)
Here the last line in the stack trace is essentially
const list = matcher.select(selectors, someDocumentFragment);
The only difference is that :is(…)
follows @media
query‑like invalidation:
Hi! This is my case:
...
<div id="my-id">
<div>
<a><span/></a>
.... any number of a > span
<span>
</div>
... any number of the same structure
<div>...</div>
</div>
...
I need separate values from a>span and div>span within function that holds ('#my-id')
I use function:
[...doc.querySelectorAll('#my-id > div')].map(row => {{
rows: row.querySelectorAll('a > span') // ok, found all <a>
root: row.querySelector(?)
}});
I have tried: > span
, span:root
, span:not(a > span)
that are not valid and span:last-child
,span:last-of-type
that return span inside first tag
How do I find the tag inside the row?
This was originally reported as part of the jsdom
repo here.
I decided to try to fix it (because I had the exact same issue) and was able to track down the issue until here.
So here's the case: given the following XML DOM tree:
<root>
<aB>
<c></c>
</aB>
<cd>
<e></e>
</cd>
</root>
This query: aB *
doesn't return anything while it should match the <c>
element.
Here's the full reproduction code:
NW.Dom.install();
const xml = `
<root>
<aB>
<c></c>
</aB>
<cd>
<e></e>
</cd>
</root>
`;
const dom = new window.DOMParser().parseFromString(xml, 'text/xml');
const ko = dom.querySelectorAll('aB *').length; // 0 (should be 1)
const ok = dom.querySelectorAll('cd *').length; // 1
console.log({ko,ok});
And here's a fiddle hosting it.
I don't know this library codebase well, but I investigated a bit and I have the feeling that this is caused by the fact that the selector is converted to lower case while the element localName
is not.
Hence the missing match in the compiled resolver code.
What I also noticed is that if you parse the same code as HTML, with:
const dom = new window.DOMParser().parseFromString(xml, 'text/xml');
It works as expected, I guess because all the tags are automatically converted to lower case.
The :placeholder-shown
pseudo-class has pretty good support in recent browsers. It matches <input>
elements which are currently showing their placeholder text. This can probably be implemented by checking that the element has a placeholder, but isn't currently focused.
Specification: https://drafts.csswg.org/selectors-4/#placeholder
nwsapi is a brilliant piece of work - wow!
Is there any interest in adding full CSS3 namespace support? This would include adding support for selectors that contain namespaced prefixes such as:
*|myelem
(this is actually supported natively by querySelector
/querySelectorAll
native methods in browsers)
myns|*
(unsupported natively)
myns|myelem
(unsupported natively)
*[*|myattr]
(supported natively)
*[myns|*]
(unsupported natively)
*[myns|myattr]
(unsupported natively)
Note that what I'm asking about here is not solved by the simplistic approach of "just use an escaped :
character". True namespace support requires being able to resolve namespaces based on the location of the element in the DOM, what namespaces are defined in the markup and how namespace prefixes are associated to a URI.
The document.evaluate
XPath call provides an example of one way this functionality might be provided. It uses a 'namespace resolver' to assist the call in determining the namespace. See the section "Implementing a User Defined Namespace Resolver" here:
I currently use a very old jQuery plugin that provides true namespace support to jQuery, but it hasn't been updated in a long time and is only usable with the jQuery 1.X series. Replacing that with nwsapi would be very nice indeed :-).
Thanks!
A simple repro:
<!doctype html>
<body>
<p></p>
<script src="src/nwsapi.js"></script>
<script>
NW.Dom.install();
document.body.innerHTML += [document.body.querySelector('P') != null, document.body.querySelector('p') != null].join(', ');
</script>
With 2.2.1 this prints false, true
, when it should be true, true
.
Per spec, "All Selectors syntax is ASCII case-insensitive".
I suspect this is due to #37 or one of the followup commits, though I haven't investigated.
(Discovered because this broke jsdom, which broke ecmarkup, which broke one of the JavaScript specifications.)
nwsapi needs an updated version of nwmatcher's Supported Selectors page, which includes all the new selectors it supports.
The following attribute selector [name=abci]
is compiled into if(((/^abc$/i).test(...)...
that is obviously incorrect. The correct variant is if(((/^abci$/).test(...)...
.
The possible fix is located in my fork of your library: #59.
Hey @dperini, would you like to release new version with recent fixes? v2.2.0 is pretty outdated.
Hi,
when using an id which starts with a digit, nwsapi throws a "SyntaxError: '...' is not a valid selector", I guess because of the identifier regexp.
As mentioned in https://www.w3.org/TR/html4/types.html#type-id, ID and NAME tokens must begin with a letter ([A-Za-z]).
But, as described in https://html.spec.whatwg.org/multipage/dom.html#global-attributes:the-id-attribute-2, this constraint is not in place anymore for html5.
For this reason, could nwsapi be updated to take this into account maybe through an option?
Thanks,
Alessandro
NWSAPI incorrectly reports the selector [data-x='],']
(selecting elements with data-x
attribute value of exactly ],
- eg. <div data-x='],'></div>
) as invalid. This is in fact a valid selector (at least in as much as browsers seem to recognize it just fine - I've not dug into the CSS grammar to check if it is).
Neither ]
nor ,
alone seem to trigger the invalid selector error, and it is possible to work around it by escaping both characters ],
as \]\,
in the value.
JSFiddle repro: https://jsfiddle.net/2wemxrp3/
Hi,
do you have any plans for updating the npm package? I noticed a vulnerability issue in the 2.2.0 package version:
https://security.snyk.io/vuln/SNYK-JS-NWSAPI-2841516
It seems that the master branch in this repo contains a fix for it.
Thanks!
Case in point:
Lines 86 to 87 in 4077276
'use strict';
const jsdom = require("jsdom");
const { JSDOM } = jsdom;
const dom = new JSDOM(`
<div aria-label="Account Information">
<a href="https://www.example.com/foo" target="_blank">Foo</a>
</div>
`);
const els = dom.window.document.querySelectorAll(
'div[aria-label] a[href="https://www.example.com/foo"]'
);
console.log(els);
With jsdom 13.2.0 and nwsapi 2.0.9, this code correctly finds one element. With nwsapi 2.1.0, this code fails to find any elements.
I noticed that nwsapi 2.1.0 fixes jsdom/jsdom#2403, which also has to do with attribute selectors, so I wonder if that fix might be related to this issue.
Hello,
More a question than an issue: I'm going to take a look at adding tests for the :scope
pseudo-class - cf. jsdom/jsdom#2028 - however from what I see in the test/scope/*.html
files it seems that nothing is automated.
Should I setup some automation (with whichever test framework you want) or do I just add new tests following the same format with console logs?
Thanks
While using react testing library that uses this library, I have encountered a difficult-to-find error when running unit tests that were just breaking and showing the following message:
node_modules/nwsapi/src/nwsapi.js:893
source = ‘n=e;while((e=e.parentElement)){’ + source + ‘}e=n;’;
After hours of investigation, I have found out that one of the React styled components I was using had a tiny mistake in its styles.
Something like:
tbody th {
vertical-align: middle;
> span {
display: inline-block;
padding: 0;
}
}ç
Where a character was out of the parenthesis.
nwapi version: 2.2.0
Live example: https://jsbin.com/folowijuvi/edit?html,js,console,output
NW.Dom.install();
console.log(NW.Dom.select(':scope', document.body));
console.log(NW.Dom.select(':scope, :scope', document.body))
// []
// DOMException [SyntaxError]: unknown pseudo-class selector ':scope'
// emit@https://unpkg.com/[email protected]/src/nwsapi.js:565:17
// compileSelector@https://unpkg.com/[email protected]/src/nwsapi.js:1292:21
// compile@https://unpkg.com/[email protected]/src/nwsapi.js:753:16
// collect@https://unpkg.com/[email protected]/src/nwsapi.js:1553:24
// _querySelectorAll@https://unpkg.com/[email protected]/src/nwsapi.js:1518:36
The real world use case was something like ':scope > span, :scope > div
.
nwsapi is nearly passing all Web Platform Tests that browsers do, which is very exciting. Since these tests are used by browsers to ensure that they are compatible with each other, it would be excellent if it could pass the final ones as well. These are the last tests from the dom/nodes/
directory which pass in browsers, but fail in nwsapi:
dom/nodes/ParentNode-querySelector-All.html:
dom/nodes/Element-closest.html:
Let me know if you have any questions about the tests.
edit: full revoke. see PR #40
edit: partial revoke: nwsapi does use different resolvers
for base-element vs pseudo-element:
if (!(e.nodeType == 1)) {
.... this condition is added for the selector body>div::after
compared to body>div
nodeType 1 is ELEMENT_NODE
module.exports = Object.freeze({
ELEMENT_NODE: 1,
ATTRIBUTE_NODE: 2,
TEXT_NODE: 3,
CDATA_SECTION_NODE: 4, // historical
ENTITY_REFERENCE_NODE: 5, // historical
ENTITY_NODE: 6, // historical
PROCESSING_INSTRUCTION_NODE: 7,
COMMENT_NODE: 8,
DOCUMENT_NODE: 9,
DOCUMENT_TYPE_NODE: 10,
DOCUMENT_FRAGMENT_NODE: 11,
NOTATION_NODE: 12 // historical
});
--
currently nwsapi compiles different resolvers
for (base-) elements and pseudo-elements
for example it compiles two different resolvers
for the selectors div
and div::before
but it should compile only one resolver
since all resolvers return the same (base-) element
so, selectors
in function _matches(selectors, element, callback)
should be processed with something like
const baseSel = selectors.replace(/::[a-z-]+/gi, '')
or more verbose
const pseudoElementNames = [
'after',
'backdrop'
'before',
'cue',
'cue-region',
'first-letter',
'first-line',
'grammar-error',
'marker',
//'part()',
'placeholder',
'selection',
//'slotted()',
'spelling-error',
];
const re = new RegExp('::('+pseudoElementNames.join('|')+')', 'gi')
const baseSel = selectors.replace(re, '')
Since jsdom isn't in the browser, things like Element
aren't global there, so things like https://github.com/dperini/nwsapi/blob/master/src/nwsapi.js#L1334-L1337 don't work there (and cause crashes)
I wonder if install/uninstall could be removed from the jsdom-facing version entirely.
An invalid pseudo-class that begins with one which is valid such as :linkexample
will currently be accepted and compile to something unintended. It should throw a unknown pseudo-class selector
-error instead.
:scope
fails to work with XML documents which have HTML-incompatible ids. Example:
doc = new DOMParser().parseFromString(`<?xml version="1.0" encoding="UTF-8"?><outer id='1a'><inner id='a'><inner></inner></inner></outer>`, "text/xml")
doc.firstChild.querySelectorAll(':scope > inner') # WAI
This works on Chrome. However, using nwsapi fails:
NW.Dom.select(':scope inner', doc.firstChild) # fails
The failure stems from :scope pseudo-class being replaced with element references which then create a selector that is invalid since HTML id attributes can't start with numbers: Uncaught DOMException: 'outer#1a inner' is not a valid selector
edit: hit enter too fast
In the latest release you added jsdom
as a dependency, but as it is only used for tests it should a dev dependency to avoid any package user installing it.
Currently, NWSAPI tests are a mess that have to be run in the browser.
I recommend creating a test suite that can be ran using a test framework (eg.: Jest) in a CI environment (eg.: GitHub Actions or Travis CI).
This was originally reported as part of the jsdom
repo here.
I decided to try to fix it (because I had the exact same issue) and was able to track down the issue until here.
So here's the case: given the following DOM tree:
<div>
<div class="ok"></div>
<div class="ok">
<div class="ko"></div>
</div>
</div>
Getting a reference to the root <div>
and doing the following query:
rootElement.querySelectorAll(':scope > div')
Doesn't only return the 2 expected "ok" divs but also the "ko" one.
Here's the full reproduction code allowing to easily switch between an ok and a ko case:
NW.Dom.install();
const SHOW_BUG = true;
const rootElementTagName = SHOW_BUG ? 'div' : 'main';
const html = `<${rootElementTagName}>
<div class="ok"></div>
<div class="ok">
<div class="ko"></div>
</div>
</${rootElementTagName}>`;
const dom = new window.DOMParser().parseFromString(html,'text/html');
const rootElement = dom.querySelector(rootElementTagName);
const queryResult = rootElement.querySelectorAll(':scope > div');
for (const element of queryResult) {
console.log(element.className);
}
// This should always output:
// - ok
// - ok
//
// But the actual output is:
// - ok
// - ok
// - ko
And here's a fiddle hosting it.
I don't know this library codebase well, but I investigated a bit and I have the feeling that this is caused by the fact that this pattern : :scope > div
is turned into a more generic one : div > div
which is solved using a parent tag name resolution strategy and ultimately returns all the element globally matching this pattern: div > div
, somewhat ignoring the element context.
I hope that this can help saving time to fix it.
Given this html page:
<!DOCTYPE html>
<script type="text/javascript" src="src/nwsapi.js"></script>
<div>
<p>first</p>
<p>second</p>
<p>third</p>
</div>
The selector p:nth-child(2n + 1)
only works if SIMPLENOT
is false:
The same selector without whitespace, p:nth-child(2n+1)
, works in both modes. The spec allows whitespace, so ideally both selectors should always work.
In addition, prettier seems to autoformat CSS selectors with spaces in this situation. So this bug leads to a sad case where autoformatting your code with prettier can cause unit tests to break in the Jest -> JSDOM -> NWSAPI stack (or anything else relying on JSDOM to run tests).
Thanks for the help!
Edit: I believe the issue goes beyond SIMPLE_NOT
, for example, p:nth-child(2n - 1)
doesn't work in either mode.
Hello, deno-dom
uses this library to emulate the DOM in Deno. However, executing JavaScript from strings can result in possible insecure security flaws within code. As a result, secure web platforms such as Deno Deploy have disabled string code execution, which makes nwsapi.js
unusable in secure contexts due to its use of the Function
constructor for codegen in nwsapi.js, I am going to try and fix this later today after I get home but just going to create an issue in response to another issue in the deno-dom
repo about deno-dom
not working on Deno Deploy.
I wonder why you wouldn't normallize 'more' the selector there, by uppercasing html tags, and camelCasing svg tags (ex: Div.foo Path
becoming DIV.foo path
), so that you don't need hasMixedNamespace
anymore
ar
Edit: Oh crap, some SVG tags are also HTML ones https://github.com/wooorm/svg-tag-names/blob/master/index.json. that explains
I ran into some weird :not(...)
selectors on Slack's homepage (in https://a.slack-edge.com/acdbf/style/rollup-marketing.css) that nwsapi doesn't support.
Repro:
new (require('jsdom').JSDOM)('').window.document.querySelector(':not(:lang(ja))')
SyntaxError: unknown pseudo-class selector ':not(:lang(ja))'
at emit (/home/andreas/work/assetgraph/node_modules/nwsapi/src/nwsapi.js:529:17)
at compileSelector (/home/andreas/work/assetgraph/node_modules/nwsapi/src/nwsapi.js:1171:17)
at compile (/home/andreas/work/assetgraph/node_modules/nwsapi/src/nwsapi.js:718:19)
at collect (/home/andreas/work/assetgraph/node_modules/nwsapi/src/nwsapi.js:1409:18)
at _querySelectorAll (/home/andreas/work/assetgraph/node_modules/nwsapi/src/nwsapi.js:1349:18)
at Object._querySelector [as first] (/home/andreas/work/assetgraph/node_modules/nwsapi/src/nwsapi.js:1283:14)
at DocumentImpl.<anonymous> (/home/andreas/work/assetgraph/node_modules/jsdom/lib/jsdom/living/nodes/ParentNode-impl.js:65:42)
at DocumentImpl.querySelector (/home/andreas/work/assetgraph/node_modules/jsdom/lib/jsdom/utils.js:123:45)
at Document.querySelector (/home/andreas/work/assetgraph/node_modules/jsdom/lib/jsdom/living/generated/Document.js:689:45)
It works fine in Firefox and Chrome with document.querySelector
.
new DOMException(message, SyntaxError());
should be
new global.DOMException(message, "SyntaxError");
2.2.0
Live example: jsbin
NW.Dom.install();
NW.Dom.select('.foo, .foo, .bar', document.body); // pass
NW.Dom.select('.foo, .foo, .bar', document.body); // error
// nwsapi.js:1450 Uncaught TypeError: Cannot read property '0' of undefined
// at Object._querySelectorAll [as select]
This is a real conner case, this issue only happens when there is a duplicate class selector and different class selector in a compound selector and when the selector runs multiple times. Context in the original issue.
This has always been part of the spec in https://html.spec.whatwg.org/#the-directionality , but it was not tested until recently. Tests were added in web-platform-tests/wpt@aaf496b#diff-fdae72426568d9ed77d62e6784fb362e247cffac722f639fd436e024b595adda and nwsapi + jsdom do not pass them.
Not a very high priority, but I thought you'd like to know!
function compileSelector in nwsapi.js
source = 'n=e;while((e=e.parentElement)){' + source + '}e=n;';
source grows to infinite length, until RangeError: Invalid string length
normal source.length
are around 1000 bytes
with infinite loop, source.length
grows to the maximum string length of 1GB
the selector _:-ms-fullscreen
comes from deepl.com/css/lmt.$d783c6.css
.lmt--web .lmt__side_container--target .lmt__ad_charLimit_container _:-ms-fullscreen
the problem is
default:
emit('\'' + selector_string + '\'' + qsInvalid);
break;
}
// end of switch symbol
which only breaks the switch (symbol) {
block, but not the while (selector) {
loop -> deadloop
the parser should seek to the next comma or to end of selector string
workarounds:
class CustomResourceLoader extends jsdom.ResourceLoader {
fetch(url, options) {
// ignore all styles
if (url.endsWith('.css')) {
return Promise.resolve(Buffer.from(''));
}
// patch style
if (url == 'https://example.com/path/to/style.css')) {
var str = require('fs').readFileSync('style.patched.css', 'utf8');
return Promise.resolve(Buffer.from(str));
}
return super.fetch(url, options);
}
}
const resourceLoader = new CustomResourceLoader();
const dom = new jsdom.JSDOM('', { resources: resourceLoader });
The spec changed in this regard in whatwg/html@1e0ee7f . There is a test in https://github.com/web-platform-tests/wpt/blob/master/html/semantics/selectors/pseudo-classes/link.html
The :focus-within
pseudo-class has pretty good support in recent browsers. In addition to matching the same element as :focus
, it'll match elements which have focused descendant elements.
Specification: https://drafts.csswg.org/selectors-4/#the-focus-within-pseudo
Test: https://github.com/w3c/web-platform-tests/blob/master/css/selectors/focus-within-009.html
import { JSDOM } from 'jsdom'
const doc = new JSDOM(`
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
</head>
<body>
</body>
</html>
`).window.document
doc.querySelector('.js-sns-icon-container ~ h2 ~ h2 ~ .spaceit_pad:not(.js-sns-icon-container ~ h2 ~ h2 ~ h2 ~ .spaceit_pad)')
throws
'.js-sns-icon-container ~ h2 ~ h2 ~ .spaceit_pad:not(.js-sns-icon-container ~ h2 ~ h2 ~ h2 ~ .spaceit_pad)' is not a valid selector
Trying to query for .js-sns-icon-container ~ h2 ~ h2 ~ .spaceit_pad:not(.js-sns-icon-container ~ h2 ~ h2 ~ h2 ~ .spaceit_pad)
in browsers work completly fine (Tried in chrome and FF).
Hi there!
I've run into a few issues using the :focus-within
selector with nwsapi v2.2.0.
Firstly, the current regex doesn't match correctly:
':focus-within'.match(/^:(?:(hover|active|focus|focus-within))(.*)/i)
Result:
[
':focus-within',
'focus',
'-within'
]
Changing the regex as follows, fixes this issue:
':focus-within'.match(/^:(?:(hover|active|focus-within|focus))(.*)/i)
Result:
[
':focus-within',
'focus-within',
''
]
However, I haven't PR'd this because now there appears to be a recursion issue as my node process consumes 100% CPU and does not end (at least not for as long as I have been willing to wait).
I am using nwsapi as via jest (with vue-test-utils), so I'm unsure whether this issue is with nwsapi or not, and I'm not sure how to further debug it.
Any help would be appreciated!
@dperini This looks great, but the selector issues for XML seem to be the as in nwmatcher.
This works::
let parser = new window.DOMParser()
let string = `<?xml version="1.0"?><cp:coreProperties xmlns:cp="http://schemas.openxmlformats.org/package/2006/metadata/core-properties" xmlns:dc="http://purl.org/dc/elements/1.1/"><dc:title></dc:title></cp:coreProperties>`
let dom = parser.parseFromString(string, 'text/xml')
let el = dom.querySelector('coreProperties')
But if one replaces the querySelector with the one from nwsapi, it does not::
NW.Dom.install()
let parser = new window.DOMParser()
let string = `<?xml version="1.0"?><cp:coreProperties xmlns:cp="http://schemas.openxmlformats.org/package/2006/metadata/core-properties" xmlns:dc="http://purl.org/dc/elements/1.1/"><dc:title></dc:title></cp:coreProperties>`
let dom = parser.parseFromString(string, 'text/xml')
let el = dom.querySelector('coreProperties')
What does however work is::
dom.querySelector('cp\\:coreProperties')
Which in turn does not work with the native querySelector found in browsers.
Same behavior as in nwmatcher seen in jsdom/jsdom#2159
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.