TF-3243 Fix email without content
This commit is contained in:
+19
-11
@@ -1,5 +1,6 @@
|
||||
import 'package:core/data/network/dio_client.dart';
|
||||
import 'package:core/presentation/utils/html_transformer/base/dom_transformer.dart';
|
||||
import 'package:core/utils/app_logger.dart';
|
||||
import 'package:html/dom.dart';
|
||||
|
||||
class AddLazyLoadingForBackgroundImageTransformer extends DomTransformer {
|
||||
@@ -11,16 +12,23 @@ class AddLazyLoadingForBackgroundImageTransformer extends DomTransformer {
|
||||
required DioClient dioClient,
|
||||
Map<String, String>? mapUrlDownloadCID,
|
||||
}) async {
|
||||
final elements = document.querySelectorAll('[style*="background-image"]');
|
||||
await Future.wait(elements.map((element) async {
|
||||
var exStyle = element.attributes['style'];
|
||||
final imageUrls = findImageUrlFromStyleTag(exStyle!);
|
||||
if (imageUrls != null) {
|
||||
exStyle = exStyle.replaceFirst(imageUrls.value1, '');
|
||||
element.attributes['style'] = exStyle;
|
||||
element.attributes['data-src'] = imageUrls.value2;
|
||||
element.attributes.addAll({'lazy': ''});
|
||||
}
|
||||
}));
|
||||
try {
|
||||
final elements = document.querySelectorAll('[style*="background-image"]');
|
||||
|
||||
if (elements.isEmpty) return;
|
||||
|
||||
await Future.wait(elements.map((element) async {
|
||||
var exStyle = element.attributes['style'];
|
||||
final imageUrls = findImageUrlFromStyleTag(exStyle!);
|
||||
if (imageUrls != null) {
|
||||
exStyle = exStyle.replaceFirst(imageUrls.value1, '');
|
||||
element.attributes['style'] = exStyle;
|
||||
element.attributes['data-src'] = imageUrls.value2;
|
||||
element.attributes.addAll({'lazy': ''});
|
||||
}
|
||||
}));
|
||||
} catch (e) {
|
||||
logError('$runtimeType::process:Exception = $e');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
|
||||
import 'package:core/data/network/dio_client.dart';
|
||||
import 'package:core/presentation/utils/html_transformer/base/dom_transformer.dart';
|
||||
import 'package:core/utils/app_logger.dart';
|
||||
import 'package:html/dom.dart';
|
||||
|
||||
class BlockCodeTransformer extends DomTransformer {
|
||||
@@ -13,9 +14,13 @@ class BlockCodeTransformer extends DomTransformer {
|
||||
required DioClient dioClient,
|
||||
Map<String, String>? mapUrlDownloadCID,
|
||||
}) async {
|
||||
final codeElements = document.getElementsByTagName('pre');
|
||||
await Future.wait(codeElements.map((element) async {
|
||||
element.attributes['style'] = '''
|
||||
try {
|
||||
final codeElements = document.getElementsByTagName('pre');
|
||||
|
||||
if (codeElements.isEmpty) return;
|
||||
|
||||
await Future.wait(codeElements.map((element) async {
|
||||
element.attributes['style'] = '''
|
||||
display: block;
|
||||
padding: 10px;
|
||||
margin: 0 0 10px;
|
||||
@@ -28,7 +33,10 @@ class BlockCodeTransformer extends DomTransformer {
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
overflow: auto;
|
||||
''';
|
||||
}));
|
||||
''';
|
||||
}));
|
||||
} catch (e) {
|
||||
logError('$runtimeType::process:Exception = $e');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
|
||||
import 'package:core/data/network/dio_client.dart';
|
||||
import 'package:core/presentation/utils/html_transformer/base/dom_transformer.dart';
|
||||
import 'package:core/utils/app_logger.dart';
|
||||
import 'package:html/dom.dart';
|
||||
|
||||
class BlockQuotedTransformer extends DomTransformer {
|
||||
@@ -13,15 +14,22 @@ class BlockQuotedTransformer extends DomTransformer {
|
||||
required DioClient dioClient,
|
||||
Map<String, String>? mapUrlDownloadCID,
|
||||
}) async {
|
||||
final quotedElements = document.getElementsByTagName('blockquote');
|
||||
await Future.wait(quotedElements.map((quotedElement) async {
|
||||
quotedElement.attributes['style'] = '''
|
||||
try {
|
||||
final quotedElements = document.getElementsByTagName('blockquote');
|
||||
|
||||
if (quotedElements.isEmpty) return;
|
||||
|
||||
await Future.wait(quotedElements.map((quotedElement) async {
|
||||
quotedElement.attributes['style'] = '''
|
||||
margin-left: 4px;
|
||||
margin-right: 4px;
|
||||
padding-left: 8px;
|
||||
padding-right: 8px;
|
||||
border-left: 2px solid #eee;
|
||||
''';
|
||||
}));
|
||||
}));
|
||||
} catch (e) {
|
||||
logError('$runtimeType::process:Exception = $e');
|
||||
}
|
||||
}
|
||||
}
|
||||
+14
-9
@@ -1,5 +1,6 @@
|
||||
import 'package:core/data/network/dio_client.dart';
|
||||
import 'package:core/presentation/utils/html_transformer/base/dom_transformer.dart';
|
||||
import 'package:core/utils/app_logger.dart';
|
||||
import 'package:html/dom.dart';
|
||||
|
||||
class HideDraftSignatureTransformer extends DomTransformer {
|
||||
@@ -12,15 +13,19 @@ class HideDraftSignatureTransformer extends DomTransformer {
|
||||
required DioClient dioClient,
|
||||
Map<String, String>? mapUrlDownloadCID
|
||||
}) async {
|
||||
final signature = document.querySelector('div.tmail-signature');
|
||||
if (signature == null) return;
|
||||
final currentStyle = signature.attributes['style']?.trim();
|
||||
if (currentStyle == null) {
|
||||
signature.attributes['style'] = 'display: none;';
|
||||
} else if (currentStyle.endsWith(';')) {
|
||||
signature.attributes['style'] = '$currentStyle display: none;';
|
||||
} else {
|
||||
signature.attributes['style'] = '$currentStyle; display: none;';
|
||||
try {
|
||||
final signature = document.querySelector('div.tmail-signature');
|
||||
if (signature == null) return;
|
||||
final currentStyle = signature.attributes['style']?.trim();
|
||||
if (currentStyle == null) {
|
||||
signature.attributes['style'] = 'display: none;';
|
||||
} else if (currentStyle.endsWith(';')) {
|
||||
signature.attributes['style'] = '$currentStyle display: none;';
|
||||
} else {
|
||||
signature.attributes['style'] = '$currentStyle; display: none;';
|
||||
}
|
||||
} catch (e) {
|
||||
logError('$runtimeType::process:Exception = $e');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import 'package:core/data/network/dio_client.dart';
|
||||
import 'package:core/data/utils/compress_file_utils.dart';
|
||||
import 'package:core/presentation/extensions/html_extension.dart';
|
||||
import 'package:core/presentation/utils/html_transformer/base/dom_transformer.dart';
|
||||
import 'package:core/utils/app_logger.dart';
|
||||
import 'package:core/utils/platform_info.dart';
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
@@ -20,41 +21,48 @@ class ImageTransformer extends DomTransformer {
|
||||
required DioClient dioClient,
|
||||
Map<String, String>? mapUrlDownloadCID,
|
||||
}) async {
|
||||
final imageElements = document.querySelectorAll('img');
|
||||
await Future.wait(imageElements.map((imageElement) async {
|
||||
var exStyle = imageElement.attributes['style'];
|
||||
if (exStyle != null) {
|
||||
if (!exStyle.trim().endsWith(';')) {
|
||||
exStyle = '$exStyle;';
|
||||
}
|
||||
if (!exStyle.contains('display')) {
|
||||
exStyle = '$exStyle display:inline;';
|
||||
}
|
||||
if (!exStyle.contains('max-width')) {
|
||||
exStyle = '$exStyle max-width:100%;';
|
||||
}
|
||||
imageElement.attributes['style'] = exStyle;
|
||||
} else {
|
||||
imageElement.attributes['style'] = 'display:inline;max-width:100%;';
|
||||
}
|
||||
final src = imageElement.attributes['src'];
|
||||
try {
|
||||
final imageElements = document.querySelectorAll('img');
|
||||
|
||||
if (src == null) return;
|
||||
if (imageElements.isEmpty) return;
|
||||
|
||||
if (src.startsWith('cid:') && mapUrlDownloadCID != null) {
|
||||
final imageBase64 = await _convertCidToBase64Image(
|
||||
dioClient: dioClient,
|
||||
mapUrlDownloadCID: mapUrlDownloadCID,
|
||||
imageSource: src
|
||||
);
|
||||
imageElement.attributes['src'] = imageBase64 ?? src;
|
||||
imageElement.attributes['id'] ??= src;
|
||||
} else if (src.startsWith('https://') || src.startsWith('http://')) {
|
||||
if (!imageElement.attributes.containsKey('loading')) {
|
||||
imageElement.attributes['loading'] = 'lazy';
|
||||
await Future.wait(imageElements.map((imageElement) async {
|
||||
var exStyle = imageElement.attributes['style'];
|
||||
if (exStyle != null) {
|
||||
if (!exStyle.trim().endsWith(';')) {
|
||||
exStyle = '$exStyle;';
|
||||
}
|
||||
if (!exStyle.contains('display')) {
|
||||
exStyle = '$exStyle display:inline;';
|
||||
}
|
||||
if (!exStyle.contains('max-width')) {
|
||||
exStyle = '$exStyle max-width:100%;';
|
||||
}
|
||||
imageElement.attributes['style'] = exStyle;
|
||||
} else {
|
||||
imageElement.attributes['style'] = 'display:inline;max-width:100%;';
|
||||
}
|
||||
}
|
||||
}));
|
||||
final src = imageElement.attributes['src'];
|
||||
|
||||
if (src == null) return;
|
||||
|
||||
if (src.startsWith('cid:') && mapUrlDownloadCID != null) {
|
||||
final imageBase64 = await _convertCidToBase64Image(
|
||||
dioClient: dioClient,
|
||||
mapUrlDownloadCID: mapUrlDownloadCID,
|
||||
imageSource: src
|
||||
);
|
||||
imageElement.attributes['src'] = imageBase64 ?? src;
|
||||
imageElement.attributes['id'] ??= src;
|
||||
} else if (src.startsWith('https://') || src.startsWith('http://')) {
|
||||
if (!imageElement.attributes.containsKey('loading')) {
|
||||
imageElement.attributes['loading'] = 'lazy';
|
||||
}
|
||||
}
|
||||
}));
|
||||
} catch (e) {
|
||||
logError('$runtimeType::process:Exception = $e');
|
||||
}
|
||||
}
|
||||
|
||||
Future<String?> _convertCidToBase64Image({
|
||||
|
||||
+12
-4
@@ -1,6 +1,7 @@
|
||||
|
||||
import 'package:core/data/network/dio_client.dart';
|
||||
import 'package:core/presentation/utils/html_transformer/base/dom_transformer.dart';
|
||||
import 'package:core/utils/app_logger.dart';
|
||||
import 'package:html/dom.dart';
|
||||
|
||||
class RemoveCollapsedSignatureButtonTransformer extends DomTransformer {
|
||||
@@ -13,9 +14,16 @@ class RemoveCollapsedSignatureButtonTransformer extends DomTransformer {
|
||||
required DioClient dioClient,
|
||||
Map<String, String>? mapUrlDownloadCID,
|
||||
}) async {
|
||||
final elements = document.querySelectorAll('.tmail-signature-button');
|
||||
await Future.wait(elements.map((element) async {
|
||||
element.remove();
|
||||
}));
|
||||
try {
|
||||
final elements = document.querySelectorAll('.tmail-signature-button');
|
||||
|
||||
if (elements.isEmpty) return;
|
||||
|
||||
await Future.wait(elements.map((element) async {
|
||||
element.remove();
|
||||
}));
|
||||
} catch (e) {
|
||||
logError('$runtimeType::process:Exception = $e');
|
||||
}
|
||||
}
|
||||
}
|
||||
+22
-14
@@ -1,5 +1,6 @@
|
||||
import 'package:core/data/network/dio_client.dart';
|
||||
import 'package:core/presentation/utils/html_transformer/base/dom_transformer.dart';
|
||||
import 'package:core/utils/app_logger.dart';
|
||||
import 'package:html/dom.dart';
|
||||
|
||||
class RemoveLazyLoadingForBackgroundImageTransformer extends DomTransformer {
|
||||
@@ -11,19 +12,26 @@ class RemoveLazyLoadingForBackgroundImageTransformer extends DomTransformer {
|
||||
required DioClient dioClient,
|
||||
Map<String, String>? mapUrlDownloadCID,
|
||||
}) async {
|
||||
final elements = document.querySelectorAll('[lazy]');
|
||||
await Future.wait(elements.map((element) async {
|
||||
var exStyle = element.attributes['style'];
|
||||
final dataSrc = element.attributes['data-src'];
|
||||
final backgroundImgUrl = 'background-image:url($dataSrc);';
|
||||
if (exStyle != null) {
|
||||
exStyle = '$exStyle;$backgroundImgUrl';
|
||||
element.attributes['style'] = exStyle;
|
||||
} else {
|
||||
element.attributes['style'] = backgroundImgUrl;
|
||||
}
|
||||
element.attributes.remove('data-src');
|
||||
element.attributes.remove('lazy');
|
||||
}));
|
||||
try {
|
||||
final elements = document.querySelectorAll('[lazy]');
|
||||
|
||||
if (elements.isEmpty) return;
|
||||
|
||||
await Future.wait(elements.map((element) async {
|
||||
var exStyle = element.attributes['style'];
|
||||
final dataSrc = element.attributes['data-src'];
|
||||
final backgroundImgUrl = 'background-image:url($dataSrc);';
|
||||
if (exStyle != null) {
|
||||
exStyle = '$exStyle;$backgroundImgUrl';
|
||||
element.attributes['style'] = exStyle;
|
||||
} else {
|
||||
element.attributes['style'] = backgroundImgUrl;
|
||||
}
|
||||
element.attributes.remove('data-src');
|
||||
element.attributes.remove('lazy');
|
||||
}));
|
||||
} catch (e) {
|
||||
logError('$runtimeType::process:Exception = $e');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+12
-4
@@ -1,5 +1,6 @@
|
||||
import 'package:core/data/network/dio_client.dart';
|
||||
import 'package:core/presentation/utils/html_transformer/base/dom_transformer.dart';
|
||||
import 'package:core/utils/app_logger.dart';
|
||||
import 'package:html/dom.dart';
|
||||
|
||||
class RemoveLazyLoadingImageTransformer extends DomTransformer {
|
||||
@@ -11,9 +12,16 @@ class RemoveLazyLoadingImageTransformer extends DomTransformer {
|
||||
required DioClient dioClient,
|
||||
Map<String, String>? mapUrlDownloadCID,
|
||||
}) async {
|
||||
final elements = document.querySelectorAll('img[loading]');
|
||||
await Future.wait(elements.map((element) async {
|
||||
element.attributes.remove('loading');
|
||||
}));
|
||||
try {
|
||||
final elements = document.querySelectorAll('img[loading]');
|
||||
|
||||
if (elements.isEmpty) return;
|
||||
|
||||
await Future.wait(elements.map((element) async {
|
||||
element.attributes.remove('loading');
|
||||
}));
|
||||
} catch (e) {
|
||||
logError('$runtimeType::process:Exception = $e');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+16
-8
@@ -1,5 +1,6 @@
|
||||
import 'package:core/data/network/dio_client.dart';
|
||||
import 'package:core/presentation/utils/html_transformer/base/dom_transformer.dart';
|
||||
import 'package:core/utils/app_logger.dart';
|
||||
import 'package:html/dom.dart';
|
||||
|
||||
class RemoveMaxWidthInImageStyleTransformer extends DomTransformer {
|
||||
@@ -12,13 +13,20 @@ class RemoveMaxWidthInImageStyleTransformer extends DomTransformer {
|
||||
required DioClient dioClient,
|
||||
Map<String, String>? mapUrlDownloadCID,
|
||||
}) async {
|
||||
final imageElements = document.querySelectorAll('img[style*="max-width"]');
|
||||
await Future.wait(imageElements.map((imageElement) async {
|
||||
var exStyle = imageElement.attributes['style'];
|
||||
if (exStyle != null) {
|
||||
exStyle = exStyle.replaceAll('max-width:100%;', '');
|
||||
imageElement.attributes['style'] = exStyle;
|
||||
}
|
||||
}));
|
||||
try {
|
||||
final imageElements = document.querySelectorAll('img[style*="max-width"]');
|
||||
|
||||
if (imageElements.isEmpty) return;
|
||||
|
||||
await Future.wait(imageElements.map((imageElement) async {
|
||||
var exStyle = imageElement.attributes['style'];
|
||||
if (exStyle != null) {
|
||||
exStyle = exStyle.replaceAll('max-width:100%;', '');
|
||||
imageElement.attributes['style'] = exStyle;
|
||||
}
|
||||
}));
|
||||
} catch (e) {
|
||||
logError('$runtimeType::process:Exception = $e');
|
||||
}
|
||||
}
|
||||
}
|
||||
+12
-4
@@ -1,5 +1,6 @@
|
||||
import 'package:core/data/network/dio_client.dart';
|
||||
import 'package:core/presentation/utils/html_transformer/base/dom_transformer.dart';
|
||||
import 'package:core/utils/app_logger.dart';
|
||||
import 'package:html/dom.dart';
|
||||
|
||||
class RemoveStyleTagOutsideTransformer extends DomTransformer {
|
||||
@@ -12,9 +13,16 @@ class RemoveStyleTagOutsideTransformer extends DomTransformer {
|
||||
required DioClient dioClient,
|
||||
Map<String, String>? mapUrlDownloadCID,
|
||||
}) async {
|
||||
final styleElements = document.querySelectorAll('style');
|
||||
await Future.wait(styleElements.map((element) async {
|
||||
element.remove();
|
||||
}));
|
||||
try {
|
||||
final styleElements = document.querySelectorAll('style');
|
||||
|
||||
if (styleElements.isEmpty) return;
|
||||
|
||||
await Future.wait(styleElements.map((element) async {
|
||||
element.remove();
|
||||
}));
|
||||
} catch (e) {
|
||||
logError('$runtimeType::process:Exception = $e');
|
||||
}
|
||||
}
|
||||
}
|
||||
+21
-13
@@ -1,6 +1,7 @@
|
||||
|
||||
import 'package:core/data/network/dio_client.dart';
|
||||
import 'package:core/presentation/utils/html_transformer/base/dom_transformer.dart';
|
||||
import 'package:core/utils/app_logger.dart';
|
||||
import 'package:core/utils/html/html_template.dart';
|
||||
import 'package:html/dom.dart';
|
||||
|
||||
@@ -14,20 +15,27 @@ class RemoveTooltipLinkTransformer extends DomTransformer {
|
||||
required DioClient dioClient,
|
||||
Map<String, String>? mapUrlDownloadCID,
|
||||
}) async {
|
||||
final linkElements = document.querySelectorAll('a.${HtmlTemplate.nameClassToolTip}');
|
||||
await Future.wait(linkElements.map((linkElement) async {
|
||||
final classAttribute = linkElement.attributes['class'];
|
||||
if (classAttribute != null) {
|
||||
final newClassAttribute = classAttribute.replaceFirst(HtmlTemplate.nameClassToolTip, '');
|
||||
linkElement.attributes['class'] = newClassAttribute;
|
||||
}
|
||||
final listSpanTag = linkElement.querySelectorAll('span.tooltiptext');
|
||||
if (listSpanTag.isNotEmpty) {
|
||||
for (var element in listSpanTag) {
|
||||
element.remove();
|
||||
try {
|
||||
final linkElements = document.querySelectorAll('a.${HtmlTemplate.nameClassToolTip}');
|
||||
|
||||
if (linkElements.isEmpty) return;
|
||||
|
||||
await Future.wait(linkElements.map((linkElement) async {
|
||||
final classAttribute = linkElement.attributes['class'];
|
||||
if (classAttribute != null) {
|
||||
final newClassAttribute = classAttribute.replaceFirst(HtmlTemplate.nameClassToolTip, '');
|
||||
linkElement.attributes['class'] = newClassAttribute;
|
||||
}
|
||||
}
|
||||
}));
|
||||
final listSpanTag = linkElement.querySelectorAll('span.tooltiptext');
|
||||
if (listSpanTag.isNotEmpty) {
|
||||
for (var element in listSpanTag) {
|
||||
element.remove();
|
||||
}
|
||||
}
|
||||
}));
|
||||
} catch (e) {
|
||||
logError('$runtimeType::process:Exception = $e');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+17
-9
@@ -1,6 +1,7 @@
|
||||
import 'package:core/data/network/dio_client.dart';
|
||||
import 'package:core/presentation/utils/html_transformer/base/dom_transformer.dart';
|
||||
import 'package:core/presentation/utils/html_transformer/sanitize_url.dart';
|
||||
import 'package:core/utils/app_logger.dart';
|
||||
import 'package:core/utils/html/html_template.dart';
|
||||
import 'package:html/dom.dart';
|
||||
|
||||
@@ -16,15 +17,22 @@ class SanitizeHyperLinkTagInHtmlTransformer extends DomTransformer {
|
||||
required DioClient dioClient,
|
||||
Map<String, String>? mapUrlDownloadCID,
|
||||
}) async {
|
||||
final elements = document.querySelectorAll('a');
|
||||
await Future.wait(elements.map((element) async {
|
||||
_sanitizeUrlResource(element);
|
||||
if (useTooltip) {
|
||||
_addToolTipWhenHoverLink(element);
|
||||
}
|
||||
_addBlankForTargetProperty(element);
|
||||
_addNoReferrerForRelProperty(element);
|
||||
}));
|
||||
try {
|
||||
final elements = document.querySelectorAll('a');
|
||||
|
||||
if (elements.isEmpty) return;
|
||||
|
||||
await Future.wait(elements.map((element) async {
|
||||
_sanitizeUrlResource(element);
|
||||
if (useTooltip) {
|
||||
_addToolTipWhenHoverLink(element);
|
||||
}
|
||||
_addBlankForTargetProperty(element);
|
||||
_addNoReferrerForRelProperty(element);
|
||||
}));
|
||||
} catch (e) {
|
||||
logError('$runtimeType::process:Exception = $e');
|
||||
}
|
||||
}
|
||||
|
||||
void _sanitizeUrlResource(Element element) {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
|
||||
import 'package:core/data/network/dio_client.dart';
|
||||
import 'package:core/utils/app_logger.dart';
|
||||
import 'package:html/dom.dart';
|
||||
import 'package:core/presentation/utils/html_transformer/base/dom_transformer.dart';
|
||||
|
||||
@@ -13,9 +14,16 @@ class RemoveScriptTransformer extends DomTransformer {
|
||||
required DioClient dioClient,
|
||||
Map<String, String>? mapUrlDownloadCID,
|
||||
}) async {
|
||||
final scriptElements = document.getElementsByTagName('script');
|
||||
await Future.wait(scriptElements.map((scriptElement) async {
|
||||
scriptElement.remove();
|
||||
}));
|
||||
try {
|
||||
final scriptElements = document.getElementsByTagName('script');
|
||||
|
||||
if (scriptElements.isEmpty) return;
|
||||
|
||||
await Future.wait(scriptElements.map((scriptElement) async {
|
||||
scriptElement.remove();
|
||||
}));
|
||||
} catch (e) {
|
||||
logError('$runtimeType::process:Exception = $e');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
|
||||
import 'package:core/data/network/dio_client.dart';
|
||||
import 'package:core/presentation/utils/html_transformer/base/dom_transformer.dart';
|
||||
import 'package:core/utils/app_logger.dart';
|
||||
import 'package:html/dom.dart';
|
||||
|
||||
class SignatureTransformer extends DomTransformer {
|
||||
@@ -13,9 +14,16 @@ class SignatureTransformer extends DomTransformer {
|
||||
required DioClient dioClient,
|
||||
Map<String, String>? mapUrlDownloadCID,
|
||||
}) async {
|
||||
final signatureElements = document.querySelectorAll('div.tmail-signature');
|
||||
await Future.wait(signatureElements.map((element) async {
|
||||
element.attributes['class'] = 'tmail-signature-blocked';
|
||||
}));
|
||||
try {
|
||||
final signatureElements = document.querySelectorAll('div.tmail-signature');
|
||||
|
||||
if (signatureElements.isEmpty) return;
|
||||
|
||||
await Future.wait(signatureElements.map((element) async {
|
||||
element.attributes['class'] = 'tmail-signature-blocked';
|
||||
}));
|
||||
} catch (e) {
|
||||
logError('$runtimeType::process:Exception = $e');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,38 +21,43 @@ class SanitizeAutolinkFilter {
|
||||
SanitizeAutolinkFilter(this.htmlEscape);
|
||||
|
||||
String process(String inputText) {
|
||||
if (inputText.isEmpty) {
|
||||
return '';
|
||||
}
|
||||
|
||||
final elements = linkify(
|
||||
inputText,
|
||||
options: _linkifyOption,
|
||||
linkifiers: _linkifier
|
||||
);
|
||||
log('AutolinkFilter::process:elements: $elements');
|
||||
final htmlTextBuffer = StringBuffer();
|
||||
|
||||
for (var element in elements) {
|
||||
if (element is TextElement) {
|
||||
final escapedHtml = htmlEscape.convert(element.text);
|
||||
htmlTextBuffer.write(escapedHtml);
|
||||
} else if (element is EmailElement) {
|
||||
final emailLinkTag = _buildEmailLinkTag(
|
||||
mailToLink: element.url,
|
||||
value: element.text
|
||||
);
|
||||
htmlTextBuffer.write(emailLinkTag);
|
||||
} else if (element is UrlElement) {
|
||||
final urlLinkTag = _buildUrlLinkTag(
|
||||
urlLink: element.url,
|
||||
value: element.text
|
||||
);
|
||||
htmlTextBuffer.write(urlLinkTag);
|
||||
try {
|
||||
if (inputText.isEmpty) {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
return htmlTextBuffer.toString();
|
||||
final elements = linkify(
|
||||
inputText,
|
||||
options: _linkifyOption,
|
||||
linkifiers: _linkifier,
|
||||
);
|
||||
log('AutolinkFilter::process:elements: $elements');
|
||||
final htmlTextBuffer = StringBuffer();
|
||||
|
||||
for (var element in elements) {
|
||||
if (element is TextElement) {
|
||||
final escapedHtml = htmlEscape.convert(element.text);
|
||||
htmlTextBuffer.write(escapedHtml);
|
||||
} else if (element is EmailElement) {
|
||||
final emailLinkTag = _buildEmailLinkTag(
|
||||
mailToLink: element.url,
|
||||
value: element.text
|
||||
);
|
||||
htmlTextBuffer.write(emailLinkTag);
|
||||
} else if (element is UrlElement) {
|
||||
final urlLinkTag = _buildUrlLinkTag(
|
||||
urlLink: element.url,
|
||||
value: element.text
|
||||
);
|
||||
htmlTextBuffer.write(urlLinkTag);
|
||||
}
|
||||
}
|
||||
|
||||
return htmlTextBuffer.toString();
|
||||
} catch (e) {
|
||||
logError('$runtimeType::process:Exception = $e');
|
||||
return inputText;
|
||||
}
|
||||
}
|
||||
|
||||
String _buildUrlLinkTag({required String urlLink, required String value}) {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import 'package:core/utils/app_logger.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
class SanitizeUrl {
|
||||
@@ -12,17 +13,20 @@ class SanitizeUrl {
|
||||
);
|
||||
|
||||
String process(String inputText) {
|
||||
var originalUrl = inputText;
|
||||
|
||||
originalUrl = Uri.decodeFull(originalUrl);
|
||||
|
||||
if (GetUtils.isURL(originalUrl)) {
|
||||
if (!originalUrl.startsWith(_protocolIdentifierRegex)) {
|
||||
originalUrl = (defaultToHttps ? "https://" : "http://") + originalUrl;
|
||||
try {
|
||||
log('SanitizeUrl::process:inputText = $inputText');
|
||||
var originalUrl = Uri.decodeFull(inputText);
|
||||
if (GetUtils.isURL(originalUrl)) {
|
||||
originalUrl = !originalUrl.startsWith(_protocolIdentifierRegex)
|
||||
? (defaultToHttps ? "https://" : "http://") + originalUrl
|
||||
: originalUrl;
|
||||
} else {
|
||||
originalUrl = '';
|
||||
}
|
||||
} else {
|
||||
originalUrl = '';
|
||||
return originalUrl;
|
||||
} catch (e) {
|
||||
logError('SanitizeUrl::process:Exception = $e');
|
||||
return inputText;
|
||||
}
|
||||
return originalUrl;
|
||||
}
|
||||
}
|
||||
@@ -108,5 +108,17 @@ void main() {
|
||||
equals('http://linagora.com')
|
||||
);
|
||||
});
|
||||
|
||||
test('SHOULD returns original input WHEN get an exception', () {
|
||||
// Arrange
|
||||
const inputText = "%E0%A4%A";
|
||||
const expectedOutput = inputText;
|
||||
|
||||
// Act
|
||||
final result = sanitizeUrl.process(inputText);
|
||||
|
||||
// Assert
|
||||
expect(result, expectedOutput);
|
||||
});
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user