Selector - bhsd-harry/wikiparser-node GitHub Wiki
Token 选择器的设计仿照了 CSS 和 jQuery 的选择器。
✅ 展开
类比 CSS 元素选择器。
// type
var root = Parser.parse("[[a]]{{{b}}}"),
{firstChild, lastChild} = root;
assert.equal(firstChild, "[[a]]");
assert.equal(lastChild, "{{{b}}}");
assert.deepStrictEqual(
root.querySelectorAll("link, arg"),
[firstChild, lastChild],
);✅ 展开
类比 CSS id 选择器。
// name
var root = Parser.parse("<ref/><poem/>"),
{firstChild} = root;
assert.equal(firstChild, "<ref/>");
assert.deepStrictEqual(root.querySelectorAll("ext#ref"), [firstChild]);// name (main)
var {firstChild} = Parser.parse("[[()]]");
assert.equal(firstChild, "[[()]]");
// 转义特殊字符
assert.ok(firstChild.matches(String.raw`#\(\)`));展开
类比 CSS 属性选择器。
// attribute (main)
var root = Parser.parse('<p id="ab-c" class="c1 c2" style="top:0"/>'),
{firstChild} = root,
attrs = firstChild.firstChild;
assert.equal(firstChild, '<p id="ab-c" class="c1 c2" style="top:0"/>');
assert.equal(attrs, ' id="ab-c" class="c1 c2" style="top:0"');
assert.deepStrictEqual(root.querySelectorAll("[selfClosing]"), [firstChild]);
assert.deepStrictEqual(root.querySelectorAll("[id^=A i]"), [firstChild, attrs]);
assert.deepStrictEqual(root.querySelectorAll("[id$=C i]"), [firstChild, attrs]);
assert.deepStrictEqual(
root.querySelectorAll("html[style*=TOP i]"),
[firstChild],
);
assert.ok(firstChild.matches("[name!=P]"));
assert.deepStrictEqual(
root.querySelectorAll("[name=P i]"),
[firstChild, attrs],
);
assert.deepStrictEqual(
root.querySelectorAll("[id|=AB i]"),
[firstChild, attrs],
);
assert.deepStrictEqual(
root.querySelectorAll("[class~=C1 i]"),
[firstChild, attrs],
);
assert.deepStrictEqual(
root.querySelectorAll("[classList~=C1 i]"),
[firstChild, attrs],
);
({firstChild} = Parser.parse("__INDEX__"));
assert.equal(firstChild, "__INDEX__");
assert.ok(firstChild.matches('[pattern="^INDEX$"]'));类比 CSS 组合器。
展开
// descendant combinator (main)
var root = Parser.parse("<poem>{{a}}</poem>{{b}}"),
template = root.querySelector("template");
assert.equal(template, "{{a}}");
assert.deepStrictEqual(root.querySelectorAll("ext template"), [template]);展开
// child combinator (main)
var root = Parser.parse("<poem>{{a}}</poem>{{b}}"),
template = root.querySelector("template");
assert.equal(template, "{{a}}");
assert.deepStrictEqual(
root.querySelectorAll("root > ext > ext-inner > template"),
[template],
);展开
// subsequent-sibling combinator (main)
var root = Parser.parse("<poem>[[a]]{{b}}</poem>{{c}}"),
template = root.querySelector("template");
assert.equal(template, "{{b}}");
assert.deepStrictEqual(root.querySelectorAll("link ~ template"), [template]);
assert.ok(!root.matches("* ~ root"));展开
// next-sibling combinator (main)
var root = Parser.parse("<poem>[[a]]{{{b}}}{{c}}</poem>{{d}}"),
template = root.querySelector("template");
assert.equal(template, "{{c}}");
assert.deepStrictEqual(
root.querySelectorAll("link + arg + template"),
[template],
);类比 CSS 和 jQuery 伪选择器。
展开
// any-link (main)
var root = Parser.parse("#redirect [[a]]ftp://b PMID 0[//d][[file:e]]"),
[{lastChild: a}, b, c, d, e] = root.children;
assert.equal(a, "[[a]]");
assert.equal(b, "ftp://b");
assert.equal(c, "PMID 0");
assert.equal(d, "[//d]");
assert.equal(e, "[[file:e]]");
assert.deepStrictEqual(root.querySelectorAll(":any-link"), [a, b, c, d, e]);展开
// contains (main)
var root = Parser.parse("[[a]]"),
{firstChild} = root;
assert.deepStrictEqual(root.querySelectorAll(":contains([[)"), [firstChild]);展开
// empty (main)
var root = Parser.parse("<!---->"),
{firstChild} = root;
assert.deepStrictEqual(root.querySelectorAll(":empty"), [firstChild]);展开
// first-child (main)
var root = Parser.parse("a<ref/>[[b]]"),
{firstElementChild} = root;
assert.equal(firstElementChild, "<ref/>");
assert.deepStrictEqual(
root.querySelectorAll("root > :first-child"),
[firstElementChild],
);展开
// first-of-type (main)
var root = Parser.parse("a<ref/>[[b]]"),
{firstElementChild, lastChild} = root;
assert.equal(firstElementChild, "<ref/>");
assert.equal(lastChild, "[[b]]");
assert.deepStrictEqual(
root.querySelectorAll("root > :first-of-type"),
[firstElementChild, lastChild],
);展开
// has (main)
var root = Parser.parse("<ref>[[a]]</ref>"),
attrs = root.querySelector("ext-attrs"),
inner = attrs.nextSibling;
assert.equal(attrs, "");
assert.equal(inner, "[[a]]");
assert.ok(root.matches(":has(#A, #B)"));
assert.deepStrictEqual(root.querySelectorAll(":has(+ ext-inner)"), [attrs]);
assert.deepStrictEqual(root.querySelectorAll(":has(> link)"), [inner]);
assert.deepStrictEqual(
root.querySelectorAll(":has(+ ext-inner, > link)"),
[attrs, inner],
);展开
// header (main)
var root = Parser.parse("==a=="),
{firstChild} = root;
assert.deepStrictEqual(root.querySelectorAll(":header"), [firstChild]);hidden
展开
// hidden (main)
var root = Parser.parse("<!-- -->__nocc__"),
{firstChild, lastChild} = root;
assert.equal(firstChild, "<!-- -->");
assert.equal(lastChild, "__nocc__");
assert.ok(root.matches(":hidden"));
assert.deepStrictEqual(
root.querySelectorAll(":hidden"),
[firstChild, lastChild],
);展开
// invalid (main)
var root = Parser.parse("{|\na\n|}<gallery>b|1px</gallery>"),
a = root.querySelector("table-inter"),
b = root.querySelector("image-parameter");
assert.equal(a, "\na");
assert.equal(b, "1px");
assert.deepStrictEqual(root.querySelectorAll(":invalid"), [a, b]);展开
// is (main)
var root = Parser.parse("[[a]]{{b}}"),
{firstChild, lastChild} = root;
assert.deepStrictEqual(
root.querySelectorAll(":is(#A, * + *)"),
[firstChild, lastChild],
);展开
// lang (main)
var root = Parser.parse('<poem lang="en"><p lang="zh-cn"><b></poem>'),
[p, b] = root.querySelectorAll("html");
assert.equal(p, '<p lang="zh-cn">');
assert.equal(b, "<b>");
assert.ok(p.matches(":lang(zh)"));
assert.ok(p.matches(":lang(zh-CN)"));
assert.ok(!p.matches(":lang(en)"));
assert.ok(b.matches(":lang(en)"));
assert.ok(!root.matches(":lang(en)"));展开
// last-child (main)
var root = Parser.parse("<ref/>a"),
{firstChild} = root;
assert.equal(firstChild, "<ref/>");
assert.deepStrictEqual(
root.querySelectorAll("root > :last-child"),
[firstChild],
);展开
// last-of-type (main)
var root = Parser.parse("<ref/>[[a]]"),
{firstChild, lastChild} = root;
assert.equal(firstChild, "<ref/>");
assert.equal(lastChild, "[[a]]");
assert.deepStrictEqual(
root.querySelectorAll("root > :last-of-type"),
[firstChild, lastChild],
);展开
// local-link (main)
var root = Parser.parse("[[#a]][[file:b|link=#b]]"),
[a, b] = root.childNodes;
assert.equal(a, "[[#a]]");
assert.equal(b, "[[file:b|link=#b]]");
assert.deepStrictEqual(root.querySelectorAll(":local-link"), [a, b]);展开
// not (main)
var root = Parser.parse("");
assert.ok(root.matches(":not(arg, * + *)"));展开
// nth-child (main)
var {lastChild} = Parser.parse("[[a]]<ref/>");
assert.ok(lastChild.matches(":nth-child(2)"));
assert.ok(lastChild.matches(":nth-child(even)"));
assert.ok(lastChild.matches(":nth-child(2n)"));
assert.ok(lastChild.matches(":nth-child(:4:2)"));展开
// nth-last-child (main)
var {firstChild} = Parser.parse("<ref/>[[a]]");
assert.ok(firstChild.matches(":nth-last-child(2)"));
assert.ok(firstChild.matches(":nth-last-child(even)"));
assert.ok(firstChild.matches(":nth-last-child(2n-2)"));
assert.ok(firstChild.matches(":nth-last-child(:3)"));展开
// nth-last-of-type (main)
var {firstChild} = Parser.parse("<ref/>[[a]]");
assert.ok(firstChild.matches(":nth-last-of-type(1)"));
assert.ok(firstChild.matches(":nth-last-of-type(odd)"));
assert.ok(firstChild.matches(":nth-last-of-type(3n+1)"));
assert.ok(firstChild.matches(":nth-last-of-type(:)"));展开
// nth-of-type (main)
var {lastChild} = Parser.parse("[[a]]<ref/>");
assert.ok(lastChild.matches(":nth-of-type(1)"));
assert.ok(lastChild.matches(":nth-of-type(odd)"));
assert.ok(lastChild.matches(":nth-of-type(-2n+3)"));
assert.ok(lastChild.matches(":nth-of-type(1:)"));展开
// only-child (main)
var root = Parser.parse("<ref/>a"),
{firstChild} = root;
assert.equal(firstChild, "<ref/>");
assert.deepStrictEqual(
root.querySelectorAll("root > :only-child"),
[firstChild],
);展开
// only-of-type (main)
var root = Parser.parse("<ref/>[[a]]"),
{firstChild, lastChild} = root;
assert.equal(firstChild, "<ref/>");
assert.equal(lastChild, "[[a]]");
assert.deepStrictEqual(
root.querySelectorAll("root > :only-of-type"),
[firstChild, lastChild],
);展开
// only-whitespace (main)
var root = Parser.parse(" ");
assert.ok(root.matches(":only-whitespace"));展开
// optional (main)
var root = Parser.parse("{{{|a}}}"),
{firstChild} = root,
{lastChild} = firstChild;
assert.equal(lastChild, "a");
// 根节点不适用
assert.ok(!root.matches(":optional"));
assert.deepStrictEqual(
root.querySelectorAll(":optional"),
[firstChild, lastChild],
);展开
// parent (main)
var root = Parser.parse("<!-- -->"),
{firstChild} = root;
assert.deepStrictEqual(root.querySelectorAll(":parent"), [firstChild]);展开
// required (main)
var root = Parser.parse("{{{a}}}\n=b="),
a = root.querySelector("arg-name"),
b = root.querySelector("heading-title");
assert.equal(a, "a");
assert.equal(b, "b");
// 根节点不适用
assert.ok(!root.matches(":required"));
assert.ok(a.matches(":required"));
assert.ok(b.matches(":required"));展开
// root (main)
var root = Parser.parse("");
assert.ok(root.matches(":root"));展开
加入的版本:1.13.0
// scope (main)
var root = Parser.parse("[[a]]"),
{firstChild} = root;
assert.ok(firstChild.matches(":scope"));
assert.deepStrictEqual(root.querySelectorAll(":is(:scope > *)"), [firstChild]);展开
加入的版本:1.13.0
// valid (main)
var root = Parser.parse("{|\na\n|}<gallery>b|1px</gallery>"),
a = root.querySelector("table-inter"),
b = root.querySelector("image-parameter");
assert.equal(a, "\na");
assert.equal(b, "1px");
assert.ok(!a.matches(":valid"));
assert.ok(!b.matches(":valid"));展开
// visible (main)
var root = Parser.parse(" ");
assert.ok(root.matches(":visible"));展开
格式类似伪选择器。
// regex (main)
var root = Parser.parse("[[aa]]<p id=段落>"),
{firstChild, lastChild} = root;
assert.equal(firstChild, "[[aa]]");
assert.equal(lastChild, "<p id=段落>");
assert.deepStrictEqual(
root.querySelectorAll(':regex("name, /^A{2,}$/i")'),
[firstChild],
);
assert.ok(lastChild.matches(String.raw`:regex("id, /\p{L}/u")`));