Skip to content

Commit

Permalink
Merge pull request #1283 from wordpress-mobile/release/1.19.0
Browse files Browse the repository at this point in the history
Release/1.19.0
  • Loading branch information
SergioEstevao authored May 6, 2020
2 parents c6a8103 + fe24074 commit 26443eb
Show file tree
Hide file tree
Showing 19 changed files with 258 additions and 12 deletions.
16 changes: 16 additions & 0 deletions Aztec.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,10 @@
FF7A1C511E5651EA00C4C7C8 /* LineAttachment.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF7A1C501E5651EA00C4C7C8 /* LineAttachment.swift */; };
FF7C89B01E3BC52F000472A8 /* NSAttributedString+FontTraits.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF7C89AF1E3BC52F000472A8 /* NSAttributedString+FontTraits.swift */; };
FF7EAEC4234D253B007A26E0 /* FontProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF7EAEC3234D253B007A26E0 /* FontProvider.swift */; };
FF94935E245738AC0085ABB3 /* SuperscriptStringAttributeConverter.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF94935D245738AC0085ABB3 /* SuperscriptStringAttributeConverter.swift */; };
FF949360245740250085ABB3 /* SuperscriptFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF94935F245740250085ABB3 /* SuperscriptFormatter.swift */; };
FF949362245744090085ABB3 /* SubscriptStringAttributeConverter.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF949361245744090085ABB3 /* SubscriptStringAttributeConverter.swift */; };
FF949364245744560085ABB3 /* SubscriptFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF949363245744560085ABB3 /* SubscriptFormatter.swift */; };
FFA61E891DF18F3D00B71BF6 /* ParagraphStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFA61E881DF18F3D00B71BF6 /* ParagraphStyle.swift */; };
FFA61EC21DF6C1C900B71BF6 /* NSAttributedString+Archive.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFA61EC11DF6C1C900B71BF6 /* NSAttributedString+Archive.swift */; };
FFB5D29720BEB21A0038DCFB /* CiteFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFB5D29620BEB21A0038DCFB /* CiteFormatter.swift */; };
Expand Down Expand Up @@ -523,6 +527,10 @@
FF7A1C501E5651EA00C4C7C8 /* LineAttachment.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LineAttachment.swift; sourceTree = "<group>"; };
FF7C89AF1E3BC52F000472A8 /* NSAttributedString+FontTraits.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSAttributedString+FontTraits.swift"; sourceTree = "<group>"; };
FF7EAEC3234D253B007A26E0 /* FontProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FontProvider.swift; sourceTree = "<group>"; };
FF94935D245738AC0085ABB3 /* SuperscriptStringAttributeConverter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SuperscriptStringAttributeConverter.swift; sourceTree = "<group>"; };
FF94935F245740250085ABB3 /* SuperscriptFormatter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SuperscriptFormatter.swift; sourceTree = "<group>"; };
FF949361245744090085ABB3 /* SubscriptStringAttributeConverter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SubscriptStringAttributeConverter.swift; sourceTree = "<group>"; };
FF949363245744560085ABB3 /* SubscriptFormatter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SubscriptFormatter.swift; sourceTree = "<group>"; };
FFA61E881DF18F3D00B71BF6 /* ParagraphStyle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ParagraphStyle.swift; sourceTree = "<group>"; };
FFA61EC11DF6C1C900B71BF6 /* NSAttributedString+Archive.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSAttributedString+Archive.swift"; sourceTree = "<group>"; };
FFB5D29620BEB21A0038DCFB /* CiteFormatter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CiteFormatter.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1004,6 +1012,8 @@
F12F585F1EF20394008AE298 /* StrikethroughFormatter.swift */,
F12F58601EF20394008AE298 /* TextListFormatter.swift */,
F12F58611EF20394008AE298 /* UnderlineFormatter.swift */,
FF94935F245740250085ABB3 /* SuperscriptFormatter.swift */,
FF949363245744560085ABB3 /* SubscriptFormatter.swift */,
FF61909D202481F4004BCD0A /* CodeFormatter.swift */,
FFB5D29620BEB21A0038DCFB /* CiteFormatter.swift */,
);
Expand Down Expand Up @@ -1089,6 +1099,8 @@
F15BA6082151501300424120 /* BoldStringAttributeConverter.swift */,
F1656FDD2152A6A6009C7E3A /* CiteStringAttributeConverter.swift */,
F15BA60C215159A600424120 /* ItalicStringAttributeConverter.swift */,
FF94935D245738AC0085ABB3 /* SuperscriptStringAttributeConverter.swift */,
FF949361245744090085ABB3 /* SubscriptStringAttributeConverter.swift */,
F15BA60E21515C0F00424120 /* UnderlineStringAttributeConverter.swift */,
);
path = Implementations;
Expand Down Expand Up @@ -1587,6 +1599,7 @@
F16A2AD520CC437E00BF3A0A /* LineAttachmentToElementConverter.swift in Sources */,
B574F4A41FB0CF3B0048F355 /* NSAttributedStringKey+Conversion.swift in Sources */,
F12F58631EF20394008AE298 /* AttributeFormatter.swift in Sources */,
FF949360245740250085ABB3 /* SuperscriptFormatter.swift in Sources */,
F19544051F588F1A00671B73 /* CSSParser.swift in Sources */,
599F254E1D8BC9A1002871D6 /* FormatBarDelegate.swift in Sources */,
F109873F214FF4C400983B6A /* ElementAttributeConverter.swift in Sources */,
Expand Down Expand Up @@ -1630,6 +1643,7 @@
F11326B21EF1AA91007FEE9A /* HTMLPre.swift in Sources */,
F1098741214FF55F00983B6A /* BoldElementAttributeConverter.swift in Sources */,
F17BC8AB1F4E512800398E2B /* AttributedStringSerializer.swift in Sources */,
FF949364245744560085ABB3 /* SubscriptFormatter.swift in Sources */,
F18986E11EF2040A0060EDBA /* FontFormatter.swift in Sources */,
F1FF7D9D201A147B007B0B32 /* Figure.swift in Sources */,
FFA61E891DF18F3D00B71BF6 /* ParagraphStyle.swift in Sources */,
Expand All @@ -1638,6 +1652,7 @@
FF7C89B01E3BC52F000472A8 /* NSAttributedString+FontTraits.swift in Sources */,
B5E94D101FE01335000E7C20 /* FigureElementConverter.swift in Sources */,
40A2986D1FD61B0C00AEDF3B /* ElementConverter.swift in Sources */,
FF949362245744090085ABB3 /* SubscriptStringAttributeConverter.swift in Sources */,
F1FF7DA1201A1D3E007B0B32 /* FigcaptionElementConverter.swift in Sources */,
F9982CF621877663001E606B /* TextViewPasteboardDelegate.swift in Sources */,
F1289FB72155244A001E07C5 /* AttributeType.swift in Sources */,
Expand Down Expand Up @@ -1684,6 +1699,7 @@
F12F586F1EF20394008AE298 /* PreFormatter.swift in Sources */,
F18A1EA921C0586E00F1AA9E /* NSAttributedString+ParagraphRange.swift in Sources */,
B5B86D371DA3EC250083DB3F /* NSRange+Helpers.swift in Sources */,
FF94935E245738AC0085ABB3 /* SuperscriptStringAttributeConverter.swift in Sources */,
F15BA6172151693F00424120 /* BoldCSSAttributeMatcher.swift in Sources */,
F1E2323420C18055008DA49F /* FormatterElementConverter.swift in Sources */,
F15BA60B2151519C00424120 /* CSSAttributeType.swift in Sources */,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class GenericElementConverter: ElementConverter {
/// At some point we should modify how the conversion works, so that any supported element never goes through this
/// converter at all, and this converter is turned into an `UnsupportedElementConverter()` exclusively.
///
private static let supportedElements: [Element] = [.a, .aztecRootNode, .b, .br, .blockquote, .del, .div, .em, .figure, .figcaption, .h1, .h2, .h3, .h4, .h5, .h6, .hr, .i, .img, .li, .ol, .p, .pre, .s, .span, .strike, .strong, .u, .ul, .video, .code]
private static let supportedElements: [Element] = [.a, .aztecRootNode, .b, .br, .blockquote, .del, .div, .em, .figure, .figcaption, .h1, .h2, .h3, .h4, .h5, .h6, .hr, .i, .img, .li, .ol, .p, .pre, .s, .span, .strike, .strong, .u, .ul, .video, .code, .sup, .sub]

// MARK: - Built-in formatter instances

Expand All @@ -34,6 +34,8 @@ class GenericElementConverter: ElementConverter {
lazy var unorderedListFormatter = TextListFormatter(style: .unordered, increaseDepth: true)
lazy var codeFormatter = CodeFormatter()
lazy var liFormatter = LiFormatter()
lazy var superscriptFormatter = SuperscriptFormatter()
lazy var subscriptFormatter = SubscriptFormatter()

public lazy var elementFormattersMap: [Element: AttributeFormatter] = {
return [
Expand All @@ -55,7 +57,9 @@ class GenericElementConverter: ElementConverter {
.p: self.paragraphFormatter,
.pre: self.preFormatter,
.code: self.codeFormatter,
.li: self.liFormatter
.li: self.liFormatter,
.sup: self.superscriptFormatter,
.sub: self.subscriptFormatter,
]
}()

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import Foundation
import UIKit


/// Converts the subscript style information from string attributes and aggregates it into an
/// existing array of element nodes.
///
open class SubscriptStringAttributeConverter: StringAttributeConverter {

private let toggler = HTMLStyleToggler(defaultElement: .sub, cssAttributeMatcher: NeverCSSAttributeMatcher())

public func convert(
attributes: [NSAttributedString.Key: Any],
andAggregateWith elementNodes: [ElementNode]) -> [ElementNode] {

var elementNodes = elementNodes

// We add the representation right away, if it exists... as it could contain attributes beyond just this
// style. The enable and disable methods below can modify this as necessary.
//
if let representation = attributes[NSAttributedString.Key.subHtmlRepresentation] as? HTMLRepresentation,
case let .element(representationElement) = representation.kind {

elementNodes.append(representationElement.toElementNode())
}

if shouldEnable(for: attributes) {
return toggler.enable(in: elementNodes)
} else {
return toggler.disable(in: elementNodes)
}
}

// MARK: - Style Detection

func shouldEnable(for attributes: [NSAttributedString.Key : Any]) -> Bool {
return hasTraits(for: attributes)
}

func hasTraits(for attributes: [NSAttributedString.Key : Any]) -> Bool {
guard let baselineOffset = attributes[.baselineOffset] as? NSNumber else {
return false
}

return baselineOffset.intValue < 0;
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import Foundation
import UIKit


/// Converts the superscript style information from string attributes and aggregates it into an
/// existing array of element nodes.
///
open class SuperscriptStringAttributeConverter: StringAttributeConverter {

private let toggler = HTMLStyleToggler(defaultElement: .sup, cssAttributeMatcher: NeverCSSAttributeMatcher())

public func convert(
attributes: [NSAttributedString.Key: Any],
andAggregateWith elementNodes: [ElementNode]) -> [ElementNode] {

var elementNodes = elementNodes

// We add the representation right away, if it exists... as it could contain attributes beyond just this
// style. The enable and disable methods below can modify this as necessary.
//
if let representation = attributes[NSAttributedString.Key.supHtmlRepresentation] as? HTMLRepresentation,
case let .element(representationElement) = representation.kind {

elementNodes.append(representationElement.toElementNode())
}

if shouldEnable(for: attributes) {
return toggler.enable(in: elementNodes)
} else {
return toggler.disable(in: elementNodes)
}
}

// MARK: - Style Detection

func shouldEnable(for attributes: [NSAttributedString.Key : Any]) -> Bool {
return hasTraits(for: attributes)
}

func hasTraits(for attributes: [NSAttributedString.Key : Any]) -> Bool {
guard let baselineOffset = attributes[.baselineOffset] as? NSNumber else {
return false
}

return baselineOffset.intValue > 0;
}
}

8 changes: 8 additions & 0 deletions Aztec/Classes/Extensions/NSAttributedStringKey+Aztec.swift
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,12 @@ public extension NSAttributedString.Key {
/// Key used to store citeHTMLRepresentations, by our CiteFormatter.
///
static let citeHtmlRepresentation = NSAttributedString.Key("Cite.htmlRepresentation")

/// Key used to store Sup Tag Metadata, by our SupFormatter.
///
static let supHtmlRepresentation = NSAttributedString.Key("Sup.htmlRepresentation")

/// Key used to store Sub Tag Metadata, by our SupFormatter.
///
static let subHtmlRepresentation = NSAttributedString.Key("Sub.htmlRepresentation")
}
7 changes: 7 additions & 0 deletions Aztec/Classes/Extensions/UITextView+Delegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,11 @@ extension UITextView {
delegate?.textViewDidChange?(self)
NotificationCenter.default.post(name: UITextView.textDidChangeNotification, object: self)
}

final func shouldChangeText(in range: NSRange, with text:String) -> Bool {
guard let result = self.delegate?.textView?(self, shouldChangeTextIn: range, replacementText: text) else {
return true
}
return result
}
}
16 changes: 14 additions & 2 deletions Aztec/Classes/Formatters/Base/StandardAttributeFormatter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,15 @@ class StandardAttributeFormatter: AttributeFormatter {

let htmlRepresentationKey: NSAttributedString.Key

let needsToMatchValue: Bool

// MARK: - Init

init(attributeKey: NSAttributedString.Key, attributeValue: Any, htmlRepresentationKey: NSAttributedString.Key) {
init(attributeKey: NSAttributedString.Key, attributeValue: Any, htmlRepresentationKey: NSAttributedString.Key, needsToMatchValue: Bool = false) {
self.attributeKey = attributeKey
self.attributeValue = attributeValue
self.htmlRepresentationKey = htmlRepresentationKey
self.needsToMatchValue = needsToMatchValue
}

func applicationRange(for range: NSRange, in text: NSAttributedString) -> NSRange {
Expand All @@ -43,7 +46,16 @@ class StandardAttributeFormatter: AttributeFormatter {

func present(in attributes: [NSAttributedString.Key: Any]) -> Bool {
let enabled = attributes[attributeKey] != nil
return enabled
if (!needsToMatchValue) {
return enabled
}

if let value = attributes[attributeKey] as? NSObject,
let attributeValue = attributeValue as? NSObject {
return value.isEqual(attributeValue)
}

return false
}
}

32 changes: 32 additions & 0 deletions Aztec/Classes/Formatters/Implementations/SubscriptFormatter.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import UIKit

class SubscriptFormatter: StandardAttributeFormatter {

init() {
super.init(attributeKey: .baselineOffset,
attributeValue: NSNumber(-4),
htmlRepresentationKey: .subHtmlRepresentation)
}

override func apply(to attributes: [NSAttributedString.Key: Any], andStore representation: HTMLRepresentation?) -> [NSAttributedString.Key: Any] {
var resultingAttributes = super.apply(to: attributes, andStore: representation)
guard let currentFont = attributes[.font] as? UIFont else {
return resultingAttributes
}
let font = UIFont(descriptor: currentFont.fontDescriptor, size: currentFont.pointSize - 2)
resultingAttributes[.font] = font
return resultingAttributes
}

override func remove(from attributes: [NSAttributedString.Key: Any]) -> [NSAttributedString.Key: Any] {
var resultingAttributes = super.remove(from: attributes)

guard let currentFont = attributes[.font] as? UIFont else {
return resultingAttributes
}
let font = UIFont(descriptor: currentFont.fontDescriptor, size: currentFont.pointSize + 2)
resultingAttributes[.font] = font

return resultingAttributes
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import UIKit

class SuperscriptFormatter: StandardAttributeFormatter {

init() {
super.init(attributeKey: .baselineOffset,
attributeValue: NSNumber(4),
htmlRepresentationKey: .supHtmlRepresentation)
}

override func apply(to attributes: [NSAttributedString.Key: Any], andStore representation: HTMLRepresentation?) -> [NSAttributedString.Key: Any] {
var resultingAttributes = super.apply(to: attributes, andStore: representation)
guard let currentFont = attributes[.font] as? UIFont else {
return resultingAttributes
}
let font = UIFont(descriptor: currentFont.fontDescriptor, size: currentFont.pointSize - 2)
resultingAttributes[.font] = font
return resultingAttributes
}

override func remove(from attributes: [NSAttributedString.Key: Any]) -> [NSAttributedString.Key: Any] {
var resultingAttributes = super.remove(from: attributes)

guard let currentFont = attributes[.font] as? UIFont else {
return resultingAttributes
}
let font = UIFont(descriptor: currentFont.fontDescriptor, size: currentFont.pointSize + 2)
resultingAttributes[.font] = font

return resultingAttributes
}
}
4 changes: 3 additions & 1 deletion Aztec/Classes/Libxml2/DOM/Data/Element.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public struct Element: RawRepresentable, Hashable {
public static var mergeableBlockLevelElements = Set<Element>([.blockquote, .div, .figure, .figcaption, .h1, .h2, .h3, .h4, .h5, .h6, .hr, .li, .ol, .ul, .p, .pre])

/// List of style HTML elements that can be merged together when they are sibling to each other
public static var mergeableStyleElements = Set<Element>([.i, .em, .b, .strong, .strike, .u, .code, .cite, .a])
public static var mergeableStyleElements = Set<Element>([.i, .em, .b, .strong, .strike, .u, .code, .cite, .a, .sup, .sub])

/// List of block level elements that can be merged but only when they have a single children that is also mergeable
///
Expand Down Expand Up @@ -106,6 +106,8 @@ extension Element {
public static let span = Element("span")
public static let strike = Element("strike")
public static let strong = Element("strong")
public static let sub = Element("sub")
public static let sup = Element("sup")
public static let table = Element("table")
public static let tbody = Element("tbody")
public static let td = Element("td")
Expand Down
6 changes: 6 additions & 0 deletions Aztec/Classes/Libxml2/DOM/Logic/CSS/CSSAttributeMatcher.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,9 @@ import Foundation
public protocol CSSAttributeMatcher {
func check(_ cssAttribute: CSSAttribute) -> Bool
}

open class NeverCSSAttributeMatcher: CSSAttributeMatcher {
public func check(_ cssAttribute: CSSAttribute) -> Bool {
return false
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ class AttributedStringParser {
BoldStringAttributeConverter(),
ConditionalItalicStringAttributeConverter(),
UnderlineStringAttributeConverter(),
SuperscriptStringAttributeConverter(),
SubscriptStringAttributeConverter(),
]

// MARK: - Attachment Converters
Expand Down
Loading

0 comments on commit 26443eb

Please sign in to comment.