@markuplint/selector
Advanced tools
Comparing version 3.0.0-alpha.0 to 3.0.0-alpha.1
@@ -6,2 +6,3 @@ "use strict"; | ||
const aria_role_pseudo_class_1 = require("./extended-selector/aria-role-pseudo-class"); | ||
const content_model_pseudo_class_1 = require("./extended-selector/content-model-pseudo-class"); | ||
const selector_1 = require("./selector"); | ||
@@ -15,2 +16,3 @@ const caches = new Map(); | ||
instance = new selector_1.Selector(selector, { | ||
model: (0, content_model_pseudo_class_1.contentModelPseudoClass)(specs), | ||
aria: (0, aria_pseudo_class_1.ariaPseudoClass)(), | ||
@@ -17,0 +19,0 @@ role: (0, aria_role_pseudo_class_1.ariaRolePseudoClass)(specs), |
@@ -11,15 +11,30 @@ "use strict"; | ||
const aria = ariaPseudoClassParser(content); | ||
const name = (0, ml_spec_1.getAccname)(el); | ||
switch (aria.type) { | ||
case 'hasName': { | ||
const name = (0, ml_spec_1.getAccname)(el); | ||
if (name) { | ||
return { | ||
specificity: [0, 1, 0], | ||
matched: true, | ||
nodes: [el], | ||
has: [], | ||
}; | ||
} | ||
return { | ||
specificity: [0, 1, 0], | ||
matched: !!name, | ||
matched: false, | ||
}; | ||
} | ||
case 'hasNoName': { | ||
const name = (0, ml_spec_1.getAccname)(el); | ||
if (!name) { | ||
return { | ||
specificity: [0, 1, 0], | ||
matched: true, | ||
nodes: [el], | ||
has: [], | ||
}; | ||
} | ||
return { | ||
specificity: [0, 1, 0], | ||
matched: !name, | ||
matched: false, | ||
}; | ||
@@ -26,0 +41,0 @@ } |
@@ -10,5 +10,13 @@ "use strict"; | ||
const computed = (0, ml_spec_1.getComputedRole)(specs, el, (_a = aria.version) !== null && _a !== void 0 ? _a : '1.2'); | ||
if (((_b = computed.role) === null || _b === void 0 ? void 0 : _b.name) === aria.role) { | ||
return { | ||
specificity: [0, 1, 0], | ||
matched: true, | ||
nodes: [el], | ||
has: [], | ||
}; | ||
} | ||
return { | ||
specificity: [0, 1, 0], | ||
matched: ((_b = computed.role) === null || _b === void 0 ? void 0 : _b.name) === aria.role, | ||
matched: false, | ||
}; | ||
@@ -15,0 +23,0 @@ }; |
"use strict"; | ||
var _SelectorTarget_combinedFrom, _SelectorTarget_selector; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.matchSelector = void 0; | ||
const tslib_1 = require("tslib"); | ||
const is_1 = require("./is"); | ||
@@ -43,14 +45,15 @@ const regex_selector_matches_1 = require("./regex-selector-matches"); | ||
constructor(selector) { | ||
this._combinatedFrom = null; | ||
this._selector = selector; | ||
_SelectorTarget_combinedFrom.set(this, null); | ||
_SelectorTarget_selector.set(this, void 0); | ||
tslib_1.__classPrivateFieldSet(this, _SelectorTarget_selector, selector, "f"); | ||
} | ||
from(target, combinator) { | ||
this._combinatedFrom = { target, combinator }; | ||
tslib_1.__classPrivateFieldSet(this, _SelectorTarget_combinedFrom, { target, combinator }, "f"); | ||
} | ||
match(el) { | ||
const unitCheck = this._matchWithoutCombinateChecking(el); | ||
const unitCheck = this._matchWithoutCombineChecking(el); | ||
if (!unitCheck.matched) { | ||
return unitCheck; | ||
} | ||
if (!this._combinatedFrom) { | ||
if (!tslib_1.__classPrivateFieldGet(this, _SelectorTarget_combinedFrom, "f")) { | ||
return unitCheck; | ||
@@ -61,3 +64,3 @@ } | ||
} | ||
const { target, combinator } = this._combinatedFrom; | ||
const { target, combinator } = tslib_1.__classPrivateFieldGet(this, _SelectorTarget_combinedFrom, "f"); | ||
switch (combinator) { | ||
@@ -137,11 +140,12 @@ // Descendant combinator | ||
default: { | ||
throw new Error(`Unsupported ${this._combinatedFrom.combinator} combinator in selector`); | ||
throw new Error(`Unsupported ${tslib_1.__classPrivateFieldGet(this, _SelectorTarget_combinedFrom, "f").combinator} combinator in selector`); | ||
} | ||
} | ||
} | ||
_matchWithoutCombinateChecking(el) { | ||
return uncombinatedRegexSelect(el, this._selector); | ||
_matchWithoutCombineChecking(el) { | ||
return uncombinedRegexSelect(el, tslib_1.__classPrivateFieldGet(this, _SelectorTarget_selector, "f")); | ||
} | ||
} | ||
function uncombinatedRegexSelect(el, selector) { | ||
_SelectorTarget_combinedFrom = new WeakMap(), _SelectorTarget_selector = new WeakMap(); | ||
function uncombinedRegexSelect(el, selector) { | ||
if (!(0, is_1.isElement)(el)) { | ||
@@ -148,0 +152,0 @@ return { |
@@ -6,3 +6,3 @@ "use strict"; | ||
const res = {}; | ||
const pattern = toRegxp(reg); | ||
const pattern = toRegexp(reg); | ||
const regex = new RegExp(pattern instanceof RegExp ? pattern : `^${pattern.trim()}$`, ignoreCase ? 'i' : undefined); | ||
@@ -20,3 +20,3 @@ const matched = regex.exec(raw); | ||
exports.regexSelectorMatches = regexSelectorMatches; | ||
function toRegxp(pattern) { | ||
function toRegexp(pattern) { | ||
const matched = pattern.match(/^\/(.+)\/([ig]*)$/i); | ||
@@ -23,0 +23,0 @@ if (matched) { |
@@ -7,3 +7,4 @@ import type { SelectorResult, Specificity } from './types'; | ||
match(el: Node, scope?: ParentNode | null): Specificity | false; | ||
search(el: Node, scope?: ParentNode | null): SelectorResult[]; | ||
} | ||
export {}; |
"use strict"; | ||
var _Selector_ruleset, _Ruleset_selectorGroup, _StructuredSelector_selector, _StructuredSelector_edge, _SelectorTarget_extended, _SelectorTarget_combinatedFrom, _SelectorTarget_isAdded; | ||
var _Selector_ruleset, _Ruleset_selectorGroup, _StructuredSelector_edge, _StructuredSelector_selector, _SelectorTarget_combinedFrom, _SelectorTarget_extended, _SelectorTarget_isAdded; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
@@ -20,3 +20,3 @@ exports.Selector = void 0; | ||
match(el, scope = (0, is_1.isElement)(el) ? el : null) { | ||
const results = tslib_1.__classPrivateFieldGet(this, _Selector_ruleset, "f").match(el, scope); | ||
const results = this.search(el, scope); | ||
for (const result of results) { | ||
@@ -29,2 +29,5 @@ if (result.matched) { | ||
} | ||
search(el, scope = (0, is_1.isElement)(el) ? el : null) { | ||
return tslib_1.__classPrivateFieldGet(this, _Selector_ruleset, "f").match(el, scope); | ||
} | ||
} | ||
@@ -73,4 +76,4 @@ exports.Selector = Selector; | ||
constructor(selector, depth, extended) { | ||
_StructuredSelector_edge.set(this, void 0); | ||
_StructuredSelector_selector.set(this, void 0); | ||
_StructuredSelector_edge.set(this, void 0); | ||
tslib_1.__classPrivateFieldSet(this, _StructuredSelector_selector, selector, "f"); | ||
@@ -86,5 +89,5 @@ tslib_1.__classPrivateFieldSet(this, _StructuredSelector_edge, new SelectorTarget(extended, depth), "f"); | ||
case 'combinator': { | ||
const combinatedTarget = new SelectorTarget(extended, depth); | ||
combinatedTarget.from(tslib_1.__classPrivateFieldGet(this, _StructuredSelector_edge, "f"), node); | ||
tslib_1.__classPrivateFieldSet(this, _StructuredSelector_edge, combinatedTarget, "f"); | ||
const combinedTarget = new SelectorTarget(extended, depth); | ||
combinedTarget.from(tslib_1.__classPrivateFieldGet(this, _StructuredSelector_edge, "f"), node); | ||
tslib_1.__classPrivateFieldSet(this, _StructuredSelector_edge, combinedTarget, "f"); | ||
break; | ||
@@ -115,11 +118,11 @@ } | ||
} | ||
_StructuredSelector_selector = new WeakMap(), _StructuredSelector_edge = new WeakMap(); | ||
_StructuredSelector_edge = new WeakMap(), _StructuredSelector_selector = new WeakMap(); | ||
class SelectorTarget { | ||
constructor(extended, depth) { | ||
_SelectorTarget_extended.set(this, void 0); | ||
_SelectorTarget_combinatedFrom.set(this, null); | ||
_SelectorTarget_isAdded.set(this, false); | ||
this.attr = []; | ||
this.class = []; | ||
_SelectorTarget_combinedFrom.set(this, null); | ||
_SelectorTarget_extended.set(this, void 0); | ||
this.id = []; | ||
_SelectorTarget_isAdded.set(this, false); | ||
this.pseudo = []; | ||
@@ -157,3 +160,3 @@ this.tag = null; | ||
from(target, combinator) { | ||
tslib_1.__classPrivateFieldSet(this, _SelectorTarget_combinatedFrom, { target, combinator }, "f"); | ||
tslib_1.__classPrivateFieldSet(this, _SelectorTarget_combinedFrom, { target, combinator }, "f"); | ||
} | ||
@@ -165,3 +168,3 @@ match(el, scope, count) { | ||
const nodeName = el.nodeName; | ||
const selector = ((_a = tslib_1.__classPrivateFieldGet(this, _SelectorTarget_combinatedFrom, "f")) === null || _a === void 0 ? void 0 : _a.target.toString()) || this.toString(); | ||
const selector = ((_a = tslib_1.__classPrivateFieldGet(this, _SelectorTarget_combinedFrom, "f")) === null || _a === void 0 ? void 0 : _a.target.toString()) || this.toString(); | ||
const combinator = result.combinator ? ` ${result.combinator}` : ''; | ||
@@ -176,8 +179,18 @@ selLog('The %s element by "%s" => %s (%d)', nodeName, `${selector}${combinator}`, result.matched, count); | ||
} | ||
toString() { | ||
var _a, _b; | ||
return [ | ||
(_b = (_a = this.tag) === null || _a === void 0 ? void 0 : _a.toString()) !== null && _b !== void 0 ? _b : '', | ||
this.id.map(id => `#${id.value}`).join(''), | ||
this.class.map(c => `.${c.value}`).join(''), | ||
this.attr.map(attr => `[${attr.toString()}]`).join(''), | ||
this.pseudo.map(pseudo => pseudo.value).join(''), | ||
].join(''); | ||
} | ||
_match(el, scope, count) { | ||
const unitCheck = this._matchWithoutCombinateChecking(el, scope); | ||
const unitCheck = this._matchWithoutCombineChecking(el, scope); | ||
if (!unitCheck.matched) { | ||
return unitCheck; | ||
} | ||
if (!tslib_1.__classPrivateFieldGet(this, _SelectorTarget_combinatedFrom, "f")) { | ||
if (!tslib_1.__classPrivateFieldGet(this, _SelectorTarget_combinedFrom, "f")) { | ||
return unitCheck; | ||
@@ -188,8 +201,10 @@ } | ||
} | ||
const { target, combinator } = tslib_1.__classPrivateFieldGet(this, _SelectorTarget_combinatedFrom, "f"); | ||
const { target, combinator } = tslib_1.__classPrivateFieldGet(this, _SelectorTarget_combinedFrom, "f"); | ||
switch (combinator.value) { | ||
// Descendant combinator | ||
case ' ': { | ||
const matchedNodes = []; | ||
const has = []; | ||
const not = []; | ||
let ancestor = el.parentElement; | ||
let matched = false; | ||
let specificity; | ||
@@ -206,4 +221,10 @@ while (ancestor) { | ||
if (res.matched) { | ||
matched = true; | ||
matchedNodes.push(...res.nodes); | ||
has.push(...res.has); | ||
} | ||
else { | ||
if (res.not) { | ||
not.push(...res.not); | ||
} | ||
} | ||
ancestor = ancestor.parentElement; | ||
@@ -219,6 +240,16 @@ } | ||
} | ||
if (matchedNodes.length) { | ||
return { | ||
combinator: '␣', | ||
specificity, | ||
matched: true, | ||
nodes: matchedNodes, | ||
has, | ||
}; | ||
} | ||
return { | ||
combinator: '␣', | ||
specificity, | ||
matched, | ||
matched: false, | ||
not, | ||
}; | ||
@@ -228,3 +259,5 @@ } | ||
case '>': { | ||
let matched; | ||
const matchedNodes = []; | ||
const has = []; | ||
const not = []; | ||
const specificity = unitCheck.specificity; | ||
@@ -237,3 +270,11 @@ const parentNode = el.parentElement; | ||
specificity[2] += res.specificity[2]; | ||
matched = res.matched; | ||
if (res.matched) { | ||
matchedNodes.push(...res.nodes); | ||
has.push(...res.has); | ||
} | ||
else { | ||
if (res.not) { | ||
not.push(...res.not); | ||
} | ||
} | ||
} | ||
@@ -245,8 +286,17 @@ else { | ||
specificity[2] += res.specificity[2]; | ||
matched = false; | ||
} | ||
if (matchedNodes.length) { | ||
return { | ||
combinator: '>', | ||
specificity, | ||
matched: true, | ||
nodes: matchedNodes, | ||
has, | ||
}; | ||
} | ||
return { | ||
combinator: '>', | ||
specificity, | ||
matched, | ||
matched: false, | ||
not, | ||
}; | ||
@@ -256,3 +306,5 @@ } | ||
case '+': { | ||
let matched; | ||
const matchedNodes = []; | ||
const has = []; | ||
const not = []; | ||
const specificity = unitCheck.specificity; | ||
@@ -264,3 +316,11 @@ if (el.previousElementSibling) { | ||
specificity[2] += res.specificity[2]; | ||
matched = res.matched; | ||
if (res.matched) { | ||
matchedNodes.push(...res.nodes); | ||
has.push(...res.has); | ||
} | ||
else { | ||
if (res.not) { | ||
not.push(...res.not); | ||
} | ||
} | ||
} | ||
@@ -272,8 +332,17 @@ else { | ||
specificity[2] += res.specificity[2]; | ||
matched = false; | ||
} | ||
if (matchedNodes.length) { | ||
return { | ||
combinator: '+', | ||
specificity, | ||
matched: true, | ||
nodes: matchedNodes, | ||
has, | ||
}; | ||
} | ||
return { | ||
combinator: '+', | ||
specificity, | ||
matched, | ||
matched: false, | ||
not, | ||
}; | ||
@@ -283,4 +352,6 @@ } | ||
case '~': { | ||
const matchedNodes = []; | ||
const has = []; | ||
const not = []; | ||
let prev = el.previousElementSibling; | ||
let matched = false; | ||
let specificity; | ||
@@ -297,4 +368,10 @@ while (prev) { | ||
if (res.matched) { | ||
matched = true; | ||
matchedNodes.push(...res.nodes); | ||
has.push(...res.has); | ||
} | ||
else { | ||
if (res.not) { | ||
not.push(...res.not); | ||
} | ||
} | ||
prev = prev.previousElementSibling; | ||
@@ -310,6 +387,16 @@ } | ||
} | ||
if (matchedNodes.length) { | ||
return { | ||
combinator: '~', | ||
specificity, | ||
matched: true, | ||
nodes: matchedNodes, | ||
has, | ||
}; | ||
} | ||
return { | ||
combinator: '~', | ||
specificity, | ||
matched, | ||
matched: false, | ||
not, | ||
}; | ||
@@ -322,17 +409,8 @@ } | ||
default: { | ||
throw new Error(`Unsupported ${tslib_1.__classPrivateFieldGet(this, _SelectorTarget_combinatedFrom, "f").combinator.value} combinator in selector`); | ||
throw new Error(`Unsupported ${tslib_1.__classPrivateFieldGet(this, _SelectorTarget_combinedFrom, "f").combinator.value} combinator in selector`); | ||
} | ||
} | ||
} | ||
toString() { | ||
var _a, _b; | ||
return [ | ||
(_b = (_a = this.tag) === null || _a === void 0 ? void 0 : _a.toString()) !== null && _b !== void 0 ? _b : '', | ||
this.id.map(id => `#${id.value}`).join(''), | ||
this.class.map(c => `.${c.value}`).join(''), | ||
this.attr.map(attr => `[${attr.toString()}]`).join(''), | ||
this.pseudo.map(pseudo => pseudo.value).join(''), | ||
].join(''); | ||
} | ||
_matchWithoutCombinateChecking(el, scope) { | ||
_matchWithoutCombineChecking(el, scope) { | ||
var _a; | ||
const specificity = [0, 0, 0]; | ||
@@ -345,2 +423,4 @@ if (!(0, is_1.isElement)(el)) { | ||
} | ||
const has = []; | ||
const not = []; | ||
// @ts-ignore | ||
@@ -390,3 +470,7 @@ if (this.tag && this.tag._namespace) { | ||
specificity[2] += pseudoRes.specificity[2]; | ||
if (!pseudoRes.matched) { | ||
if (pseudoRes.matched) { | ||
has.push(...pseudoRes.has); | ||
} | ||
else { | ||
not.push(...((_a = pseudoRes.not) !== null && _a !== void 0 ? _a : [])); | ||
matched = false; | ||
@@ -407,9 +491,18 @@ } | ||
} | ||
if (matched) { | ||
return { | ||
specificity, | ||
matched, | ||
nodes: [el], | ||
has, | ||
}; | ||
} | ||
return { | ||
specificity, | ||
matched, | ||
not, | ||
}; | ||
} | ||
} | ||
_SelectorTarget_extended = new WeakMap(), _SelectorTarget_combinatedFrom = new WeakMap(), _SelectorTarget_isAdded = new WeakMap(); | ||
_SelectorTarget_combinedFrom = new WeakMap(), _SelectorTarget_extended = new WeakMap(), _SelectorTarget_isAdded = new WeakMap(); | ||
function attrMatch(attr, el) { | ||
@@ -486,6 +579,9 @@ return Array.from(el.attributes).some(attrOfEl => { | ||
while (parent) { | ||
if (ruleset.match(parent, scope).some(r => r.matched)) { | ||
const matched = ruleset.match(parent, scope).filter((r) => r.matched); | ||
if (matched.length) { | ||
return { | ||
specificity, | ||
matched: true, | ||
nodes: [el], | ||
has: matched, | ||
}; | ||
@@ -507,6 +603,15 @@ } | ||
const specificity = getSpecificity(resList); | ||
const matched = resList.every(r => !r.matched); | ||
const not = resList.filter((r) => r.matched); | ||
if (not.length === 0) { | ||
return { | ||
specificity, | ||
matched: true, | ||
nodes: [el], | ||
has: [], | ||
}; | ||
} | ||
return { | ||
specificity, | ||
matched, | ||
matched: false, | ||
not, | ||
}; | ||
@@ -518,6 +623,8 @@ } | ||
const specificity = getSpecificity(resList); | ||
const matched = resList.some(r => r.matched); | ||
const matched = resList.filter((r) => r.matched); | ||
return { | ||
specificity, | ||
matched, | ||
matched: !!matched.length, | ||
nodes: matched.map(m => m.nodes).flat(), | ||
has: matched.map(m => m.has).flat(), | ||
}; | ||
@@ -531,13 +638,33 @@ } | ||
case '~': { | ||
const matched = getSiblings(el).some(sib => ruleset.match(sib, el).some(m => m.matched)); | ||
const has = getSiblings(el) | ||
.map(sib => ruleset.match(sib, el).filter((m) => m.matched)) | ||
.flat(); | ||
if (has.length) { | ||
return { | ||
specificity, | ||
matched: true, | ||
nodes: [el], | ||
has, | ||
}; | ||
} | ||
return { | ||
specificity, | ||
matched, | ||
matched: false, | ||
}; | ||
} | ||
default: { | ||
const matched = getDescendants(el).some(desc => ruleset.match(desc, el).some(m => m.matched)); | ||
const has = getDescendants(el) | ||
.map(sib => ruleset.match(sib, el).filter((m) => m.matched)) | ||
.flat(); | ||
if (has.length) { | ||
return { | ||
specificity, | ||
matched: true, | ||
nodes: [el], | ||
has, | ||
}; | ||
} | ||
return { | ||
specificity, | ||
matched, | ||
matched: false, | ||
}; | ||
@@ -550,6 +677,8 @@ } | ||
const resList = ruleset.match(el, scope); | ||
const matched = resList.some(r => r.matched); | ||
const matched = resList.filter((r) => r.matched); | ||
return { | ||
specificity: [0, 0, 0], | ||
matched, | ||
matched: !!matched.length, | ||
nodes: matched.map(m => m.nodes).flat(), | ||
has: matched.map(m => m.has).flat(), | ||
}; | ||
@@ -562,2 +691,4 @@ } | ||
matched: true, | ||
nodes: [el], | ||
has: [], | ||
}; | ||
@@ -575,2 +706,4 @@ } | ||
matched: true, | ||
nodes: [el], | ||
has: [], | ||
}; | ||
@@ -661,13 +794,13 @@ } | ||
} | ||
function getSpecificity(result) { | ||
function getSpecificity(results) { | ||
let specificity; | ||
for (const res of result) { | ||
for (const result of results) { | ||
if (specificity) { | ||
const order = (0, compare_specificity_1.compareSpecificity)(specificity, res.specificity); | ||
const order = (0, compare_specificity_1.compareSpecificity)(specificity, result.specificity); | ||
if (order === -1) { | ||
specificity = res.specificity; | ||
specificity = result.specificity; | ||
} | ||
} | ||
else { | ||
specificity = res.specificity; | ||
specificity = result.specificity; | ||
} | ||
@@ -674,0 +807,0 @@ } |
export declare type Specificity = [number, number, number]; | ||
export declare type SelectorResult = { | ||
export declare type SelectorResult = SelectorMatchedResult | SelectorUnmatchedResult; | ||
export declare type SelectorMatchedResult = { | ||
specificity: Specificity; | ||
matched: boolean; | ||
matched: true; | ||
nodes: (Element | Text)[]; | ||
has: SelectorMatchedResult[]; | ||
}; | ||
export declare type RegexSelector = RegexSelectorWithoutCompination & { | ||
export declare type SelectorUnmatchedResult = { | ||
specificity: Specificity; | ||
matched: false; | ||
not?: SelectorMatchedResult[]; | ||
}; | ||
export declare type RegexSelector = RegexSelectorWithoutCombination & { | ||
combination?: { | ||
@@ -12,3 +20,3 @@ combinator: RegexSelectorCombinator; | ||
export declare type RegexSelectorCombinator = ' ' | '>' | '+' | '~' | ':has(+)' | ':has(~)'; | ||
export declare type RegexSelectorWithoutCompination = { | ||
export declare type RegexSelectorWithoutCombination = { | ||
nodeName?: string; | ||
@@ -15,0 +23,0 @@ attrName?: string; |
{ | ||
"name": "@markuplint/selector", | ||
"version": "3.0.0-alpha.0", | ||
"version": "3.0.0-alpha.1", | ||
"description": "W3C Selector and Regex selector", | ||
@@ -25,8 +25,8 @@ "repository": "git@github.com:markuplint/markuplint.git", | ||
"devDependencies": { | ||
"@markuplint/ml-spec": "3.0.0-alpha.0", | ||
"@markuplint/ml-spec": "3.0.0-alpha.1", | ||
"@types/debug": "^4.1.7", | ||
"@types/jsdom": "^16.2.14", | ||
"jsdom": "^19.0.0" | ||
"@types/jsdom": "16", | ||
"jsdom": "19" | ||
}, | ||
"gitHead": "d32c522e016888e20bcbb5f09352c006b964f193" | ||
"gitHead": "56de89456146a06777eb5b6d4e8ba456147dd18b" | ||
} |
Sorry, the diff of this file is not supported yet
120858
1384
31