168 lines
4.1 KiB
Dart
168 lines
4.1 KiB
Dart
// Copyright 2017 Google Inc.
|
|
//
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file or at
|
|
// https://developers.google.com/open-source/licenses/bsd
|
|
|
|
import 'package:html/dom.dart';
|
|
import 'package:html/parser.dart' show parseFragment;
|
|
|
|
import 'visitors/dart_class_info.dart';
|
|
|
|
/// Data for generating page object.
|
|
class PageObjectData {
|
|
static const pageLoaderDependency = 'package:pageloader/objects.dart';
|
|
static const asyncDependency = 'dart:async';
|
|
|
|
/// Common dependencies for page object classes.
|
|
List<String> get commonDependencies => [pageLoaderDependency]
|
|
..addAll(variables.isNotEmpty ? [asyncDependency] : []);
|
|
|
|
final List<_Variable> variables;
|
|
final DocumentFragment document;
|
|
|
|
factory PageObjectData(String templateFileContent) {
|
|
var document = parseFragment(templateFileContent);
|
|
|
|
var variables = document
|
|
.querySelectorAll('*')
|
|
.map((element) => new _Variable.fromElement(element))
|
|
.where((variable) => variable != null)
|
|
.toList(growable: false)
|
|
..sort();
|
|
|
|
return new PageObjectData._internal(document, variables);
|
|
}
|
|
|
|
PageObjectData._internal(this.document, this.variables);
|
|
}
|
|
|
|
class _Selector {
|
|
static const ignoredTags = const [
|
|
'a',
|
|
'p',
|
|
'b',
|
|
'i',
|
|
'small',
|
|
'strong',
|
|
'object',
|
|
'canvas',
|
|
'table',
|
|
'span',
|
|
'img',
|
|
'form',
|
|
'fieldset',
|
|
'li',
|
|
'center',
|
|
'label',
|
|
'br',
|
|
'legend',
|
|
'ul',
|
|
'ng-content'
|
|
];
|
|
|
|
final String type;
|
|
final String name;
|
|
final String value;
|
|
|
|
factory _Selector.fromElement(Element element) {
|
|
if (ignoredTags.contains(element.localName)) {
|
|
return null;
|
|
}
|
|
|
|
if (element.id.isNotEmpty) {
|
|
return new _Selector('ById', element.id);
|
|
}
|
|
|
|
if (element.classes.isNotEmpty) {
|
|
return new _Selector('ByClass', element.classes.first);
|
|
}
|
|
|
|
return new _Selector('ByTagName', element.localName);
|
|
}
|
|
|
|
_Selector(this.type, this.name, [this.value]);
|
|
|
|
@override
|
|
String toString() => "@$type('${value ?? name}')";
|
|
}
|
|
|
|
class _Variable implements Comparable<_Variable> {
|
|
static final wordReg = new RegExp(r'(^|[\-._])(\w)');
|
|
|
|
final Element element;
|
|
final _Selector selector;
|
|
final bool isList;
|
|
final bool isOptional;
|
|
final DartClassInfo type;
|
|
final String name;
|
|
|
|
factory _Variable.fromElement(Element element) {
|
|
var selector = new _Selector.fromElement(element);
|
|
if (selector == null) {
|
|
return null;
|
|
}
|
|
|
|
var type = new DartClassInfo(
|
|
'PageLoaderElement', 'package:pageloader/objects.dart');
|
|
|
|
return new _Variable(element, _getCamelCasedName(selector.name), selector,
|
|
type, _isElementInList(element), _isElementInIf(element));
|
|
}
|
|
|
|
_Variable(this.element, this.name, this.selector, this.type,
|
|
[this.isList = false, this.isOptional = false]);
|
|
|
|
static bool _isElementInList(Element element) {
|
|
while (element != null) {
|
|
if (element.attributes.keys.any((a) => ['*ngfor'].contains(a))) {
|
|
return true;
|
|
}
|
|
element = element.parent;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
static bool _isElementInIf(Element element) {
|
|
while (element != null) {
|
|
if (element.attributes.keys.contains('*ngif') ||
|
|
element.localName == 'template' &&
|
|
element.attributes.keys.contains('[ngif]')) {
|
|
return true;
|
|
}
|
|
element = element.parent;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
static String _getCamelCasedName(String name) =>
|
|
name.replaceAllMapped(wordReg, (m) => m[2].toUpperCase());
|
|
|
|
String get internalString => '${_getOptionalString()}'
|
|
'$selector\n'
|
|
' Lazy<${_getTypeString()}> _get$name;';
|
|
|
|
String get getterString =>
|
|
'Future<${_getTypeString()}> get $_getFirstCharacterLoweredName'
|
|
' => _get$name();';
|
|
|
|
String _getOptionalString() => isOptional ? '@optional\n' : '';
|
|
|
|
String _getTypeString() {
|
|
var s = type.className;
|
|
if (isList) {
|
|
s = 'List<$s>';
|
|
}
|
|
|
|
return s;
|
|
}
|
|
|
|
String get _getFirstCharacterLoweredName =>
|
|
name.replaceFirstMapped(new RegExp('^(.)'), (m) => m[1].toLowerCase());
|
|
|
|
@override
|
|
int compareTo(_Variable other) => name.compareTo(other.name);
|
|
}
|