mirror of
https://gitlab.opencode.de/bwi/bundesmessenger/clients/bundesmessenger-ios.git
synced 2026-04-19 16:13:42 +02:00
Improve HTML formatter
This commit is contained in:
@@ -28,6 +28,7 @@
|
||||
#import "MXRoom+Sync.h"
|
||||
|
||||
#import "MXKRoomNameStringLocalizer.h"
|
||||
#import "GeneratedInterface-Swift.h"
|
||||
|
||||
static NSString *const kHTMLATagRegexPattern = @"<a href=(?:'|\")(.*?)(?:'|\")>([^<]*)</a>";
|
||||
|
||||
@@ -1723,7 +1724,8 @@ static NSString *const kHTMLATagRegexPattern = @"<a href=(?:'|\")(.*?)(?:'|\")>(
|
||||
{
|
||||
// body font is the same with the whole string font, no need to change body font
|
||||
// apply additional treatments
|
||||
return [self postRenderAttributedString:str];
|
||||
[self postRenderAttributedString:str];
|
||||
return str;
|
||||
}
|
||||
|
||||
NSString *body;
|
||||
@@ -1740,13 +1742,14 @@ static NSString *const kHTMLATagRegexPattern = @"<a href=(?:'|\")(.*?)(?:'|\")>(
|
||||
{
|
||||
// body not found in the whole string
|
||||
// apply additional treatments
|
||||
return [self postRenderAttributedString:str];
|
||||
[self postRenderAttributedString:str];
|
||||
return str;
|
||||
}
|
||||
|
||||
NSMutableAttributedString *mutableStr = [str mutableCopy];
|
||||
[mutableStr addAttribute:NSFontAttributeName value:fontForBody range:bodyRange];
|
||||
[str addAttribute:NSFontAttributeName value:fontForBody range:bodyRange];
|
||||
// apply additional treatments
|
||||
return [self postRenderAttributedString:mutableStr];
|
||||
[self postRenderAttributedString:str];
|
||||
return str;
|
||||
}
|
||||
|
||||
- (NSAttributedString*)renderHTMLString:(NSString*)htmlString forEvent:(MXEvent*)event withRoomState:(MXRoomState*)roomState
|
||||
@@ -1769,81 +1772,25 @@ static NSString *const kHTMLATagRegexPattern = @"<a href=(?:'|\")(.*?)(?:'|\")>(
|
||||
|
||||
// Apply the css style that corresponds to the event state
|
||||
UIFont *fontForWholeString = [self fontForEvent:event string:htmlString];
|
||||
|
||||
// Do some sanitisation before finalizing the string
|
||||
|
||||
HTMLFormatter *htmlFormatter = [[HTMLFormatter alloc] init];
|
||||
|
||||
MXWeakify(self);
|
||||
DTHTMLAttributedStringBuilderWillFlushCallback sanitizeCallback = ^(DTHTMLElement *element) {
|
||||
NSAttributedString *str = [htmlFormatter formatHTML:html
|
||||
withAllowedTags:_allowedHTMLTags
|
||||
andImageHandler:_htmlImageHandler
|
||||
extraOptions:@{ DTDefaultTextColor: [self textColorForEvent:event],
|
||||
DTDefaultStyleSheet: dtCSS }
|
||||
font:fontForWholeString
|
||||
postFormatOperations:^(NSMutableAttributedString *mutableStr) {
|
||||
MXStrongifyAndReturnIfNil(self);
|
||||
[element sanitizeWith:self.allowedHTMLTags bodyFont:fontForWholeString imageHandler:self.htmlImageHandler];
|
||||
};
|
||||
[self postFormatMutableAttributedString:mutableStr
|
||||
forEvent:event
|
||||
andRepliedEvent:repliedEvent
|
||||
defaultFont:fontForWholeString];
|
||||
}];
|
||||
|
||||
NSDictionary *options = @{
|
||||
DTUseiOS6Attributes: @(YES), // Enable it to be able to display the attributed string in a UITextView
|
||||
DTDefaultFontFamily: fontForWholeString.familyName,
|
||||
DTDefaultFontName: fontForWholeString.fontName,
|
||||
DTDefaultFontSize: @(fontForWholeString.pointSize),
|
||||
DTDefaultTextColor: [self textColorForEvent:event],
|
||||
DTDefaultLinkDecoration: @(NO),
|
||||
DTDefaultStyleSheet: dtCSS,
|
||||
DTWillFlushBlockCallBack: sanitizeCallback
|
||||
};
|
||||
|
||||
// Do not use the default HTML renderer of NSAttributedString because this method
|
||||
// runs on the UI thread which we want to avoid because renderHTMLString is called
|
||||
// most of the time from a background thread.
|
||||
// Use DTCoreText HTML renderer instead.
|
||||
// Using DTCoreText, which renders static string, helps to avoid code injection attacks
|
||||
// that could happen with the default HTML renderer of NSAttributedString which is a
|
||||
// webview.
|
||||
NSAttributedString *str = [[NSAttributedString alloc] initWithHTMLData:[html dataUsingEncoding:NSUTF8StringEncoding] options:options documentAttributes:NULL];
|
||||
|
||||
// Apply additional treatments
|
||||
str = [self postRenderAttributedString:str];
|
||||
|
||||
// Finalize the attributed string by removing DTCoreText artifacts (Trim trailing newlines).
|
||||
str = [MXKTools removeDTCoreTextArtifacts:str];
|
||||
|
||||
// Finalize HTML blockquote blocks marking
|
||||
str = [MXKTools removeMarkedBlockquotesArtifacts:str];
|
||||
|
||||
if (repliedEvent && repliedEvent.isRedactedEvent)
|
||||
{
|
||||
// Replace the description of an empty replied event
|
||||
NSMutableAttributedString *mutableStr = [[NSMutableAttributedString alloc] initWithAttributedString:str];
|
||||
NSRange nullRange = [mutableStr.string rangeOfString:@"(null)"];
|
||||
if (nullRange.location != NSNotFound)
|
||||
{
|
||||
[mutableStr replaceCharactersInRange:nullRange withAttributedString:[self redactedMessageReplacementAttributedString]];
|
||||
str = mutableStr;
|
||||
}
|
||||
}
|
||||
|
||||
UIFont *fontForBody = [self fontForEvent:event string:nil];
|
||||
if ([fontForWholeString isEqual:fontForBody])
|
||||
{
|
||||
// body font is the same with the whole string font, no need to change body font
|
||||
return str;
|
||||
}
|
||||
|
||||
NSString *body;
|
||||
if (event.content[kMXMessageContentKeyNewContent])
|
||||
{
|
||||
MXJSONModelSetString(body, event.content[kMXMessageContentKeyNewContent][kMXMessageBodyKey]);
|
||||
}
|
||||
else
|
||||
{
|
||||
MXJSONModelSetString(body, event.content[kMXMessageBodyKey]);
|
||||
}
|
||||
NSRange bodyRange = [str.string rangeOfString:body];
|
||||
if (bodyRange.location == NSNotFound)
|
||||
{
|
||||
// body not found in the whole string
|
||||
return str;
|
||||
}
|
||||
|
||||
NSMutableAttributedString *mutableStr = [str mutableCopy];
|
||||
[mutableStr addAttribute:NSFontAttributeName value:fontForBody range:bodyRange];
|
||||
return mutableStr;
|
||||
return str;
|
||||
}
|
||||
|
||||
- (NSAttributedString*)redactedMessageReplacementAttributedString
|
||||
@@ -2017,11 +1964,55 @@ static NSString *const kHTMLATagRegexPattern = @"<a href=(?:'|\")(.*?)(?:'|\")>(
|
||||
return html;
|
||||
}
|
||||
|
||||
- (NSAttributedString*)postRenderAttributedString:(NSAttributedString*)attributedString
|
||||
- (void)postFormatMutableAttributedString:(NSMutableAttributedString*)mutableAttributedString
|
||||
forEvent:(MXEvent*)event
|
||||
andRepliedEvent:(MXEvent*)repliedEvent
|
||||
defaultFont:(UIFont*)defaultFont
|
||||
{
|
||||
if (!attributedString)
|
||||
[self postRenderAttributedString:mutableAttributedString];
|
||||
[MXKTools removeMarkedBlockquotesArtifacts:mutableAttributedString];
|
||||
|
||||
if (repliedEvent && repliedEvent.isRedactedEvent)
|
||||
{
|
||||
return nil;
|
||||
// Replace the description of an empty replied event
|
||||
NSRange nullRange = [mutableAttributedString.string rangeOfString:@"(null)"];
|
||||
if (nullRange.location != NSNotFound)
|
||||
{
|
||||
[mutableAttributedString replaceCharactersInRange:nullRange withAttributedString:[self redactedMessageReplacementAttributedString]];
|
||||
}
|
||||
}
|
||||
|
||||
UIFont *fontForBody = [self fontForEvent:event string:nil];
|
||||
if ([defaultFont isEqual:fontForBody])
|
||||
{
|
||||
// body font is the same with the whole string font, no need to change body font
|
||||
return;
|
||||
}
|
||||
|
||||
NSString *body;
|
||||
if (event.content[kMXMessageContentKeyNewContent])
|
||||
{
|
||||
MXJSONModelSetString(body, event.content[kMXMessageContentKeyNewContent][kMXMessageBodyKey]);
|
||||
}
|
||||
else
|
||||
{
|
||||
MXJSONModelSetString(body, event.content[kMXMessageBodyKey]);
|
||||
}
|
||||
NSRange bodyRange = [mutableAttributedString.string rangeOfString:body];
|
||||
if (bodyRange.location == NSNotFound)
|
||||
{
|
||||
// body not found in the whole string
|
||||
return;
|
||||
}
|
||||
|
||||
[mutableAttributedString addAttribute:NSFontAttributeName value:fontForBody range:bodyRange];
|
||||
}
|
||||
|
||||
- (void)postRenderAttributedString:(NSMutableAttributedString*)mutableAttributedString
|
||||
{
|
||||
if (!mutableAttributedString)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
NSInteger enabledMatrixIdsBitMask= 0;
|
||||
@@ -2056,7 +2047,7 @@ static NSString *const kHTMLATagRegexPattern = @"<a href=(?:'|\")(.*?)(?:'|\")>(
|
||||
enabledMatrixIdsBitMask |= MXKTOOLS_GROUP_IDENTIFIER_BITWISE;
|
||||
}
|
||||
|
||||
return [MXKTools createLinksInAttributedString:attributedString forEnabledMatrixIds:enabledMatrixIdsBitMask];
|
||||
[MXKTools createLinksInMutableAttributedString:mutableAttributedString forEnabledMatrixIds:enabledMatrixIdsBitMask];
|
||||
}
|
||||
|
||||
- (NSAttributedString *)renderString:(NSString *)string withPrefix:(NSString *)prefix forEvent:(MXEvent *)event
|
||||
|
||||
Reference in New Issue
Block a user