Add a wonderfull css package(pseudom) with custom pseudo selectors
This commit is contained in:
parent
69dd1aab34
commit
59ed4da8de
8 changed files with 174 additions and 4 deletions
|
|
@ -141,6 +141,16 @@ class $MDocument implements MDocument, $Instance {
|
|||
false)
|
||||
]),
|
||||
),
|
||||
'hasAttr': BridgeMethodDef(
|
||||
BridgeFunctionDef(
|
||||
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.bool)),
|
||||
params: [
|
||||
BridgeParameter(
|
||||
'attr',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)),
|
||||
false)
|
||||
]),
|
||||
),
|
||||
},
|
||||
wrap: true);
|
||||
|
||||
|
|
@ -194,6 +204,8 @@ class $MDocument implements MDocument, $Instance {
|
|||
return __xpathFirst;
|
||||
case 'attr':
|
||||
return __attr;
|
||||
case 'hasAttr':
|
||||
return __hasAttr;
|
||||
default:
|
||||
return _superclass.$getProperty(runtime, identifier);
|
||||
}
|
||||
|
|
@ -276,6 +288,13 @@ class $MDocument implements MDocument, $Instance {
|
|||
return res == null ? const $null() : $String(res);
|
||||
}
|
||||
|
||||
static const $Function __hasAttr = $Function(_hasAttr);
|
||||
static $Value? _hasAttr(
|
||||
final Runtime runtime, final $Value? target, final List<$Value?> args) {
|
||||
final res = (target!.$value as MDocument).attr(args[0]?.$value ?? "");
|
||||
return res == null ? const $null() : $String(res);
|
||||
}
|
||||
|
||||
@override
|
||||
List<MElement>? select(String selector) => $value.select(selector);
|
||||
|
||||
|
|
@ -299,6 +318,9 @@ class $MDocument implements MDocument, $Instance {
|
|||
@override
|
||||
String? attr(String attr) => $value.attr(attr);
|
||||
|
||||
@override
|
||||
bool hasAttr(String attr) => $value.hasAttr(attr);
|
||||
|
||||
@override
|
||||
MElement? getElementById(String id) => $value.getElementById(id);
|
||||
|
||||
|
|
|
|||
|
|
@ -162,6 +162,16 @@ class $MElement implements MElement, $Instance {
|
|||
false)
|
||||
]),
|
||||
),
|
||||
'hasAttr': BridgeMethodDef(
|
||||
BridgeFunctionDef(
|
||||
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.bool)),
|
||||
params: [
|
||||
BridgeParameter(
|
||||
'attr',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)),
|
||||
false)
|
||||
]),
|
||||
),
|
||||
},
|
||||
wrap: true);
|
||||
|
||||
|
|
@ -245,6 +255,8 @@ class $MElement implements MElement, $Instance {
|
|||
return __xpath;
|
||||
case 'xpathFirst':
|
||||
return __xpathFirst;
|
||||
case 'hasAttr':
|
||||
return __hasAttr;
|
||||
default:
|
||||
return _superclass.$getProperty(runtime, identifier);
|
||||
}
|
||||
|
|
@ -322,6 +334,13 @@ class $MElement implements MElement, $Instance {
|
|||
return res == null ? const $null() : $String(res);
|
||||
}
|
||||
|
||||
static const $Function __hasAttr = $Function(_hasAttr);
|
||||
static $Value? _hasAttr(
|
||||
final Runtime runtime, final $Value? target, final List<$Value?> args) {
|
||||
final res = (target!.$value as MElement).attr(args[0]?.$value ?? "");
|
||||
return res == null ? const $null() : $String(res);
|
||||
}
|
||||
|
||||
@override
|
||||
List<String>? xpath(String xpath) => $value.xpath(xpath);
|
||||
|
||||
|
|
@ -348,6 +367,9 @@ class $MElement implements MElement, $Instance {
|
|||
List<MElement>? getElementsByTagName(String localNames) =>
|
||||
$value.getElementsByTagName(localNames);
|
||||
|
||||
@override
|
||||
bool hasAttr(String attr) => $value.hasAttr(attr);
|
||||
|
||||
@override
|
||||
String? get className => $value.className;
|
||||
|
||||
|
|
|
|||
|
|
@ -59,4 +59,8 @@ class MDocument {
|
|||
String? attr(String attr) {
|
||||
return _document?.attr(attr);
|
||||
}
|
||||
|
||||
bool hasAttr(String attr) {
|
||||
return _document?.hasAtr(attr) ?? false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -69,4 +69,8 @@ class MElement {
|
|||
String? attr(String attribute) {
|
||||
return _element?.attr(attribute);
|
||||
}
|
||||
|
||||
bool hasAttr(String attr) {
|
||||
return _element?.hasAtr(attr) ?? false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -85,6 +85,16 @@ class JsDomSelector {
|
|||
final attr = args[1];
|
||||
return parse(input).attr(attr) ?? "";
|
||||
});
|
||||
runtime.onMessage('ele_has_attr', (dynamic args) {
|
||||
final attr = args[0];
|
||||
final key = args[1];
|
||||
return _elements[key]?.hasAtr(attr) ?? false;
|
||||
});
|
||||
runtime.onMessage('doc_has_attr', (dynamic args) {
|
||||
final input = args[0];
|
||||
final attr = args[1];
|
||||
return parse(input).hasAtr(attr);
|
||||
});
|
||||
runtime.onMessage('doc_xpath_first', (dynamic args) {
|
||||
final input = args[0];
|
||||
final xpath = args[1];
|
||||
|
|
@ -270,6 +280,12 @@ class Document {
|
|||
JSON.stringify([this.html, attr])
|
||||
);
|
||||
}
|
||||
hasAttr(attr) {
|
||||
return sendMessage(
|
||||
"doc_has_attr",
|
||||
JSON.stringify([this.html, attr])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class Element {
|
||||
|
|
@ -379,6 +395,12 @@ class Element {
|
|||
});
|
||||
return elements;
|
||||
}
|
||||
hasAttr(attr) {
|
||||
return sendMessage(
|
||||
"ele_has_attr",
|
||||
JSON.stringify([this.html, attr])
|
||||
);
|
||||
}
|
||||
}
|
||||
''');
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,73 @@
|
|||
import 'package:html/dom.dart';
|
||||
import 'package:pseudom/pseudom.dart' as pseudom;
|
||||
import 'package:mangayomi/utils/reg_exp_matcher.dart';
|
||||
import 'package:xpath_selector_html_parser/xpath_selector_html_parser.dart';
|
||||
|
||||
void _initPseudoSelector() {
|
||||
bool nthChild(Element element, String? args) {
|
||||
if (int.tryParse(args!) != null) {
|
||||
final parent = element.parentNode;
|
||||
return parent != null &&
|
||||
(int.parse(args) as num) > 0 &&
|
||||
parent.nodes.indexOf(element) == int.parse(args);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool has(Element element, String? args) {
|
||||
if (args == null) return false;
|
||||
final parent = element.parent;
|
||||
final res = parent == null
|
||||
? false
|
||||
: pseudom.parse(args).selectFirst(parent) == element;
|
||||
return res ? res : pseudom.parse(args).selectFirst(element) != null;
|
||||
}
|
||||
|
||||
bool inot(Element element, String? args) {
|
||||
if (args == null) return false;
|
||||
final parent = element.parent;
|
||||
final res = parent == null
|
||||
? false
|
||||
: pseudom.parse(args).selectFirst(parent) != element;
|
||||
return res ? res : pseudom.parse(args).selectFirst(element) == null;
|
||||
}
|
||||
|
||||
bool contains(Element element, String? args) {
|
||||
final text = args ?? '';
|
||||
return element.text.contains(text);
|
||||
}
|
||||
|
||||
bool firstChild(Element element, String? args) {
|
||||
return element.previousElementSibling == null;
|
||||
}
|
||||
|
||||
bool lastChild(Element element, String? args) {
|
||||
return element.nextElementSibling == null;
|
||||
}
|
||||
|
||||
bool onlyChild(Element element, String? args) {
|
||||
return element.nextElementSibling == null;
|
||||
}
|
||||
|
||||
pseudom.PseudoSelector.handlers['nth-child'] = nthChild;
|
||||
pseudom.PseudoSelector.handlers['has'] = has;
|
||||
pseudom.PseudoSelector.handlers['inot'] = inot;
|
||||
pseudom.PseudoSelector.handlers['contains'] = contains;
|
||||
pseudom.PseudoSelector.handlers['last-child'] = lastChild;
|
||||
pseudom.PseudoSelector.handlers['first-child'] = firstChild;
|
||||
pseudom.PseudoSelector.handlers['only-child'] = onlyChild;
|
||||
}
|
||||
|
||||
String _fixSelector(String selector) {
|
||||
return selector.replaceAll(':not', ':inot');
|
||||
}
|
||||
|
||||
extension DocumentExtension on Document? {
|
||||
List<Element>? select(String selector) {
|
||||
try {
|
||||
return this?.querySelectorAll(selector);
|
||||
_initPseudoSelector();
|
||||
final dom = this?.documentElement;
|
||||
return pseudom.parse(_fixSelector(selector)).select(dom!).toList();
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
|
|
@ -13,12 +75,18 @@ extension DocumentExtension on Document? {
|
|||
|
||||
Element? selectFirst(String selector) {
|
||||
try {
|
||||
return this?.querySelector(selector);
|
||||
_initPseudoSelector();
|
||||
final dom = this?.documentElement;
|
||||
return pseudom.parse(_fixSelector(selector)).selectFirst(dom!);
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
bool hasAtr(String attribute) {
|
||||
return attr(attribute) != null;
|
||||
}
|
||||
|
||||
String? xpathFirst(String xpath) {
|
||||
final dom = this?.documentElement;
|
||||
if (dom == null) return null;
|
||||
|
|
@ -50,7 +118,12 @@ extension DocumentExtension on Document? {
|
|||
extension ElementtExtension on Element {
|
||||
List<Element>? select(String selector) {
|
||||
try {
|
||||
return querySelectorAll(selector);
|
||||
_initPseudoSelector();
|
||||
return pseudom
|
||||
.parse(_fixSelector(selector))
|
||||
.select(
|
||||
parent!.nodes.firstWhere((element) => element == this) as Element)
|
||||
.toList();
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
|
|
@ -73,7 +146,9 @@ extension ElementtExtension on Element {
|
|||
|
||||
Element? selectFirst(String selector) {
|
||||
try {
|
||||
return querySelector(selector);
|
||||
_initPseudoSelector();
|
||||
return pseudom.parse(_fixSelector(selector)).selectFirst(
|
||||
parent!.nodes.firstWhere((element) => element == this) as Element);
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
|
|
@ -87,6 +162,10 @@ extension ElementtExtension on Element {
|
|||
}
|
||||
}
|
||||
|
||||
bool hasAtr(String attribute) {
|
||||
return attr(attribute) != null;
|
||||
}
|
||||
|
||||
String? get getSrc {
|
||||
try {
|
||||
return regSrcMatcher(outerHtml);
|
||||
|
|
|
|||
16
pubspec.lock
16
pubspec.lock
|
|
@ -25,6 +25,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.11.3"
|
||||
antlr4:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: antlr4
|
||||
sha256: "96f576fcb88202a327b28f40485d99ca6987246ff37805488be06bcf05dc227f"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.13.1"
|
||||
archive:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
@ -1184,6 +1192,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.0"
|
||||
pseudom:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: pseudom
|
||||
sha256: "3df7b5aa28adc8e035820db8954e34466aa94353a02e28fd72e54d0ed68b0ecf"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.1"
|
||||
pub_semver:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
|
|||
|
|
@ -82,6 +82,7 @@ dependencies:
|
|||
flutter_rust_bridge: ^2.0.0-dev.39
|
||||
rust_lib_mangayomi:
|
||||
path: rust_builder
|
||||
pseudom: ^1.0.1
|
||||
|
||||
dependency_overrides:
|
||||
http: ^1.2.1
|
||||
|
|
|
|||
Loading…
Reference in a new issue