Skip to content

Commit

Permalink
Update filterSelector() for nwsapi
Browse files Browse the repository at this point in the history
  • Loading branch information
asamuzaK committed Dec 14, 2024
1 parent 619f2fe commit 3a60def
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 20 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
},
"types": "types/index.d.ts",
"dependencies": {
"@asamuzakjp/nwsapi": "^2.2.24",
"@asamuzakjp/nwsapi": "^2.2.27",
"bidi-js": "^1.0.3",
"css-tree": "^3.1.0",
"is-potential-custom-element-name": "^1.0.1"
Expand Down
6 changes: 4 additions & 2 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ export class DOMSelector {
this.#finder.onError(e, opt);
}
const document = node.ownerDocument;
if (document === this.#document && document.contentType === 'text/html') {
if (document === this.#document && document.contentType === 'text/html' &&
node.parentNode) {
const filterOpt = {
complex: REG_COMPLEX.test(selector),
compound: false,
Expand Down Expand Up @@ -98,7 +99,8 @@ export class DOMSelector {
this.#finder.onError(e, opt);
}
const document = node.ownerDocument;
if (document === this.#document && document.contentType === 'text/html') {
if (document === this.#document && document.contentType === 'text/html' &&
node.parentNode) {
const filterOpt = {
complex: REG_COMPLEX.test(selector),
compound: false,
Expand Down
16 changes: 10 additions & 6 deletions src/js/constant.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,29 +65,33 @@ export const N_TH =
`nth-(?:last-)?(?:child|of-type)\\(\\s*(?:even|odd|${ANB})\\s*\\)`;
// SUB_TYPE: attr, id, class, pseudo-class, note that [foo|=bar] is excluded
export const SUB_TYPE = '\\[[^|\\]]+\\]|[#.:][\\w-]+';
export const SUB_TYPE_WO_PSEUDO = '\\[[^|\\]]+\\]|[#.][\\w-]+';
// TAG_TYPE: *, tag
export const TAG_ID_CLASS = '(?:[A-Za-z][\\w-]*|[#.][\\w-]+)';
export const TAG_TYPE = '\\*|[A-Za-z][\\w-]*';
export const TAG_TYPE_I = '\\*|[A-Z][\\w-]*';
export const COMPOUND = `(?:${TAG_TYPE}|(?:${TAG_TYPE})?(?:${SUB_TYPE})+)`;
export const COMPOUND_WO_PSEUDO =
`(?:${TAG_TYPE}|(?:${TAG_TYPE})?(?:${SUB_TYPE_WO_PSEUDO})+)`;
export const COMBO = '\\s?[\\s>~+]\\s?';
export const COMPLEX = `${COMPOUND}(?:${COMBO}${COMPOUND})*`;
export const DESCEND = '\\s?[\\s>]\\s?';
export const NESTED_LOGICAL_A =
export const NESTED_LOGIC_A =
`:is\\(\\s*${COMPOUND}(?:\\s*,\\s*${COMPOUND})*\\s*\\)`;
export const NESTED_LOGICAL_B =
export const NESTED_LOGIC_B =
`:is\\(\\s*${COMPLEX}(?:\\s*,\\s*${COMPLEX})*\\s*\\)`;
export const COMPOUND_A =
`(?:${TAG_TYPE}|(?:${TAG_TYPE})?(?:${SUB_TYPE}|${NESTED_LOGICAL_A})+)`;
`(?:${TAG_TYPE}|(?:${TAG_TYPE})?(?:${SUB_TYPE}|${NESTED_LOGIC_A})+)`;
export const COMPOUND_B =
`(?:${TAG_TYPE}|(?:${TAG_TYPE})?(?:${SUB_TYPE}|${NESTED_LOGICAL_B})+)`;
`(?:${TAG_TYPE}|(?:${TAG_TYPE})?(?:${SUB_TYPE}|${NESTED_LOGIC_B})+)`;
export const COMPOUND_I =
`(?:${TAG_TYPE_I}|(?:${TAG_TYPE_I})?(?:${SUB_TYPE})+)`;
export const COMPLEX_L = `${COMPOUND_B}(?:${COMBO}${COMPOUND_B})*`;
export const LOGICAL_COMPLEX =
export const LOGIC_COMPLEX =
`(?:is|not)\\(\\s*${COMPLEX_L}(?:\\s*,\\s*${COMPLEX_L})*\\s*\\)`;
export const LOGICAL_COMPOUND =
export const LOGIC_COMPOUND =
`(?:is|not)\\(\\s*${COMPOUND_A}(?:\\s*,\\s*${COMPOUND_A})*\\s*\\)`;
export const HAS_COMPOUND = `has\\([\\s>~+]?\\s*${COMPOUND_WO_PSEUDO}\\s*\\)`;

/* array */
export const KEY_FORM_FOCUS =
Expand Down
25 changes: 15 additions & 10 deletions src/js/utility.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,16 @@ import isCustomElementName from 'is-potential-custom-element-name';
/* constants */
import {
DOCUMENT_FRAGMENT_NODE, DOCUMENT_NODE, DOCUMENT_POSITION_CONTAINS,
DOCUMENT_POSITION_PRECEDING, ELEMENT_NODE, KEY_INPUT_BUTTON, KEY_INPUT_EDIT,
KEY_INPUT_TEXT, LOGICAL_COMPLEX, LOGICAL_COMPOUND, N_TH, PSEUDO_CLASS,
TEXT_NODE, TYPE_FROM, TYPE_TO
DOCUMENT_POSITION_PRECEDING, ELEMENT_NODE, HAS_COMPOUND, KEY_INPUT_BUTTON,
KEY_INPUT_EDIT, KEY_INPUT_TEXT, LOGIC_COMPLEX, LOGIC_COMPOUND, N_TH,
PSEUDO_CLASS, TARGET_LINEAL, TARGET_SELF, TEXT_NODE, TYPE_FROM, TYPE_TO
} from './constant.js';
const REG_LOGICAL_COMPLEX =
new RegExp(`:(?!${PSEUDO_CLASS}|${N_TH}|${LOGICAL_COMPLEX})`);
const REG_LOGICAL_COMPOUND =
new RegExp(`:(?!${PSEUDO_CLASS}|${N_TH}|${LOGICAL_COMPOUND})`);
const REG_LOGIC_COMPLEX =
new RegExp(`:(?!${PSEUDO_CLASS}|${N_TH}|${LOGIC_COMPLEX})`);
const REG_LOGIC_COMPOUND =
new RegExp(`:(?!${PSEUDO_CLASS}|${N_TH}|${LOGIC_COMPOUND})`);
const REG_LOGIC_HAS_COMPOUND =
new RegExp(`:(?!${PSEUDO_CLASS}|${N_TH}|${LOGIC_COMPOUND}|${HAS_COMPOUND})`);
const REG_WO_LOGICAL = new RegExp(`:(?!${PSEUDO_CLASS}|${N_TH})`);

/**
Expand Down Expand Up @@ -671,7 +673,7 @@ export const filterSelector = (selector, opt = {}) => {
if (!selector || typeof selector !== 'string') {
return false;
}
const { complex, compound, descend, simple } = opt;
const { complex, compound, descend, simple, target } = opt;
// exclude simple selector and compound selector
if (simple || compound) {
return false;
Expand All @@ -695,11 +697,14 @@ export const filterSelector = (selector, opt = {}) => {
if (selector.includes(':')) {
if (descend) {
return false;
} else if ((target === TARGET_SELF || target === TARGET_LINEAL) &&
/:has\(/.test(selector)) {
return !REG_LOGIC_HAS_COMPOUND.test(selector);
} else if (/:(?:is|not)\(/.test(selector)) {
if (complex) {
return !REG_LOGICAL_COMPLEX.test(selector);
return !REG_LOGIC_COMPLEX.test(selector);
} else {
return !REG_LOGICAL_COMPOUND.test(selector);
return !REG_LOGIC_COMPOUND.test(selector);
}
} else {
return !REG_WO_LOGICAL.test(selector);
Expand Down
58 changes: 57 additions & 1 deletion test/utility.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ import { afterEach, beforeEach, describe, it } from 'mocha';

/* test */
import * as util from '../src/js/utility.js';
import { WALKER_FILTER } from '../src/js/constant.js';
import {
TARGET_SELF, TARGET_LINEAL, WALKER_FILTER
} from '../src/js/constant.js';

describe('utility functions', () => {
const domStr = `<!doctype html>
Expand Down Expand Up @@ -2336,5 +2338,59 @@ describe('utility functions', () => {
const res = func(':nth-child()');
assert.strictEqual(res, false, 'result');
});

it('should get false', () => {
const res = func(':has(.foo)');
assert.strictEqual(res, false, 'result');
});

it('should get true', () => {
const res = func(':has(.foo)', {
target: TARGET_SELF
});
assert.strictEqual(res, true, 'result');
});

it('should get false', () => {
const res = func(':has(:checked)', {
target: TARGET_SELF
});
assert.strictEqual(res, false, 'result');
});

it('should get true', () => {
const res = func(':has(>.foo)', {
target: TARGET_SELF
});
assert.strictEqual(res, true, 'result');
});

it('should get false', () => {
const res = func(':has(.foo .bar)', {
target: TARGET_SELF
});
assert.strictEqual(res, false, 'result');
});

it('should get true', () => {
const res = func(':has(.foo)', {
target: TARGET_LINEAL
});
assert.strictEqual(res, true, 'result');
});

it('should get true', () => {
const res = func(':has(>.foo)', {
target: TARGET_LINEAL
});
assert.strictEqual(res, true, 'result');
});

it('should get false', () => {
const res = func(':has(.foo .bar)', {
target: TARGET_LINEAL
});
assert.strictEqual(res, false, 'result');
});
});
});

0 comments on commit 3a60def

Please sign in to comment.