Jelajahi Sumber

1.更换 markdown 第三方
2.用户发送的消息,也改用attributedText

100Years 1 bulan lalu
induk
melakukan
a1fa5b053d
43 mengubah file dengan 1740 tambahan dan 49 penghapusan
  1. 372 0
      AIEmoji.xcodeproj/project.pbxproj
  2. 2 2
      AIEmoji/Business/AIChat/TSChatViewController/Models/TSTextLayoutSizeCalculator.swift
  3. 5 1
      AIEmoji/Business/AIChat/TSChatViewController/TSChatViewController/TSChatViewController+SendMsg.swift
  4. 4 34
      AIEmoji/Business/AIChat/TSChatViewController/ViewModel/TSAIChatVM.swift
  5. 94 0
      AIEmoji/Business/AIChat/TSChatViewController/ViewModel/TSMarkDownTool.swift
  6. 1 1
      AIEmoji/Business/AIChat/TSChatViewController/Views/TSTextMessageContentCell.swift
  7. 5 5
      AIEmoji/Common/NetworkManager/TSNetWork/TSNetworkManager.swift
  8. 22 0
      AIEmoji/Common/ThirdParty/MarkdownKit/Resources/iOS/Info.plist
  9. 19 0
      AIEmoji/Common/ThirdParty/MarkdownKit/Resources/iOS/MarkdownKit.h
  10. 24 0
      AIEmoji/Common/ThirdParty/MarkdownKit/Resources/macOS/Info.plist
  11. 19 0
      AIEmoji/Common/ThirdParty/MarkdownKit/Resources/macOS/MarkdownKit.h
  12. 18 0
      AIEmoji/Common/ThirdParty/MarkdownKit/Sources/AppKit/Elements/Code/MarkdownCode+AppKit.swift
  13. 16 0
      AIEmoji/Common/ThirdParty/MarkdownKit/Sources/AppKit/Elements/Header/MarkdownHeader+AppKit.swift
  14. 16 0
      AIEmoji/Common/ThirdParty/MarkdownKit/Sources/AppKit/Elements/Link/MarkdownLink+AppKit.swift
  15. 34 0
      AIEmoji/Common/ThirdParty/MarkdownKit/Sources/AppKit/Extensions/MarkdownFont+Traits.swift
  16. 17 0
      AIEmoji/Common/ThirdParty/MarkdownKit/Sources/AppKit/MarkdownParser+AppKit.swift
  17. 48 0
      AIEmoji/Common/ThirdParty/MarkdownKit/Sources/Common/Elements/Bold/MarkdownBold.swift
  18. 47 0
      AIEmoji/Common/ThirdParty/MarkdownKit/Sources/Common/Elements/Code/MarkdownCode.swift
  19. 34 0
      AIEmoji/Common/ThirdParty/MarkdownKit/Sources/Common/Elements/Escaping/MarkdownCodeEscaping.swift
  20. 32 0
      AIEmoji/Common/ThirdParty/MarkdownKit/Sources/Common/Elements/Escaping/MarkdownEscaping.swift
  21. 28 0
      AIEmoji/Common/ThirdParty/MarkdownKit/Sources/Common/Elements/Escaping/MarkdownUnescaping.swift
  22. 46 0
      AIEmoji/Common/ThirdParty/MarkdownKit/Sources/Common/Elements/Header/MarkdownHeader.swift
  23. 48 0
      AIEmoji/Common/ThirdParty/MarkdownKit/Sources/Common/Elements/Italic/MarkdownItalic.swift
  24. 22 0
      AIEmoji/Common/ThirdParty/MarkdownKit/Sources/Common/Elements/Link/MarkdownAutomaticLink.swift
  25. 107 0
      AIEmoji/Common/ThirdParty/MarkdownKit/Sources/Common/Elements/Link/MarkdownLink.swift
  26. 52 0
      AIEmoji/Common/ThirdParty/MarkdownKit/Sources/Common/Elements/List/MarkdownList.swift
  27. 42 0
      AIEmoji/Common/ThirdParty/MarkdownKit/Sources/Common/Elements/Quote/MarkdownQuote.swift
  28. 36 0
      AIEmoji/Common/ThirdParty/MarkdownKit/Sources/Common/Elements/Strikethrough/MarkdownStrikethrough.swift
  29. 41 0
      AIEmoji/Common/ThirdParty/MarkdownKit/Sources/Common/Extensions/String+UTF16.swift
  30. 186 0
      AIEmoji/Common/ThirdParty/MarkdownKit/Sources/Common/MarkdownParser.swift
  31. 35 0
      AIEmoji/Common/ThirdParty/MarkdownKit/Sources/Common/Protocols/MarkdownCommonElement.swift
  32. 39 0
      AIEmoji/Common/ThirdParty/MarkdownKit/Sources/Common/Protocols/MarkdownElement.swift
  33. 44 0
      AIEmoji/Common/ThirdParty/MarkdownKit/Sources/Common/Protocols/MarkdownLevelElement.swift
  34. 15 0
      AIEmoji/Common/ThirdParty/MarkdownKit/Sources/Common/Protocols/MarkdownLinkElement.swift
  35. 28 0
      AIEmoji/Common/ThirdParty/MarkdownKit/Sources/Common/Protocols/MarkdownStyle.swift
  36. 29 0
      AIEmoji/Common/ThirdParty/MarkdownKit/Sources/Common/Typealias.swift
  37. 19 0
      AIEmoji/Common/ThirdParty/MarkdownKit/Sources/UIKit/Elements/Code/MarkdownCode+UIKit.swift
  38. 17 0
      AIEmoji/Common/ThirdParty/MarkdownKit/Sources/UIKit/Elements/Header/MarkdownHeader+UIKit.swift
  39. 17 0
      AIEmoji/Common/ThirdParty/MarkdownKit/Sources/UIKit/Elements/Link/MarkdownLink+UIKit.swift
  40. 39 0
      AIEmoji/Common/ThirdParty/MarkdownKit/Sources/UIKit/Extensions/UIFont+Traits.swift
  41. 18 0
      AIEmoji/Common/ThirdParty/MarkdownKit/Sources/UIKit/MarkdownParser+UIKit.swift
  42. 2 1
      Podfile
  43. 1 5
      Podfile.lock

+ 372 - 0
AIEmoji.xcodeproj/project.pbxproj

@@ -38,6 +38,37 @@
 		A80E73E12D533E5800C64288 /* TSPurchaseVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = A80E73D82D533E5800C64288 /* TSPurchaseVC.swift */; };
 		A80E73E42D533EB000C64288 /* TSPurchaseManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = A80E73E22D533EB000C64288 /* TSPurchaseManager.swift */; };
 		A80E73E62D5348D000C64288 /* SettingPurchaseTopView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A80E73E52D5348CF00C64288 /* SettingPurchaseTopView.swift */; };
+		A80EDD032D6C282B003CD332 /* TSMarkDownTool.swift in Sources */ = {isa = PBXBuildFile; fileRef = A80EDD022D6C281E003CD332 /* TSMarkDownTool.swift */; };
+		A80EDD462D6C3F82003CD332 /* MarkdownEscaping.swift in Sources */ = {isa = PBXBuildFile; fileRef = A80EDD1B2D6C3F82003CD332 /* MarkdownEscaping.swift */; };
+		A80EDD472D6C3F82003CD332 /* MarkdownItalic.swift in Sources */ = {isa = PBXBuildFile; fileRef = A80EDD202D6C3F82003CD332 /* MarkdownItalic.swift */; };
+		A80EDD482D6C3F82003CD332 /* MarkdownBold.swift in Sources */ = {isa = PBXBuildFile; fileRef = A80EDD162D6C3F82003CD332 /* MarkdownBold.swift */; };
+		A80EDD4A2D6C3F82003CD332 /* MarkdownLevelElement.swift in Sources */ = {isa = PBXBuildFile; fileRef = A80EDD302D6C3F82003CD332 /* MarkdownLevelElement.swift */; };
+		A80EDD4B2D6C3F82003CD332 /* MarkdownParser+AppKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = A80EDD142D6C3F82003CD332 /* MarkdownParser+AppKit.swift */; };
+		A80EDD4C2D6C3F82003CD332 /* Typealias.swift in Sources */ = {isa = PBXBuildFile; fileRef = A80EDD352D6C3F82003CD332 /* Typealias.swift */; };
+		A80EDD4D2D6C3F82003CD332 /* MarkdownStrikethrough.swift in Sources */ = {isa = PBXBuildFile; fileRef = A80EDD292D6C3F82003CD332 /* MarkdownStrikethrough.swift */; };
+		A80EDD4E2D6C3F82003CD332 /* MarkdownUnescaping.swift in Sources */ = {isa = PBXBuildFile; fileRef = A80EDD1C2D6C3F82003CD332 /* MarkdownUnescaping.swift */; };
+		A80EDD4F2D6C3F82003CD332 /* MarkdownParser+UIKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = A80EDD402D6C3F82003CD332 /* MarkdownParser+UIKit.swift */; };
+		A80EDD502D6C3F82003CD332 /* MarkdownFont+Traits.swift in Sources */ = {isa = PBXBuildFile; fileRef = A80EDD122D6C3F82003CD332 /* MarkdownFont+Traits.swift */; };
+		A80EDD512D6C3F82003CD332 /* MarkdownCode.swift in Sources */ = {isa = PBXBuildFile; fileRef = A80EDD182D6C3F82003CD332 /* MarkdownCode.swift */; };
+		A80EDD522D6C3F82003CD332 /* MarkdownCode+AppKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = A80EDD0B2D6C3F82003CD332 /* MarkdownCode+AppKit.swift */; };
+		A80EDD532D6C3F82003CD332 /* MarkdownHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = A80EDD1E2D6C3F82003CD332 /* MarkdownHeader.swift */; };
+		A80EDD542D6C3F82003CD332 /* MarkdownQuote.swift in Sources */ = {isa = PBXBuildFile; fileRef = A80EDD272D6C3F82003CD332 /* MarkdownQuote.swift */; };
+		A80EDD552D6C3F82003CD332 /* UIFont+Traits.swift in Sources */ = {isa = PBXBuildFile; fileRef = A80EDD3E2D6C3F82003CD332 /* UIFont+Traits.swift */; };
+		A80EDD562D6C3F82003CD332 /* MarkdownHeader+AppKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = A80EDD0D2D6C3F82003CD332 /* MarkdownHeader+AppKit.swift */; };
+		A80EDD572D6C3F82003CD332 /* MarkdownCode+UIKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = A80EDD372D6C3F82003CD332 /* MarkdownCode+UIKit.swift */; };
+		A80EDD582D6C3F82003CD332 /* String+UTF16.swift in Sources */ = {isa = PBXBuildFile; fileRef = A80EDD2C2D6C3F82003CD332 /* String+UTF16.swift */; };
+		A80EDD592D6C3F82003CD332 /* MarkdownLink+UIKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = A80EDD3B2D6C3F82003CD332 /* MarkdownLink+UIKit.swift */; };
+		A80EDD5A2D6C3F82003CD332 /* MarkdownParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = A80EDD342D6C3F82003CD332 /* MarkdownParser.swift */; };
+		A80EDD5B2D6C3F82003CD332 /* MarkdownCommonElement.swift in Sources */ = {isa = PBXBuildFile; fileRef = A80EDD2E2D6C3F82003CD332 /* MarkdownCommonElement.swift */; };
+		A80EDD5C2D6C3F82003CD332 /* MarkdownList.swift in Sources */ = {isa = PBXBuildFile; fileRef = A80EDD252D6C3F82003CD332 /* MarkdownList.swift */; };
+		A80EDD5D2D6C3F82003CD332 /* MarkdownCodeEscaping.swift in Sources */ = {isa = PBXBuildFile; fileRef = A80EDD1A2D6C3F82003CD332 /* MarkdownCodeEscaping.swift */; };
+		A80EDD5E2D6C3F82003CD332 /* MarkdownLinkElement.swift in Sources */ = {isa = PBXBuildFile; fileRef = A80EDD312D6C3F82003CD332 /* MarkdownLinkElement.swift */; };
+		A80EDD5F2D6C3F82003CD332 /* MarkdownHeader+UIKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = A80EDD392D6C3F82003CD332 /* MarkdownHeader+UIKit.swift */; };
+		A80EDD602D6C3F82003CD332 /* MarkdownElement.swift in Sources */ = {isa = PBXBuildFile; fileRef = A80EDD2F2D6C3F82003CD332 /* MarkdownElement.swift */; };
+		A80EDD612D6C3F82003CD332 /* MarkdownLink+AppKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = A80EDD0F2D6C3F82003CD332 /* MarkdownLink+AppKit.swift */; };
+		A80EDD622D6C3F82003CD332 /* MarkdownLink.swift in Sources */ = {isa = PBXBuildFile; fileRef = A80EDD232D6C3F82003CD332 /* MarkdownLink.swift */; };
+		A80EDD632D6C3F82003CD332 /* MarkdownAutomaticLink.swift in Sources */ = {isa = PBXBuildFile; fileRef = A80EDD222D6C3F82003CD332 /* MarkdownAutomaticLink.swift */; };
+		A80EDD642D6C3F82003CD332 /* MarkdownStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = A80EDD322D6C3F82003CD332 /* MarkdownStyle.swift */; };
 		A85E478F2D67115A0018D62D /* TSTextGeneralPictureVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = A85E478E2D6711590018D62D /* TSTextGeneralPictureVC.swift */; };
 		A85E47922D6728A00018D62D /* TSTextGeneralPictureVM.swift in Sources */ = {isa = PBXBuildFile; fileRef = A85E47912D67289F0018D62D /* TSTextGeneralPictureVM.swift */; };
 		A85E47962D672ADA0018D62D /* TSTextPicGennerateVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = A85E47952D672AD90018D62D /* TSTextPicGennerateVC.swift */; };
@@ -169,6 +200,41 @@
 		A80E73D82D533E5800C64288 /* TSPurchaseVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSPurchaseVC.swift; sourceTree = "<group>"; };
 		A80E73E22D533EB000C64288 /* TSPurchaseManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSPurchaseManager.swift; sourceTree = "<group>"; };
 		A80E73E52D5348CF00C64288 /* SettingPurchaseTopView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingPurchaseTopView.swift; sourceTree = "<group>"; };
+		A80EDD022D6C281E003CD332 /* TSMarkDownTool.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSMarkDownTool.swift; sourceTree = "<group>"; };
+		A80EDD042D6C3F82003CD332 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
+		A80EDD052D6C3F82003CD332 /* MarkdownKit.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MarkdownKit.h; sourceTree = "<group>"; };
+		A80EDD072D6C3F82003CD332 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
+		A80EDD082D6C3F82003CD332 /* MarkdownKit.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MarkdownKit.h; sourceTree = "<group>"; };
+		A80EDD0B2D6C3F82003CD332 /* MarkdownCode+AppKit.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MarkdownCode+AppKit.swift"; sourceTree = "<group>"; };
+		A80EDD0D2D6C3F82003CD332 /* MarkdownHeader+AppKit.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MarkdownHeader+AppKit.swift"; sourceTree = "<group>"; };
+		A80EDD0F2D6C3F82003CD332 /* MarkdownLink+AppKit.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MarkdownLink+AppKit.swift"; sourceTree = "<group>"; };
+		A80EDD122D6C3F82003CD332 /* MarkdownFont+Traits.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MarkdownFont+Traits.swift"; sourceTree = "<group>"; };
+		A80EDD142D6C3F82003CD332 /* MarkdownParser+AppKit.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MarkdownParser+AppKit.swift"; sourceTree = "<group>"; };
+		A80EDD162D6C3F82003CD332 /* MarkdownBold.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MarkdownBold.swift; sourceTree = "<group>"; };
+		A80EDD182D6C3F82003CD332 /* MarkdownCode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MarkdownCode.swift; sourceTree = "<group>"; };
+		A80EDD1A2D6C3F82003CD332 /* MarkdownCodeEscaping.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MarkdownCodeEscaping.swift; sourceTree = "<group>"; };
+		A80EDD1B2D6C3F82003CD332 /* MarkdownEscaping.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MarkdownEscaping.swift; sourceTree = "<group>"; };
+		A80EDD1C2D6C3F82003CD332 /* MarkdownUnescaping.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MarkdownUnescaping.swift; sourceTree = "<group>"; };
+		A80EDD1E2D6C3F82003CD332 /* MarkdownHeader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MarkdownHeader.swift; sourceTree = "<group>"; };
+		A80EDD202D6C3F82003CD332 /* MarkdownItalic.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MarkdownItalic.swift; sourceTree = "<group>"; };
+		A80EDD222D6C3F82003CD332 /* MarkdownAutomaticLink.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MarkdownAutomaticLink.swift; sourceTree = "<group>"; };
+		A80EDD232D6C3F82003CD332 /* MarkdownLink.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MarkdownLink.swift; sourceTree = "<group>"; };
+		A80EDD252D6C3F82003CD332 /* MarkdownList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MarkdownList.swift; sourceTree = "<group>"; };
+		A80EDD272D6C3F82003CD332 /* MarkdownQuote.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MarkdownQuote.swift; sourceTree = "<group>"; };
+		A80EDD292D6C3F82003CD332 /* MarkdownStrikethrough.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MarkdownStrikethrough.swift; sourceTree = "<group>"; };
+		A80EDD2C2D6C3F82003CD332 /* String+UTF16.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+UTF16.swift"; sourceTree = "<group>"; };
+		A80EDD2E2D6C3F82003CD332 /* MarkdownCommonElement.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MarkdownCommonElement.swift; sourceTree = "<group>"; };
+		A80EDD2F2D6C3F82003CD332 /* MarkdownElement.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MarkdownElement.swift; sourceTree = "<group>"; };
+		A80EDD302D6C3F82003CD332 /* MarkdownLevelElement.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MarkdownLevelElement.swift; sourceTree = "<group>"; };
+		A80EDD312D6C3F82003CD332 /* MarkdownLinkElement.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MarkdownLinkElement.swift; sourceTree = "<group>"; };
+		A80EDD322D6C3F82003CD332 /* MarkdownStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MarkdownStyle.swift; sourceTree = "<group>"; };
+		A80EDD342D6C3F82003CD332 /* MarkdownParser.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MarkdownParser.swift; sourceTree = "<group>"; };
+		A80EDD352D6C3F82003CD332 /* Typealias.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Typealias.swift; sourceTree = "<group>"; };
+		A80EDD372D6C3F82003CD332 /* MarkdownCode+UIKit.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MarkdownCode+UIKit.swift"; sourceTree = "<group>"; };
+		A80EDD392D6C3F82003CD332 /* MarkdownHeader+UIKit.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MarkdownHeader+UIKit.swift"; sourceTree = "<group>"; };
+		A80EDD3B2D6C3F82003CD332 /* MarkdownLink+UIKit.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MarkdownLink+UIKit.swift"; sourceTree = "<group>"; };
+		A80EDD3E2D6C3F82003CD332 /* UIFont+Traits.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIFont+Traits.swift"; sourceTree = "<group>"; };
+		A80EDD402D6C3F82003CD332 /* MarkdownParser+UIKit.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MarkdownParser+UIKit.swift"; sourceTree = "<group>"; };
 		A85E478E2D6711590018D62D /* TSTextGeneralPictureVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSTextGeneralPictureVC.swift; sourceTree = "<group>"; };
 		A85E47912D67289F0018D62D /* TSTextGeneralPictureVM.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSTextGeneralPictureVM.swift; sourceTree = "<group>"; };
 		A85E47952D672AD90018D62D /* TSTextPicGennerateVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSTextPicGennerateVC.swift; sourceTree = "<group>"; };
@@ -453,6 +519,279 @@
 			path = AIChat;
 			sourceTree = "<group>";
 		};
+		A80EDD062D6C3F82003CD332 /* iOS */ = {
+			isa = PBXGroup;
+			children = (
+				A80EDD042D6C3F82003CD332 /* Info.plist */,
+				A80EDD052D6C3F82003CD332 /* MarkdownKit.h */,
+			);
+			path = iOS;
+			sourceTree = "<group>";
+		};
+		A80EDD092D6C3F82003CD332 /* macOS */ = {
+			isa = PBXGroup;
+			children = (
+				A80EDD072D6C3F82003CD332 /* Info.plist */,
+				A80EDD082D6C3F82003CD332 /* MarkdownKit.h */,
+			);
+			path = macOS;
+			sourceTree = "<group>";
+		};
+		A80EDD0A2D6C3F82003CD332 /* Resources */ = {
+			isa = PBXGroup;
+			children = (
+				A80EDD062D6C3F82003CD332 /* iOS */,
+				A80EDD092D6C3F82003CD332 /* macOS */,
+			);
+			path = Resources;
+			sourceTree = "<group>";
+		};
+		A80EDD0C2D6C3F82003CD332 /* Code */ = {
+			isa = PBXGroup;
+			children = (
+				A80EDD0B2D6C3F82003CD332 /* MarkdownCode+AppKit.swift */,
+			);
+			path = Code;
+			sourceTree = "<group>";
+		};
+		A80EDD0E2D6C3F82003CD332 /* Header */ = {
+			isa = PBXGroup;
+			children = (
+				A80EDD0D2D6C3F82003CD332 /* MarkdownHeader+AppKit.swift */,
+			);
+			path = Header;
+			sourceTree = "<group>";
+		};
+		A80EDD102D6C3F82003CD332 /* Link */ = {
+			isa = PBXGroup;
+			children = (
+				A80EDD0F2D6C3F82003CD332 /* MarkdownLink+AppKit.swift */,
+			);
+			path = Link;
+			sourceTree = "<group>";
+		};
+		A80EDD112D6C3F82003CD332 /* Elements */ = {
+			isa = PBXGroup;
+			children = (
+				A80EDD0C2D6C3F82003CD332 /* Code */,
+				A80EDD0E2D6C3F82003CD332 /* Header */,
+				A80EDD102D6C3F82003CD332 /* Link */,
+			);
+			path = Elements;
+			sourceTree = "<group>";
+		};
+		A80EDD132D6C3F82003CD332 /* Extensions */ = {
+			isa = PBXGroup;
+			children = (
+				A80EDD122D6C3F82003CD332 /* MarkdownFont+Traits.swift */,
+			);
+			path = Extensions;
+			sourceTree = "<group>";
+		};
+		A80EDD152D6C3F82003CD332 /* AppKit */ = {
+			isa = PBXGroup;
+			children = (
+				A80EDD112D6C3F82003CD332 /* Elements */,
+				A80EDD132D6C3F82003CD332 /* Extensions */,
+				A80EDD142D6C3F82003CD332 /* MarkdownParser+AppKit.swift */,
+			);
+			path = AppKit;
+			sourceTree = "<group>";
+		};
+		A80EDD172D6C3F82003CD332 /* Bold */ = {
+			isa = PBXGroup;
+			children = (
+				A80EDD162D6C3F82003CD332 /* MarkdownBold.swift */,
+			);
+			path = Bold;
+			sourceTree = "<group>";
+		};
+		A80EDD192D6C3F82003CD332 /* Code */ = {
+			isa = PBXGroup;
+			children = (
+				A80EDD182D6C3F82003CD332 /* MarkdownCode.swift */,
+			);
+			path = Code;
+			sourceTree = "<group>";
+		};
+		A80EDD1D2D6C3F82003CD332 /* Escaping */ = {
+			isa = PBXGroup;
+			children = (
+				A80EDD1A2D6C3F82003CD332 /* MarkdownCodeEscaping.swift */,
+				A80EDD1B2D6C3F82003CD332 /* MarkdownEscaping.swift */,
+				A80EDD1C2D6C3F82003CD332 /* MarkdownUnescaping.swift */,
+			);
+			path = Escaping;
+			sourceTree = "<group>";
+		};
+		A80EDD1F2D6C3F82003CD332 /* Header */ = {
+			isa = PBXGroup;
+			children = (
+				A80EDD1E2D6C3F82003CD332 /* MarkdownHeader.swift */,
+			);
+			path = Header;
+			sourceTree = "<group>";
+		};
+		A80EDD212D6C3F82003CD332 /* Italic */ = {
+			isa = PBXGroup;
+			children = (
+				A80EDD202D6C3F82003CD332 /* MarkdownItalic.swift */,
+			);
+			path = Italic;
+			sourceTree = "<group>";
+		};
+		A80EDD242D6C3F82003CD332 /* Link */ = {
+			isa = PBXGroup;
+			children = (
+				A80EDD222D6C3F82003CD332 /* MarkdownAutomaticLink.swift */,
+				A80EDD232D6C3F82003CD332 /* MarkdownLink.swift */,
+			);
+			path = Link;
+			sourceTree = "<group>";
+		};
+		A80EDD262D6C3F82003CD332 /* List */ = {
+			isa = PBXGroup;
+			children = (
+				A80EDD252D6C3F82003CD332 /* MarkdownList.swift */,
+			);
+			path = List;
+			sourceTree = "<group>";
+		};
+		A80EDD282D6C3F82003CD332 /* Quote */ = {
+			isa = PBXGroup;
+			children = (
+				A80EDD272D6C3F82003CD332 /* MarkdownQuote.swift */,
+			);
+			path = Quote;
+			sourceTree = "<group>";
+		};
+		A80EDD2A2D6C3F82003CD332 /* Strikethrough */ = {
+			isa = PBXGroup;
+			children = (
+				A80EDD292D6C3F82003CD332 /* MarkdownStrikethrough.swift */,
+			);
+			path = Strikethrough;
+			sourceTree = "<group>";
+		};
+		A80EDD2B2D6C3F82003CD332 /* Elements */ = {
+			isa = PBXGroup;
+			children = (
+				A80EDD172D6C3F82003CD332 /* Bold */,
+				A80EDD192D6C3F82003CD332 /* Code */,
+				A80EDD1D2D6C3F82003CD332 /* Escaping */,
+				A80EDD1F2D6C3F82003CD332 /* Header */,
+				A80EDD212D6C3F82003CD332 /* Italic */,
+				A80EDD242D6C3F82003CD332 /* Link */,
+				A80EDD262D6C3F82003CD332 /* List */,
+				A80EDD282D6C3F82003CD332 /* Quote */,
+				A80EDD2A2D6C3F82003CD332 /* Strikethrough */,
+			);
+			path = Elements;
+			sourceTree = "<group>";
+		};
+		A80EDD2D2D6C3F82003CD332 /* Extensions */ = {
+			isa = PBXGroup;
+			children = (
+				A80EDD2C2D6C3F82003CD332 /* String+UTF16.swift */,
+			);
+			path = Extensions;
+			sourceTree = "<group>";
+		};
+		A80EDD332D6C3F82003CD332 /* Protocols */ = {
+			isa = PBXGroup;
+			children = (
+				A80EDD2E2D6C3F82003CD332 /* MarkdownCommonElement.swift */,
+				A80EDD2F2D6C3F82003CD332 /* MarkdownElement.swift */,
+				A80EDD302D6C3F82003CD332 /* MarkdownLevelElement.swift */,
+				A80EDD312D6C3F82003CD332 /* MarkdownLinkElement.swift */,
+				A80EDD322D6C3F82003CD332 /* MarkdownStyle.swift */,
+			);
+			path = Protocols;
+			sourceTree = "<group>";
+		};
+		A80EDD362D6C3F82003CD332 /* Common */ = {
+			isa = PBXGroup;
+			children = (
+				A80EDD2B2D6C3F82003CD332 /* Elements */,
+				A80EDD2D2D6C3F82003CD332 /* Extensions */,
+				A80EDD332D6C3F82003CD332 /* Protocols */,
+				A80EDD342D6C3F82003CD332 /* MarkdownParser.swift */,
+				A80EDD352D6C3F82003CD332 /* Typealias.swift */,
+			);
+			path = Common;
+			sourceTree = "<group>";
+		};
+		A80EDD382D6C3F82003CD332 /* Code */ = {
+			isa = PBXGroup;
+			children = (
+				A80EDD372D6C3F82003CD332 /* MarkdownCode+UIKit.swift */,
+			);
+			path = Code;
+			sourceTree = "<group>";
+		};
+		A80EDD3A2D6C3F82003CD332 /* Header */ = {
+			isa = PBXGroup;
+			children = (
+				A80EDD392D6C3F82003CD332 /* MarkdownHeader+UIKit.swift */,
+			);
+			path = Header;
+			sourceTree = "<group>";
+		};
+		A80EDD3C2D6C3F82003CD332 /* Link */ = {
+			isa = PBXGroup;
+			children = (
+				A80EDD3B2D6C3F82003CD332 /* MarkdownLink+UIKit.swift */,
+			);
+			path = Link;
+			sourceTree = "<group>";
+		};
+		A80EDD3D2D6C3F82003CD332 /* Elements */ = {
+			isa = PBXGroup;
+			children = (
+				A80EDD382D6C3F82003CD332 /* Code */,
+				A80EDD3A2D6C3F82003CD332 /* Header */,
+				A80EDD3C2D6C3F82003CD332 /* Link */,
+			);
+			path = Elements;
+			sourceTree = "<group>";
+		};
+		A80EDD3F2D6C3F82003CD332 /* Extensions */ = {
+			isa = PBXGroup;
+			children = (
+				A80EDD3E2D6C3F82003CD332 /* UIFont+Traits.swift */,
+			);
+			path = Extensions;
+			sourceTree = "<group>";
+		};
+		A80EDD412D6C3F82003CD332 /* UIKit */ = {
+			isa = PBXGroup;
+			children = (
+				A80EDD3D2D6C3F82003CD332 /* Elements */,
+				A80EDD3F2D6C3F82003CD332 /* Extensions */,
+				A80EDD402D6C3F82003CD332 /* MarkdownParser+UIKit.swift */,
+			);
+			path = UIKit;
+			sourceTree = "<group>";
+		};
+		A80EDD422D6C3F82003CD332 /* Sources */ = {
+			isa = PBXGroup;
+			children = (
+				A80EDD152D6C3F82003CD332 /* AppKit */,
+				A80EDD362D6C3F82003CD332 /* Common */,
+				A80EDD412D6C3F82003CD332 /* UIKit */,
+			);
+			path = Sources;
+			sourceTree = "<group>";
+		};
+		A80EDD452D6C3F82003CD332 /* MarkdownKit */ = {
+			isa = PBXGroup;
+			children = (
+				A80EDD0A2D6C3F82003CD332 /* Resources */,
+				A80EDD422D6C3F82003CD332 /* Sources */,
+			);
+			path = MarkdownKit;
+			sourceTree = "<group>";
+		};
 		A85E478D2D670DF10018D62D /* TSTextGeneralPictureVC */ = {
 			isa = PBXGroup;
 			children = (
@@ -555,6 +894,7 @@
 		A89EA6782D59D238000EB181 /* ViewModel */ = {
 			isa = PBXGroup;
 			children = (
+				A80EDD022D6C281E003CD332 /* TSMarkDownTool.swift */,
 				A89EA6792D59D248000EB181 /* TSAIChatVM.swift */,
 			);
 			path = ViewModel;
@@ -695,6 +1035,7 @@
 		A8F774C62D38EA8C00AA6E93 /* ThirdParty */ = {
 			isa = PBXGroup;
 			children = (
+				A80EDD452D6C3F82003CD332 /* MarkdownKit */,
 			);
 			path = ThirdParty;
 			sourceTree = "<group>";
@@ -1185,6 +1526,36 @@
 				A80E73E42D533EB000C64288 /* TSPurchaseManager.swift in Sources */,
 				A8F7762F2D3A765400AA6E93 /* TSGenmojiViewModel.swift in Sources */,
 				A8F7751B2D38EC9800AA6E93 /* TSGenmojiVC.swift in Sources */,
+				A80EDD462D6C3F82003CD332 /* MarkdownEscaping.swift in Sources */,
+				A80EDD472D6C3F82003CD332 /* MarkdownItalic.swift in Sources */,
+				A80EDD482D6C3F82003CD332 /* MarkdownBold.swift in Sources */,
+				A80EDD4A2D6C3F82003CD332 /* MarkdownLevelElement.swift in Sources */,
+				A80EDD4B2D6C3F82003CD332 /* MarkdownParser+AppKit.swift in Sources */,
+				A80EDD4C2D6C3F82003CD332 /* Typealias.swift in Sources */,
+				A80EDD4D2D6C3F82003CD332 /* MarkdownStrikethrough.swift in Sources */,
+				A80EDD4E2D6C3F82003CD332 /* MarkdownUnescaping.swift in Sources */,
+				A80EDD4F2D6C3F82003CD332 /* MarkdownParser+UIKit.swift in Sources */,
+				A80EDD502D6C3F82003CD332 /* MarkdownFont+Traits.swift in Sources */,
+				A80EDD512D6C3F82003CD332 /* MarkdownCode.swift in Sources */,
+				A80EDD522D6C3F82003CD332 /* MarkdownCode+AppKit.swift in Sources */,
+				A80EDD532D6C3F82003CD332 /* MarkdownHeader.swift in Sources */,
+				A80EDD542D6C3F82003CD332 /* MarkdownQuote.swift in Sources */,
+				A80EDD552D6C3F82003CD332 /* UIFont+Traits.swift in Sources */,
+				A80EDD562D6C3F82003CD332 /* MarkdownHeader+AppKit.swift in Sources */,
+				A80EDD572D6C3F82003CD332 /* MarkdownCode+UIKit.swift in Sources */,
+				A80EDD582D6C3F82003CD332 /* String+UTF16.swift in Sources */,
+				A80EDD592D6C3F82003CD332 /* MarkdownLink+UIKit.swift in Sources */,
+				A80EDD5A2D6C3F82003CD332 /* MarkdownParser.swift in Sources */,
+				A80EDD5B2D6C3F82003CD332 /* MarkdownCommonElement.swift in Sources */,
+				A80EDD5C2D6C3F82003CD332 /* MarkdownList.swift in Sources */,
+				A80EDD5D2D6C3F82003CD332 /* MarkdownCodeEscaping.swift in Sources */,
+				A80EDD5E2D6C3F82003CD332 /* MarkdownLinkElement.swift in Sources */,
+				A80EDD5F2D6C3F82003CD332 /* MarkdownHeader+UIKit.swift in Sources */,
+				A80EDD602D6C3F82003CD332 /* MarkdownElement.swift in Sources */,
+				A80EDD612D6C3F82003CD332 /* MarkdownLink+AppKit.swift in Sources */,
+				A80EDD622D6C3F82003CD332 /* MarkdownLink.swift in Sources */,
+				A80EDD632D6C3F82003CD332 /* MarkdownAutomaticLink.swift in Sources */,
+				A80EDD642D6C3F82003CD332 /* MarkdownStyle.swift in Sources */,
 				A89EA6CF2D6430F3000EB181 /* TSChatViewController+Keyboard.swift in Sources */,
 				A8F7754E2D39E59100AA6E93 /* TSGenmojiModel.swift in Sources */,
 				A8F776452D3DE8A800AA6E93 /* TSSmallIconBrowseVC.swift in Sources */,
@@ -1217,6 +1588,7 @@
 				A8F776212D3A3F0200AA6E93 /* TSEmojisChildVC.swift in Sources */,
 				A80E72222D3F3A9200C64288 /* DiyStickerElement.swift in Sources */,
 				A85E47C32D6964A50018D62D /* TSMSGAIDefaultHeaderView.swift in Sources */,
+				A80EDD032D6C282B003CD332 /* TSMarkDownTool.swift in Sources */,
 				A8F775002D38EA8C00AA6E93 /* WindowHelper.swift in Sources */,
 				A8F7764B2D3E008500AA6E93 /* TSEmojisChildColViewModel.swift in Sources */,
 				A80E72772D41EFF900C64288 /* TSEmojisTutorialsVC.swift in Sources */,

+ 2 - 2
AIEmoji/Business/AIChat/TSChatViewController/Models/TSTextLayoutSizeCalculator.swift

@@ -70,8 +70,8 @@ class TSTextLayoutSizeCalculator: TSLayoutSizeCalculator {
         //用 label 计算更加精准
         var size = UILabel.getAttributedTextSize(attributedText: attributedText, maxWidth: maxWidth)
 //        debugPrint("attributedText size=\(size)")
-//        var size = attributedText.size(consideringWidth: maxWidth)
-//        size.width = size.width + 10
+        
+        var size1 = attributedText.size(consideringWidth: maxWidth)
 
         let minSize = Self.cellMessagelabelMinSize
         if size.width < minSize.width {

+ 5 - 1
AIEmoji/Business/AIChat/TSChatViewController/TSChatViewController/TSChatViewController+SendMsg.swift

@@ -26,7 +26,9 @@ extension TSChatViewController {
         let user = viewModel.kUserSender
         for component in data {
             if let str = component as? String {
-                let message = TSChatMessage(text: str, user: user, messageId: UUID().uuidString, date: Date())
+//                let message = TSChatMessage(text: str, user: user, messageId: UUID().uuidString, date: Date())
+                let attri = kMDSendAttributedString(text: str)
+                let message = TSChatMessage(attributedText: attri, user: user, messageId: UUID().uuidString, date: Date())
                 insertMessage(message)
                 //保存这条消息到本地数据库
                 //发送消息后,进行AI 对话生成
@@ -40,6 +42,8 @@ extension TSChatViewController {
         switch message.kind {
         case .text(let message):
             messageString = message
+        case .attributedText(let message):
+            messageString = message.string
         default:
             break
         }

+ 4 - 34
AIEmoji/Business/AIChat/TSChatViewController/ViewModel/TSAIChatVM.swift

@@ -45,21 +45,7 @@ extension TSAIChatVM {
             "sessionId": dbAIChatList.sessionId,
             "message": message
         ]
-        
-//        AiMDString = ""
-//        streamRequest = TSNetworkShared.postStream(urlType: .chat,parameters: parameters) {[weak self] string in
-//            guard let self = self else { return }
-//            AiMDString = AiMDString + string
-//            streamHandler(string)
-//        } completion: { result in
-//            switch result {
-//            case .success(let data):
-//                completion(data,nil)
-//            case .failure(let error):
-//                completion(nil,error)
-//            }
-//        }
-        
+
         AiMDString = ""
         _ = TSNetworkShared.postStream(urlType: .chat,parameters: parameters) {[weak self] string in
             guard let self = self else { return }
@@ -97,7 +83,9 @@ extension TSAIChatVM {
         if uiStyle == .history {
             return self.dbAIChatList.getMessageList()
         }else {
-            let aiString = "I can tackle your questions, my skillset includes, but is not limited to:\n\n📧 Composing high-quality emails\n\n🇺🇸 Facilitating language learning\n\n📑 Assisting in your studies\n\n💡Brainstorming ideas\n\nand much more!"
+//            let aiString = "I can tackle your questions, my skillset includes, but is not limited to:\n\n📧 Composing high-quality emails\n\n🇺🇸 Facilitating language learning\n\n📑 Assisting in your studies\n\n💡Brainstorming ideas\n\nand much more!"
+            
+            let aiString = "I can tackle your questions, my skillset includes, but is not limited to:\n📧 Composing high-quality emails\n🇺🇸 Facilitating language learning\n📑 Assisting in your studies\n💡Brainstorming ideas\nand much more!"
             let msg = TSChatMessage(kind: .attributedText(kMDAttributedString(text: aiString)), user: kAIUser, messageId: "", date: Date())
 
             let model = TSChatMessageUIBaseModel()
@@ -115,23 +103,5 @@ extension TSAIChatVM {
             self.dbAIChatList.updateMessages(msgModels: msgModels)
             //保存服务器
         }
-        
-        
     }
 }
-
-
-
-import SwiftyMarkdown
-private var md: SwiftyMarkdown = {
-    let md = SwiftyMarkdown(string: "")
-    md.setFontColorForAllStyles(with: .white)
-    md.code.color = .red
-    
-    return md
-}()
-
-//字符串转成 markdown NSAttributedString
-func kMDAttributedString(text:String) -> NSAttributedString{
-    return md.attributedString(from: text)
-}

+ 94 - 0
AIEmoji/Business/AIChat/TSChatViewController/ViewModel/TSMarkDownTool.swift

@@ -0,0 +1,94 @@
+//
+//  TSMarkDownTool.swift
+//  AIEmoji
+//
+//  Created by 100Years on 2025/2/23.
+//
+
+let kLineSpacing = 8.0
+let KFont = UIFont.font(size: 16)
+let kSendColor = "#111111".uiColor
+
+
+let paragraphStyle:NSMutableParagraphStyle = {
+    let paragraphStyle = NSMutableParagraphStyle()
+    paragraphStyle.lineSpacing = kLineSpacing
+    return paragraphStyle
+}()
+
+///发送的Attributed
+func kMDSendAttributedString(text:String) -> NSAttributedString{
+    let attributes : [NSAttributedString.Key : Any] = [
+        .font: KFont,
+        .foregroundColor:kSendColor,
+        .paragraphStyle:paragraphStyle
+    ]
+    
+    let attributedString = NSMutableAttributedString(string: text, attributes: attributes)
+//    attributedString.addAttribute(.paragraphStyle, value: paragraphStyle, range: NSRange(location: 0, length: attributedString.length))
+    return attributedString
+}
+
+
+var md: MarkdownParser = {
+    let parser = MarkdownParser(font: KFont,color: .white)
+    parser.enabledElements = .disabledAutomaticLink
+    let code = TSCustomMarkdownCode()
+    code.textBackgroundColor = .clear
+    code.color = .white.withAlphaComponent(0.8)
+    code.textHighlightColor = .white.withAlphaComponent(0.8)
+    parser.replaceDefaultElement(parser.code, with: code)
+    return parser
+}()
+
+//ai 对话的 字符串转成 markdown NSAttributedString
+func kMDAttributedString(text:String) -> NSAttributedString{
+    let attributedString = NSMutableAttributedString(attributedString: md.parse(text))
+    attributedString.addAttribute(.paragraphStyle, value: paragraphStyle, range: NSRange(location: 0, length: attributedString.length))
+    return attributedString
+}
+
+open class TSCustomMarkdownCode: MarkdownCode {
+  fileprivate static let regex = "(^|\\s?)(\\`{1,3})(.+?)(\\2)"
+  open override var regex: String {
+    return TSCustomMarkdownCode.regex
+  }
+}
+
+
+
+//import SwiftyMarkdown
+//private var md: SwiftyMarkdown = {
+//
+//    var characterRules = SwiftyMarkdown.characterRules
+//    characterRules.append(
+//        CharacterRule(
+//            primaryTag: CharacterRuleTag(tag: "```", type: .repeating),
+//            otherTags: [],
+//            styles: [1 : CharacterStyle.code],
+//            shouldCancelRemainingRules: true,
+//            balancedTags: true
+//        )
+//    )
+//    SwiftyMarkdown.characterRules = characterRules
+//
+//    let md = SwiftyMarkdown(string: "")
+//    md.setFontColorForAllStyles(with: .white)
+////    md.code.color = .red
+//
+////    let characterRules = [
+////        CharacterRule(primaryTag: CharacterRuleTag(tag: "```", type: .repeating), otherTags: [], styles: [1 : CharacterStyle.code], shouldCancelRemainingRules: true, balancedTags: true)
+////    ]
+////    let processor = SwiftyTokeniser( with : characterRules)
+////    let string = "The elf will speak now: %Here is my elf speaking%"
+////    let tokens = processor.process(string)
+//
+//
+//
+//    return md
+//}()
+//
+////字符串转成 markdown NSAttributedString
+//func kMDAttributedString(text:String) -> NSAttributedString{
+//    return md.attributedString(from: text)
+//}

+ 1 - 1
AIEmoji/Business/AIChat/TSChatViewController/Views/TSTextMessageContentCell.swift

@@ -8,7 +8,7 @@
 
 import MessageKit
 import UIKit
-import SwiftyMarkdown
+
 class TSTextMessageContentCell: TSMessageContentCell {
     var messageLabel: UILabel = {
         let label = UILabel.createLabel(font: .font(size: 16),numberOfLines: 0)

+ 5 - 5
AIEmoji/Common/NetworkManager/TSNetWork/TSNetworkManager.swift

@@ -49,7 +49,7 @@ class TSNetworkManager {
             let jsonData = try JSONSerialization.data(withJSONObject: parameters, options: [])
             urlRequest.httpBody = jsonData
         } catch {
-            print("Failed to encode parameters: \(error)")
+            dePrint("Failed to encode parameters: \(error)")
             completion(.failure(error))
             return nil
         }
@@ -61,18 +61,18 @@ class TSNetworkManager {
             case .stream(let result):
                 switch result {
                 case .success(let string):
-                    debugPrint("Stream Received string: \(string)")
+                    dePrint("Stream Received string: \(string)")
                     streamHandler(string)
                 case .failure(let error):
-                    debugPrint("Stream error: \(error)")
+                    dePrint("Stream error: \(error)")
                     completion(.failure(error))
                 }
             case .complete(let cpl):
                 if let error = cpl.error {
-                    debugPrint("Stream Request failed with error: \(error)")
+                    dePrint("Stream Request failed with error: \(error)")
                     completion(.failure(error))
                 } else {
-                    debugPrint("Stream success")
+                    dePrint("Stream success")
                     completion(.success("Stream success"))
                 }
             }

+ 22 - 0
AIEmoji/Common/ThirdParty/MarkdownKit/Resources/iOS/Info.plist

@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>$(DEVELOPMENT_LANGUAGE)</string>
+	<key>CFBundleExecutable</key>
+	<string>$(EXECUTABLE_NAME)</string>
+	<key>CFBundleIdentifier</key>
+	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundleName</key>
+	<string>$(PRODUCT_NAME)</string>
+	<key>CFBundlePackageType</key>
+	<string>FMWK</string>
+	<key>CFBundleShortVersionString</key>
+	<string>$(MARKETING_VERSION)</string>
+	<key>CFBundleVersion</key>
+	<string>$(CURRENT_PROJECT_VERSION)</string>
+</dict>
+</plist>

+ 19 - 0
AIEmoji/Common/ThirdParty/MarkdownKit/Resources/iOS/MarkdownKit.h

@@ -0,0 +1,19 @@
+//
+//  MarkdownKit.h
+//  MarkdownKit
+//
+//  Created by Bruno Oliveira on 16/01/2019.
+//  Copyright © 2019 Ivan Bruel. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+//! Project version number for MarkdownKit.
+FOUNDATION_EXPORT double MarkdownKitVersionNumber;
+
+//! Project version string for MarkdownKit.
+FOUNDATION_EXPORT const unsigned char MarkdownKitVersionString[];
+
+// In this header, you should import all the public headers of your framework using statements like #import <MarkdownKit/PublicHeader.h>
+
+

+ 24 - 0
AIEmoji/Common/ThirdParty/MarkdownKit/Resources/macOS/Info.plist

@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>$(DEVELOPMENT_LANGUAGE)</string>
+	<key>CFBundleExecutable</key>
+	<string>$(EXECUTABLE_NAME)</string>
+	<key>CFBundleIdentifier</key>
+	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundleName</key>
+	<string>$(PRODUCT_NAME)</string>
+	<key>CFBundlePackageType</key>
+	<string>FMWK</string>
+	<key>CFBundleShortVersionString</key>
+	<string>$(MARKETING_VERSION)</string>
+	<key>CFBundleVersion</key>
+	<string>$(CURRENT_PROJECT_VERSION)</string>
+	<key>NSHumanReadableCopyright</key>
+	<string>Copyright © 2019 Ivan Bruel. All rights reserved.</string>
+</dict>
+</plist>

+ 19 - 0
AIEmoji/Common/ThirdParty/MarkdownKit/Resources/macOS/MarkdownKit.h

@@ -0,0 +1,19 @@
+//
+//  MarkdownKit_mac.h
+//  MarkdownKit-mac
+//
+//  Created by Bruno Oliveira on 31/01/2019.
+//  Copyright © 2019 Ivan Bruel. All rights reserved.
+//
+
+#import <Cocoa/Cocoa.h>
+
+//! Project version number for MarkdownKit_mac.
+FOUNDATION_EXPORT double MarkdownKit_macVersionNumber;
+
+//! Project version string for MarkdownKit_mac.
+FOUNDATION_EXPORT const unsigned char MarkdownKit_macVersionString[];
+
+// In this header, you should import all the public headers of your framework using statements like #import <MarkdownKit_mac/PublicHeader.h>
+
+

+ 18 - 0
AIEmoji/Common/ThirdParty/MarkdownKit/Sources/AppKit/Elements/Code/MarkdownCode+AppKit.swift

@@ -0,0 +1,18 @@
+//
+//  MarkdownCode+UIKit.swift
+//  MarkdownKit
+//
+//  Created by Bruno Oliveira on 31/01/2019.
+//  Copyright © 2019 Ivan Bruel. All rights reserved.
+//
+#if canImport(AppKit) && !targetEnvironment(macCatalyst)
+
+import AppKit
+
+public extension MarkdownCode {
+  static let defaultHighlightColor = MarkdownColor(red: 0.90, green: 0.20, blue: 0.40, alpha: 1.0)
+  static let defaultBackgroundColor = MarkdownColor(red: 0.85, green: 0.85, blue: 0.85, alpha: 1.0)
+  static let defaultFont = MarkdownFont(name: "Menlo-Regular", size: 16)
+}
+
+#endif

+ 16 - 0
AIEmoji/Common/ThirdParty/MarkdownKit/Sources/AppKit/Elements/Header/MarkdownHeader+AppKit.swift

@@ -0,0 +1,16 @@
+//
+//  MarkdownHeader+UIKit.swift
+//  MarkdownKit
+//
+//  Created by Bruno Oliveira on 31/01/2019.
+//  Copyright © 2019 Ivan Bruel. All rights reserved.
+//
+#if canImport(AppKit) && !targetEnvironment(macCatalyst)
+
+import AppKit
+
+public extension MarkdownHeader {
+  static let defaultFont = NSFont.boldSystemFont(ofSize: NSFont.systemFontSize)
+}
+
+#endif

+ 16 - 0
AIEmoji/Common/ThirdParty/MarkdownKit/Sources/AppKit/Elements/Link/MarkdownLink+AppKit.swift

@@ -0,0 +1,16 @@
+//
+//  MarkdownLink+UIKit.swift
+//  MarkdownKit
+//
+//  Created by Bruno Oliveira on 31/01/2019.
+//  Copyright © 2019 Ivan Bruel. All rights reserved.
+//
+#if canImport(AppKit) && !targetEnvironment(macCatalyst)
+
+import AppKit
+
+public extension MarkdownLink {
+  static let defaultColor = NSColor.blue
+}
+
+#endif

+ 34 - 0
AIEmoji/Common/ThirdParty/MarkdownKit/Sources/AppKit/Extensions/MarkdownFont+Traits.swift

@@ -0,0 +1,34 @@
+//
+//  NSFont+Traits.swift
+//  MarkdownKit
+//
+//  Created by Bruno Oliveira on 31/01/2019.
+//  Copyright © 2019 Ivan Bruel. All rights reserved.
+//
+#if canImport(AppKit) && !targetEnvironment(macCatalyst)
+
+import AppKit
+
+public extension MarkdownFont {
+  func italic() -> MarkdownFont {
+    return NSFontManager().convert(self, toHaveTrait: NSFontTraitMask.italicFontMask)
+  }
+  
+  func bold() -> MarkdownFont {
+    return NSFontManager().convert(self, toHaveTrait: NSFontTraitMask.boldFontMask)
+  }
+
+  func isItalic() -> Bool {
+    return NSFontManager().traits(of: self).contains(.italicFontMask)
+  }
+
+  func isBold() -> Bool {
+    return NSFontManager().traits(of: self).contains(.boldFontMask)
+  }
+  
+  func withSize(_ size: CGFloat) -> NSFont {
+    return NSFontManager().convert(self, toSize: size)
+  }
+}
+
+#endif

+ 17 - 0
AIEmoji/Common/ThirdParty/MarkdownKit/Sources/AppKit/MarkdownParser+AppKit.swift

@@ -0,0 +1,17 @@
+//
+//  MarkdownParser+UIKit.swift
+//  MarkdownKit
+//
+//  Created by Bruno Oliveira on 31/01/2019.
+//  Copyright © 2019 Ivan Bruel. All rights reserved.
+//
+#if canImport(AppKit) && !targetEnvironment(macCatalyst)
+
+import AppKit
+
+public extension MarkdownParser {
+  static let defaultFont = NSFont.systemFont(ofSize: NSFont.smallSystemFontSize)
+  static let defaultColor = NSColor.black
+}
+
+#endif

+ 48 - 0
AIEmoji/Common/ThirdParty/MarkdownKit/Sources/Common/Elements/Bold/MarkdownBold.swift

@@ -0,0 +1,48 @@
+//
+//  MarkdownBold.swift
+//  Pods
+//
+//  Created by Ivan Bruel on 18/07/16.
+//
+//
+import Foundation
+
+open class MarkdownBold: MarkdownCommonElement {
+  
+  fileprivate static let regex = "(.?|^)(\\*\\*|__)(?=\\S)(.+?)(?<=\\S)(\\2)"
+
+  open var font: MarkdownFont?
+  open var color: MarkdownColor?
+
+  open var regex: String {
+    return MarkdownBold.regex
+  }
+  
+  public init(font: MarkdownFont? = nil, color: MarkdownColor? = nil) {
+    self.font = font
+    self.color = color
+  }
+
+  public func match(_ match: NSTextCheckingResult, attributedString: NSMutableAttributedString) {
+    attributedString.deleteCharacters(in: match.range(at: 4))
+
+    var attributes = self.attributes
+
+    attributedString.enumerateAttribute(.font, in: match.range(at: 3)) { value, range, _ in
+      guard let currentFont = value as? MarkdownFont else { return }
+      if let customFont = self.font {
+          attributes[.font] = currentFont.isItalic() ? customFont.bold().italic() : customFont.bold()
+      } else {
+        attributedString.addAttribute(
+          NSAttributedString.Key.font,
+          value: currentFont.bold(),
+          range: range
+        )
+      }
+    }
+
+    attributedString.addAttributes(attributes, range: match.range(at: 3))
+
+    attributedString.deleteCharacters(in: match.range(at: 2))
+  }
+}

+ 47 - 0
AIEmoji/Common/ThirdParty/MarkdownKit/Sources/Common/Elements/Code/MarkdownCode.swift

@@ -0,0 +1,47 @@
+//
+//  MarkdownCode.swift
+//  Pods
+//
+//  Created by Ivan Bruel on 18/07/16.
+//
+//
+import Foundation
+
+open class MarkdownCode: MarkdownCommonElement {
+
+  fileprivate static let regex = "(.?|^)(\\`{1,3})(.+?)(\\2)"
+  
+  open var font: MarkdownFont?
+  open var color: MarkdownColor?
+  open var textHighlightColor: MarkdownColor?
+  open var textBackgroundColor: MarkdownColor?
+
+  open var regex: String {
+    return MarkdownCode.regex
+  }
+
+  public init(font: MarkdownFont? = MarkdownCode.defaultFont,
+              color: MarkdownColor? = nil,
+              textHighlightColor: MarkdownColor? = MarkdownCode.defaultHighlightColor,
+              textBackgroundColor: MarkdownColor? = MarkdownCode.defaultBackgroundColor) {
+    self.font = font
+    self.color = color
+    self.textHighlightColor = textHighlightColor
+    self.textBackgroundColor = textBackgroundColor
+  }
+
+  open func addAttributes(_ attributedString: NSMutableAttributedString, range: NSRange) {
+    let matchString: String = attributedString.attributedSubstring(from: range).string
+    guard let unescapedString = matchString.unescapeUTF16() else { return }
+    attributedString.replaceCharacters(in: range, with: unescapedString)
+    
+    var codeAttributes = attributes
+    
+    textHighlightColor.flatMap { codeAttributes[NSAttributedString.Key.foregroundColor] = $0 }
+    textBackgroundColor.flatMap { codeAttributes[NSAttributedString.Key.backgroundColor] = $0 }
+    font.flatMap { codeAttributes[NSAttributedString.Key.font] = $0 }
+    
+    let updatedRange = (attributedString.string as NSString).range(of: unescapedString)
+    attributedString.addAttributes(codeAttributes, range: NSRange(location: range.location, length: updatedRange.length))
+  }
+}

+ 34 - 0
AIEmoji/Common/ThirdParty/MarkdownKit/Sources/Common/Elements/Escaping/MarkdownCodeEscaping.swift

@@ -0,0 +1,34 @@
+//
+//  MarkdownCodeEscaping.swift
+//  Pods
+//
+//  Created by Ivan Bruel on 18/07/16.
+//
+//
+import Foundation
+
+open class MarkdownCodeEscaping: MarkdownElement {
+
+  fileprivate static let regex = "(\\s+|^)(?<!\\\\)(?:\\\\\\\\)*+(\\`+)(.+?)(\\2)"
+
+  open var regex: String {
+    return MarkdownCodeEscaping.regex
+  }
+
+  open func regularExpression() throws -> NSRegularExpression {
+    return try NSRegularExpression(pattern: regex, options: .dotMatchesLineSeparators)
+  }
+
+  open func match(_ match: NSTextCheckingResult, attributedString: NSMutableAttributedString) {
+    let range = match.range(at: 3)
+    // escaping all characters
+    let matchString = attributedString.attributedSubstring(from: range).string
+    let escapedString = [UInt16](matchString.utf16)
+      .map { (value: UInt16) -> String in String(format: "%04x", value) }
+      .reduce("") { (string: String, character: String) -> String in
+        return "\(string)\(character)"
+    }
+    attributedString.replaceCharacters(in: range, with: escapedString)
+  }
+
+}

+ 32 - 0
AIEmoji/Common/ThirdParty/MarkdownKit/Sources/Common/Elements/Escaping/MarkdownEscaping.swift

@@ -0,0 +1,32 @@
+//
+//  MarkdownEscaping.swift
+//  Pods
+//
+//  Created by Ivan Bruel on 18/07/16.
+//
+//
+import Foundation
+
+open class MarkdownEscaping: MarkdownElement {
+
+  fileprivate static let regex = "\\\\."
+
+  open var regex: String {
+    return MarkdownEscaping.regex
+  }
+
+  open func regularExpression() throws -> NSRegularExpression {
+    return try NSRegularExpression(pattern: regex, options: .dotMatchesLineSeparators)
+  }
+
+  open func match(_ match: NSTextCheckingResult, attributedString: NSMutableAttributedString) {
+    let range = NSRange(location: match.range.location + 1, length: 1)
+    // escape one character
+    let matchString = attributedString.attributedSubstring(from: range).string
+    if let escapedString = [UInt16](matchString.utf16).first
+      .flatMap({ (value: UInt16) -> String in String(format: "%04x", value) }) {
+      attributedString.replaceCharacters(in: range, with: escapedString)
+    }
+  }
+
+}

+ 28 - 0
AIEmoji/Common/ThirdParty/MarkdownKit/Sources/Common/Elements/Escaping/MarkdownUnescaping.swift

@@ -0,0 +1,28 @@
+//
+//  MarkdownUnescaping.swift
+//  Pods
+//
+//  Created by Ivan Bruel on 18/07/16.
+//
+//
+import Foundation
+
+open class MarkdownUnescaping: MarkdownElement {
+  
+  fileprivate static let regex = "\\\\[0-9a-z]{4}"
+  
+  open var regex: String {
+    return MarkdownUnescaping.regex
+  }
+  
+  open func regularExpression() throws -> NSRegularExpression {
+    return try NSRegularExpression(pattern: regex, options: .dotMatchesLineSeparators)
+  }
+  
+  open func match(_ match: NSTextCheckingResult, attributedString: NSMutableAttributedString) {
+    let range = NSRange(location: match.range.location + 1, length: 4)
+    let matchString = attributedString.attributedSubstring(from: range).string
+    guard let unescapedString = matchString.unescapeUTF16() else { return }
+    attributedString.replaceCharacters(in: match.range, with: unescapedString)
+  }
+}

+ 46 - 0
AIEmoji/Common/ThirdParty/MarkdownKit/Sources/Common/Elements/Header/MarkdownHeader.swift

@@ -0,0 +1,46 @@
+//
+//  MarkdownHeader.swift
+//  Pods
+//
+//  Created by Ivan Bruel on 18/07/16.
+//
+//
+import Foundation
+import CoreGraphics
+
+open class MarkdownHeader: MarkdownLevelElement {
+
+  fileprivate static let regex = "^(#{1,%@})\\s*(.+)$"
+
+  open var maxLevel: Int
+  open var font: MarkdownFont?
+  open var color: MarkdownColor?
+  open var fontIncrease: Int
+
+  open var regex: String {
+    let level: String = maxLevel > 0 ? "\(maxLevel)" : ""
+    return String(format: MarkdownHeader.regex, level)
+  }
+
+  public init(font: MarkdownFont? = MarkdownHeader.defaultFont,
+              maxLevel: Int = 0, fontIncrease: Int = 2, color: MarkdownColor? = nil) {
+    self.maxLevel = maxLevel
+    self.font = font
+    self.color = color
+    self.fontIncrease = fontIncrease
+  }
+
+  open func formatText(_ attributedString: NSMutableAttributedString, range: NSRange, level: Int) {
+      attributedString.deleteCharacters(in: range)
+  }
+
+    open func attributesForLevel(_ level: Int) -> [NSAttributedString.Key: AnyObject] {
+    var attributes = self.attributes
+    if let font = font {
+        let headerFontSize: CGFloat = font.pointSize + 4 + (-1 * CGFloat(level) * CGFloat(fontIncrease))
+      
+      attributes[NSAttributedString.Key.font] = font.withSize(headerFontSize).bold()
+    }
+    return attributes
+  }
+}

+ 48 - 0
AIEmoji/Common/ThirdParty/MarkdownKit/Sources/Common/Elements/Italic/MarkdownItalic.swift

@@ -0,0 +1,48 @@
+//
+//  MarkdownItalic.swift
+//  Pods
+//
+//  Created by Ivan Bruel on 18/07/16.
+//
+//
+import Foundation
+
+open class MarkdownItalic: MarkdownCommonElement {
+  
+  fileprivate static let regex = "(.?|^)(\\*|_)(?=\\S)(.+?)(?<![\\*_\\s])(\\2)"
+
+  open var font: MarkdownFont?
+  open var color: MarkdownColor?
+  
+  open var regex: String {
+    return MarkdownItalic.regex
+  }
+  
+  public init(font: MarkdownFont? = nil, color: MarkdownColor? = nil) {
+    self.font = font
+    self.color = color
+  }
+    
+  public func match(_ match: NSTextCheckingResult, attributedString: NSMutableAttributedString) {
+    attributedString.deleteCharacters(in: match.range(at: 4))
+
+    var attributes = self.attributes
+
+    attributedString.enumerateAttribute(.font, in: match.range(at: 3)) { value, range, _ in
+      guard let currentFont = value as? MarkdownFont else { return }
+      if let customFont = self.font {
+        attributes[.font] = currentFont.isBold() ? customFont.bold().italic() : customFont.italic()
+      } else {
+        attributedString.addAttribute(
+          NSAttributedString.Key.font,
+          value: currentFont.italic(),
+          range: range
+        )
+      }
+    }
+
+    attributedString.addAttributes(attributes, range: match.range(at: 3))
+
+    attributedString.deleteCharacters(in: match.range(at: 2))
+  }
+}

+ 22 - 0
AIEmoji/Common/ThirdParty/MarkdownKit/Sources/Common/Elements/Link/MarkdownAutomaticLink.swift

@@ -0,0 +1,22 @@
+//
+//  MarkdownAutomaticLink.swift
+//  Pods
+//
+//  Created by Ivan Bruel on 19/07/16.
+//
+//
+import Foundation
+
+open class MarkdownAutomaticLink: MarkdownLink {
+  
+ open override func regularExpression() throws -> NSRegularExpression {
+    return try NSDataDetector(types: NSTextCheckingResult.CheckingType.link.rawValue)
+  }
+  
+  open override func match(_ match: NSTextCheckingResult,
+                             attributedString: NSMutableAttributedString) {
+    let linkURLString = attributedString.attributedSubstring(from: match.range).string
+    formatText(attributedString, range: match.range, link: linkURLString)
+    addAttributes(attributedString, range: match.range)
+  }
+}

+ 107 - 0
AIEmoji/Common/ThirdParty/MarkdownKit/Sources/Common/Elements/Link/MarkdownLink.swift

@@ -0,0 +1,107 @@
+//
+//  MarkdownLink.swift
+//  Pods
+//
+//  Created by Ivan Bruel on 18/07/16.
+//
+//
+import Foundation
+
+open class MarkdownLink: MarkdownLinkElement {
+
+  fileprivate static let regex = "(\\[[^\\]]+)(\\]\\([^\\s]+)?\\)"
+
+  private let schemeRegex = "([a-z]{2,20}):\\/\\/"
+
+  open var font: MarkdownFont?
+  open var color: MarkdownColor?
+  open var defaultScheme: String?
+
+  open var regex: String {
+    return MarkdownLink.regex
+  }
+
+  open func regularExpression() throws -> NSRegularExpression {
+    return try NSRegularExpression(pattern: regex, options: .dotMatchesLineSeparators)
+  }
+
+  public init(font: MarkdownFont? = nil, color: MarkdownColor? = MarkdownLink.defaultColor) {
+    self.font = font
+    self.color = color
+  }
+
+  open func formatText(_ attributedString: NSMutableAttributedString, range: NSRange, link: String) {
+    let regex = try? NSRegularExpression(pattern: schemeRegex, options: .caseInsensitive)
+    let hasScheme = regex?.firstMatch(
+        in: link,
+        options: .anchored,
+        range: NSRange(0..<link.count)
+    ) != nil
+
+    let fullLink = hasScheme ? link : "\(defaultScheme ?? "https://")\(link)"
+
+    guard let encodedLink = fullLink.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed) else { return }
+    guard let url = URL(string: fullLink) ?? URL(string: encodedLink) else { return }
+    attributedString.addAttribute(NSAttributedString.Key.link, value: url, range: range)
+  }
+
+  open func match(_ match: NSTextCheckingResult, attributedString: NSMutableAttributedString) {
+    // Remove opening bracket
+    attributedString.deleteCharacters(in: NSRange(location: match.range(at: 1).location, length: 1))
+
+    // Remove closing bracket
+    attributedString.deleteCharacters(in: NSRange(location: match.range(at: 2).location - 1, length: 1))
+
+    let urlStart = match.range(at: 2).location
+
+    let string = NSString(string: attributedString.string)
+    var urlString = String(string.substring(with: NSRange(urlStart..<match.range(at: 2).upperBound - 2 )))
+
+    // Balance opening and closing parantheses inside the url
+    var numberOfOpeningParantheses = 0
+    var numberOfClosingParantheses = 0
+    for (index, character) in urlString.enumerated() {
+        switch character {
+        case "(": numberOfOpeningParantheses += 1
+        case ")": numberOfClosingParantheses += 1
+        default: continue
+        }
+        if numberOfClosingParantheses > numberOfOpeningParantheses {
+            urlString = NSString(string: urlString).substring(with: NSRange(0..<index))
+            break
+        }
+    }
+
+    // Remove opening parantheses
+    attributedString.deleteCharacters(in: NSRange(location: match.range(at: 2).location, length: 1))
+
+    // Remove closing parantheses
+    let trailingMarkdownRange = NSRange(location: match.range(at: 2).location - 1, length: urlString.count + 1)
+    attributedString.deleteCharacters(in: trailingMarkdownRange)
+
+    let formatRange = NSRange(match.range(at: 1).location..<match.range(at: 2).location - 1)
+
+    // Add attributes while preserving current attributes
+
+    let currentAttributes = attributedString.attributes(
+      at: formatRange.location,
+      longestEffectiveRange: nil,
+      in: formatRange
+    )
+
+    addAttributes(attributedString, range: formatRange)
+    formatText(attributedString, range: formatRange, link: urlString)
+
+    if let font = currentAttributes[.font] as? MarkdownFont {
+      attributedString.addAttribute(
+        NSAttributedString.Key.font,
+        value: font,
+        range: formatRange
+      )
+    }
+  }
+
+  open func addAttributes(_ attributedString: NSMutableAttributedString, range: NSRange) {
+    attributedString.addAttributes(attributes, range: range)
+  }
+}

+ 52 - 0
AIEmoji/Common/ThirdParty/MarkdownKit/Sources/Common/Elements/List/MarkdownList.swift

@@ -0,0 +1,52 @@
+//
+//  MarkdownList.swift
+//  Pods
+//
+//  Created by Ivan Bruel on 18/07/16.
+//
+//
+import Foundation
+
+open class MarkdownList: MarkdownLevelElement {
+
+  fileprivate static let regex = "^( {0,%@}[\\*\\+\\-])\\s+(.+)$"
+
+  open var maxLevel: Int
+  open var font: MarkdownFont?
+  open var color: MarkdownColor?
+  open var separator: String
+  open var indicator: String
+
+  open var regex: String {
+    let level: String = maxLevel > 0 ? "\(maxLevel)" : ""
+    return String(format: MarkdownList.regex, level)
+  }
+
+  public init(font: MarkdownFont? = nil, maxLevel: Int = 6, indicator: String = "•",
+              separator: String = "  ", color: MarkdownColor? = nil) {
+    self.maxLevel = maxLevel
+    self.indicator = indicator
+    self.separator = separator
+    self.font = font
+    self.color = color
+  }
+
+  open func formatText(_ attributedString: NSMutableAttributedString, range: NSRange, level: Int) {
+    let levelIndicatorList = [1: "\(indicator)  ", 2: "\(indicator)  ", 3: "◦  ", 4: "◦  ", 5: "▪︎  ", 6: "▪︎  "]
+    let levelIndicatorOffsetList = [1: "", 2: "", 3: "  ", 4: "  ", 5: "    ", 6: "    "]
+    guard let indicatorIcon = levelIndicatorList[level],
+      let offset = levelIndicatorOffsetList[level] else { return }
+    let indicator = "\(offset)\(indicatorIcon)"
+    attributedString.replaceCharacters(in: range, with: indicator)
+    let updatedRange = NSRange(location: range.location, length: indicator.utf16.count)
+    attributedString.addAttributes([.paragraphStyle : defaultParagraphStyle()], range: updatedRange)
+  }
+
+  private func defaultParagraphStyle() -> NSMutableParagraphStyle {
+    let paragraphStyle = NSMutableParagraphStyle()
+    paragraphStyle.firstLineHeadIndent = 0
+    paragraphStyle.headIndent = 16
+    paragraphStyle.paragraphSpacing = 4
+    return paragraphStyle
+  }
+}

+ 42 - 0
AIEmoji/Common/ThirdParty/MarkdownKit/Sources/Common/Elements/Quote/MarkdownQuote.swift

@@ -0,0 +1,42 @@
+//
+//  MarkdownQuote.swift
+//  Pods
+//
+//  Created by Ivan Bruel on 18/07/16.
+//
+//
+import Foundation
+
+open class MarkdownQuote: MarkdownLevelElement {
+
+  fileprivate static let regex = "^(\\>{1,%@})\\s*(.+)$"
+
+  open var maxLevel: Int
+  open var font: MarkdownFont?
+  open var color: MarkdownColor?
+  open var separator: String
+  open var indicator: String
+
+  open var regex: String {
+    let level: String = maxLevel > 0 ? "\(maxLevel)" : ""
+    return String(format: MarkdownQuote.regex, level)
+  }
+
+  public init(font: MarkdownFont? = nil, maxLevel: Int = 0, indicator: String = ">",
+              separator: String = "  ", color: MarkdownColor? = nil) {
+    self.maxLevel = maxLevel
+    self.indicator = indicator
+    self.separator = separator
+    self.font = font
+    self.color = color
+  }
+
+
+  open func formatText(_ attributedString: NSMutableAttributedString, range: NSRange, level: Int) {
+    var string = (0..<level).reduce("") { (string: String, _: Int) -> String in
+      return "\(string)\(separator)"
+    }
+    string = "\(string)\(indicator) "
+    attributedString.replaceCharacters(in: range, with: string)
+  }
+}

+ 36 - 0
AIEmoji/Common/ThirdParty/MarkdownKit/Sources/Common/Elements/Strikethrough/MarkdownStrikethrough.swift

@@ -0,0 +1,36 @@
+//
+//  MarkdownStrikethrough.swift
+//  Pods
+//
+//  Created by _ on _.
+//
+//
+import Foundation
+
+open class MarkdownStrikethrough: MarkdownCommonElement {
+  fileprivate static let regex = "(.?|^)(\\~\\~)(?=\\S)(.+?)(?<=\\S)(\\2)"
+  
+  open var font: MarkdownFont?
+  open var color: MarkdownColor?
+  
+  open var regex: String {
+    return MarkdownStrikethrough.regex
+  }
+  
+  public init(font: MarkdownFont? = nil, color: MarkdownColor? = nil) {
+    self.font = font
+    self.color = color
+  }
+
+  public func match(_ match: NSTextCheckingResult, attributedString: NSMutableAttributedString) {
+    attributedString.deleteCharacters(in: match.range(at: 4))
+
+    attributedString.addAttribute(
+      NSAttributedString.Key.strikethroughStyle,
+      value: NSNumber.init(value: NSUnderlineStyle.single.rawValue),
+      range: match.range(at: 3)
+    )
+
+    attributedString.deleteCharacters(in: match.range(at: 2))
+  }
+}

+ 41 - 0
AIEmoji/Common/ThirdParty/MarkdownKit/Sources/Common/Extensions/String+UTF16.swift

@@ -0,0 +1,41 @@
+//
+//  String+UTF16.swift
+//  Pods
+//
+//  Created by Ivan Bruel on 19/07/16.
+//
+//
+import Foundation
+
+extension String {
+  
+  /// Converts each character to its UTF16 form in hexadecimal value (e.g. "H" -> "0048")
+  func escapeUTF16() -> String {
+    return Array(utf16).map {
+      String(format: "%04x", $0)
+    }.reduce("") {
+      return $0 + $1
+    }
+  }
+  
+  /// Converts each 4 digit characters to its String form  (e.g. "0048" -> "H")
+  func unescapeUTF16() -> String? {
+    
+    //This is an hot fix for the crash when a regular string is passed here.
+     guard count % 4 == 0 else {
+      return self
+    }
+ 
+    var utf16Array = [UInt16]()
+    stride(from: 0, to: count, by: 4).forEach {
+      let startIndex = index(self.startIndex, offsetBy: $0)
+      let endIndex = index(self.startIndex, offsetBy: $0 + 4)
+      let hex4 = String(self[startIndex..<endIndex])
+      if let utf16 = UInt16(hex4, radix: 16) {
+        utf16Array.append(utf16)
+      }
+    }
+    
+    return String(utf16CodeUnits: utf16Array, count: utf16Array.count)
+  }
+}

+ 186 - 0
AIEmoji/Common/ThirdParty/MarkdownKit/Sources/Common/MarkdownParser.swift

@@ -0,0 +1,186 @@
+//
+//  MarkdownParser.swift
+//  Pods
+//
+//  Created by Ivan Bruel on 18/07/16.
+//
+//
+import Foundation
+
+open class MarkdownParser {
+  public struct EnabledElements: OptionSet {
+    public let rawValue: Int
+
+    public init(rawValue: Int) {
+      self.rawValue = rawValue
+    }
+    public static let automaticLink = EnabledElements(rawValue: 1)
+    public static let header        = EnabledElements(rawValue: 1 << 1)
+    public static let list          = EnabledElements(rawValue: 1 << 2)
+    public static let quote         = EnabledElements(rawValue: 1 << 3)
+    public static let link          = EnabledElements(rawValue: 1 << 4)
+    public static let bold          = EnabledElements(rawValue: 1 << 5)
+    public static let italic        = EnabledElements(rawValue: 1 << 6)
+    public static let code          = EnabledElements(rawValue: 1 << 7)
+    public static let strikethrough = EnabledElements(rawValue: 1 << 8)
+
+    public static let disabledAutomaticLink: EnabledElements = [
+      .header,
+      .list,
+      .quote,
+      .link,
+      .bold,
+      .italic,
+      .code,
+      .strikethrough,
+      ]
+
+    public static let all: EnabledElements = [
+      .disabledAutomaticLink,
+      .automaticLink,
+      ]
+  }
+
+  // MARK: Element Arrays
+  fileprivate var escapingElements: [MarkdownElement]
+  fileprivate var defaultElements: [MarkdownElement] = []
+  fileprivate var unescapingElements: [MarkdownElement]
+  
+  open var customElements: [MarkdownElement]
+  
+  // MARK: Basic Elements
+  public let header: MarkdownHeader
+  public let list: MarkdownList
+  public let quote: MarkdownQuote
+  public let link: MarkdownLink
+  public let automaticLink: MarkdownAutomaticLink
+  public let bold: MarkdownBold
+  public let italic: MarkdownItalic
+  public let code: MarkdownCode
+  public let strikethrough: MarkdownStrikethrough
+
+  // MARK: Escaping Elements
+  fileprivate var codeEscaping = MarkdownCodeEscaping()
+  fileprivate var escaping = MarkdownEscaping()
+  fileprivate var unescaping = MarkdownUnescaping()
+  
+  // MARK: Configuration
+  /// Enables individual Markdown elements and automatic link detection
+  open var enabledElements: EnabledElements {
+    didSet {
+      updateDefaultElements()
+      updateEscapingElements()
+      updateUnescapingElements()
+    }
+  }
+
+  public let font: MarkdownFont
+  public let color: MarkdownColor
+  
+  // MARK: Legacy Initializer
+  @available(*, deprecated, renamed: "init", message: "This constructor will be removed soon, please use the new options constructor")
+  public convenience init(automaticLinkDetectionEnabled: Bool,
+                          font: MarkdownFont = MarkdownParser.defaultFont,
+                          customElements: [MarkdownElement] = []) {
+    let enabledElements: EnabledElements = automaticLinkDetectionEnabled ? .all : .disabledAutomaticLink
+    self.init(font: font, enabledElements: enabledElements, customElements: customElements)
+  }
+  
+  // MARK: Initializer
+  public init(font: MarkdownFont = MarkdownParser.defaultFont,
+              color: MarkdownColor = MarkdownParser.defaultColor,
+              enabledElements: EnabledElements = .all,
+              customElements: [MarkdownElement] = []) {
+    self.font = font
+    self.color = color
+    
+    self.header = MarkdownHeader()
+    self.list = MarkdownList()
+    self.quote = MarkdownQuote()
+    self.link = MarkdownLink()
+    self.automaticLink = MarkdownAutomaticLink()
+    self.bold = MarkdownBold()
+    self.italic = MarkdownItalic()
+    self.code = MarkdownCode()
+    self.strikethrough = MarkdownStrikethrough()
+
+    self.escapingElements = [codeEscaping, escaping]
+    self.unescapingElements = [code, unescaping]
+    self.customElements = customElements
+    self.enabledElements = enabledElements
+    updateDefaultElements()
+    updateEscapingElements()
+    updateUnescapingElements()
+  }
+
+  // MARK: Element Extensibility
+  public func replaceDefaultElement(_ defaultElement: MarkdownElement, with element: MarkdownElement) {
+    guard let index = defaultElements.firstIndex(where: { $0 === defaultElement }) else { return }
+	defaultElements[index] = element
+  }
+
+  open func addCustomElement(_ element: MarkdownElement) {
+    customElements.append(element)
+  }
+  
+  open func removeCustomElement(_ element: MarkdownElement) {
+    if let index = customElements.firstIndex(where: { $0 === element }) {
+      customElements.remove(at: index)
+    }
+  }
+  
+  // MARK: Parsing
+  open func parse(_ markdown: String) -> NSAttributedString {
+    return parse(NSAttributedString(string: markdown))
+  }
+  
+  open func parse(_ markdown: NSAttributedString) -> NSAttributedString {
+    let attributedString = NSMutableAttributedString(attributedString: markdown)
+    attributedString.addAttribute(.font, value: font,
+                                  range: NSRange(location: 0, length: attributedString.length))
+    attributedString.addAttribute(.foregroundColor, value: color,
+                                  range: NSRange(location: 0, length: attributedString.length))
+    var elements: [MarkdownElement] = escapingElements
+    elements.append(contentsOf: defaultElements)
+    elements.append(contentsOf: customElements)
+    elements.append(contentsOf: unescapingElements)
+    elements.forEach { element in
+      element.parse(attributedString)
+    }
+    return attributedString
+  }
+
+  fileprivate func updateDefaultElements() {
+    // Parsing order matters!
+    let pairs: [(EnabledElements, MarkdownElement)] = [
+      (.header, header),
+      (.list, list),
+      (.quote, quote),
+      (.bold, bold),
+      (.italic, italic),
+      (.strikethrough, strikethrough),
+      (.link, link),
+      (.automaticLink, automaticLink),
+      (.code, code),
+    ]
+    defaultElements = pairs.compactMap { enabled, element in
+        enabledElements.contains(enabled) ? element : nil
+    }
+  }
+
+  fileprivate func updateEscapingElements() {
+    if enabledElements.contains(.code) {
+      escapingElements = [codeEscaping, escaping]
+    } else {
+      escapingElements = [escaping]
+    }
+  }
+
+  fileprivate func updateUnescapingElements() {
+    if enabledElements.contains(.code) {
+      unescapingElements = [code, unescaping]
+    } else {
+      unescapingElements = [unescaping]
+    }
+  }
+}

+ 35 - 0
AIEmoji/Common/ThirdParty/MarkdownKit/Sources/Common/Protocols/MarkdownCommonElement.swift

@@ -0,0 +1,35 @@
+//
+//  MarkdownElement.swift
+//  Pods
+//
+//  Created by Ivan Bruel on 18/07/16.
+//
+//
+/// MarkdownCommentElement represent the default Markdown elements which only manipulate content 
+/// visually, (e.g. Bold or Italic)
+import Foundation
+
+public protocol MarkdownCommonElement: MarkdownElement, MarkdownStyle {
+  
+  func addAttributes(_ attributedString: NSMutableAttributedString, range: NSRange)
+}
+
+public extension MarkdownCommonElement {
+  
+  func regularExpression() throws -> NSRegularExpression {
+    return try NSRegularExpression(pattern: regex, options: [])
+  }
+  
+  func addAttributes(_ attributedString: NSMutableAttributedString, range: NSRange) {
+    attributedString.addAttributes(attributes, range: range)
+  }
+  
+  func match(_ match: NSTextCheckingResult, attributedString: NSMutableAttributedString) {
+    // deleting trailing markdown
+    attributedString.deleteCharacters(in: match.range(at: 4))
+    // formatting string (may alter the length)
+    addAttributes(attributedString, range: match.range(at: 3))
+    // deleting leading markdown
+    attributedString.deleteCharacters(in: match.range(at: 2))
+  }
+}

+ 39 - 0
AIEmoji/Common/ThirdParty/MarkdownKit/Sources/Common/Protocols/MarkdownElement.swift

@@ -0,0 +1,39 @@
+//
+//  MarkdownElement.swift
+//  Pods
+//
+//  Created by Ivan Bruel on 18/07/16.
+//
+//
+import Foundation
+
+/// The base protocol for all Markdown Elements, it handles parsing through regex.
+public protocol MarkdownElement: AnyObject {
+  
+  var regex: String { get }
+  
+  func regularExpression() throws -> NSRegularExpression
+  func parse(_ attributedString: NSMutableAttributedString)
+  func match(_ match: NSTextCheckingResult, attributedString: NSMutableAttributedString)
+}
+
+public extension MarkdownElement {
+  
+  func parse(_ attributedString: NSMutableAttributedString) {
+      var location = 0
+      do {
+        let regex = try regularExpression()
+        while let regexMatch =
+          regex.firstMatch(in: attributedString.string,
+                                               options: .withoutAnchoringBounds,
+                                               range: NSRange(location: location,
+                                                length: attributedString.length - location))
+        {
+          let oldLength = attributedString.length
+          match(regexMatch, attributedString: attributedString)
+          let newLength = attributedString.length
+          location = regexMatch.range.location + regexMatch.range.length + newLength - oldLength
+        }
+      } catch { }
+  }
+}

+ 44 - 0
AIEmoji/Common/ThirdParty/MarkdownKit/Sources/Common/Protocols/MarkdownLevelElement.swift

@@ -0,0 +1,44 @@
+//
+//  MarkdownLevelElement.swift
+//  Pods
+//
+//  Created by Ivan Bruel on 18/07/16.
+//
+//
+import Foundation
+
+/// MarkdownLevelElement serves the purpose of handling Elements which may have more than one 
+/// representation (e.g. Headers or Lists)
+public protocol MarkdownLevelElement: MarkdownElement, MarkdownStyle {
+  
+  /// The maximum level of elements we should parse (e.g. limit the headers to 6 #s)
+  var maxLevel: Int { get }
+  
+  func formatText(_ attributedString: NSMutableAttributedString, range: NSRange, level: Int)
+  func addAttributes(_ attributedString: NSMutableAttributedString, range: NSRange, level: Int)
+    func attributesForLevel(_ level: Int) -> [NSAttributedString.Key: AnyObject]
+}
+
+public extension MarkdownLevelElement {
+  
+  
+  func regularExpression() throws -> NSRegularExpression {
+    return try NSRegularExpression(pattern: regex, options: .anchorsMatchLines)
+  }
+  
+  func addAttributes(_ attributedString: NSMutableAttributedString, range: NSRange, level: Int) {
+    attributedString.addAttributes(attributesForLevel(level - 1), range: range)
+  }
+  
+    func attributesForLevel(_ level: Int) -> [NSAttributedString.Key: AnyObject] {
+    return self.attributes
+  }
+  
+  func match(_ match: NSTextCheckingResult, attributedString: NSMutableAttributedString) {
+    let level = match.range(at: 1).length
+    addAttributes(attributedString, range: match.range(at: 2), level: level)
+    let range = NSRange(location: match.range(at: 1).location,
+                        length: match.range(at: 2).location - match.range(at: 1).location)
+    formatText(attributedString, range: range, level: level)
+  }
+}

+ 15 - 0
AIEmoji/Common/ThirdParty/MarkdownKit/Sources/Common/Protocols/MarkdownLinkElement.swift

@@ -0,0 +1,15 @@
+//
+//  MarkdownLinkElement.swift
+//  Pods
+//
+//  Created by Ivan Bruel on 18/07/16.
+//
+//
+import Foundation
+
+/// The base to all Link parsing elements.
+public protocol MarkdownLinkElement: MarkdownElement, MarkdownStyle {
+  
+  func formatText(_ attributedString: NSMutableAttributedString, range: NSRange, link: String)
+  func addAttributes(_ attributedString: NSMutableAttributedString, range: NSRange)
+}

+ 28 - 0
AIEmoji/Common/ThirdParty/MarkdownKit/Sources/Common/Protocols/MarkdownStyle.swift

@@ -0,0 +1,28 @@
+//
+//  MarkdownStyle.swift
+//  Pods
+//
+//  Created by Ivan Bruel on 18/07/16.
+//
+//
+import Foundation
+
+/// Styling protocol for all MarkdownElements
+public protocol MarkdownStyle {
+  var font: MarkdownFont? { get }
+  var color: MarkdownColor? { get }
+  var attributes: [NSAttributedString.Key: AnyObject] { get }
+}
+
+public extension MarkdownStyle {
+    var attributes: [NSAttributedString.Key: AnyObject] {
+        var attributes = [NSAttributedString.Key: AnyObject]()
+    if let font = font {
+        attributes[NSAttributedString.Key.font] = font
+    }
+    if let color = color {
+        attributes[NSAttributedString.Key.foregroundColor] = color
+    }
+    return attributes
+  }
+}

+ 29 - 0
AIEmoji/Common/ThirdParty/MarkdownKit/Sources/Common/Typealias.swift

@@ -0,0 +1,29 @@
+//
+//  Typealias+UIKit.swift
+//  MarkdownKit
+//
+//  Created by Bruno Oliveira on 31/01/2019.
+//  Copyright © 2019 Ivan Bruel. All rights reserved.
+//
+
+#if canImport(AppKit) && !targetEnvironment(macCatalyst)
+
+import AppKit
+
+public typealias MarkdownFont = NSFont
+public typealias MarkdownColor = NSColor
+
+public typealias NSMutableParagraphStyle = AppKit.NSMutableParagraphStyle
+public typealias NSUnderlineStyle = AppKit.NSUnderlineStyle
+
+#elseif canImport(UIKit)
+
+import UIKit
+
+public typealias MarkdownFont = UIFont
+public typealias MarkdownColor = UIColor
+
+public typealias NSMutableParagraphStyle = UIKit.NSMutableParagraphStyle
+public typealias NSUnderlineStyle = UIKit.NSUnderlineStyle
+
+#endif

+ 19 - 0
AIEmoji/Common/ThirdParty/MarkdownKit/Sources/UIKit/Elements/Code/MarkdownCode+UIKit.swift

@@ -0,0 +1,19 @@
+//
+//  MarkdownCode+UIKit.swift
+//  MarkdownKit
+//
+//  Created by Bruno Oliveira on 31/01/2019.
+//  Copyright © 2019 Ivan Bruel. All rights reserved.
+//
+
+#if canImport(UIKit)
+
+import UIKit
+
+public extension MarkdownCode {
+  static let defaultHighlightColor = UIColor(red: 0.90, green: 0.20, blue: 0.40, alpha: 1.0)
+  static let defaultBackgroundColor = UIColor(red: 0.85, green: 0.85, blue: 0.85, alpha: 1.0)
+  static let defaultFont = UIFont(name: "Menlo-Regular", size: 16)
+}
+
+#endif

+ 17 - 0
AIEmoji/Common/ThirdParty/MarkdownKit/Sources/UIKit/Elements/Header/MarkdownHeader+UIKit.swift

@@ -0,0 +1,17 @@
+//
+//  MarkdownHeader+UIKit.swift
+//  MarkdownKit
+//
+//  Created by Bruno Oliveira on 31/01/2019.
+//  Copyright © 2019 Ivan Bruel. All rights reserved.
+//
+
+#if canImport(UIKit)
+
+import UIKit
+
+public extension MarkdownHeader {
+    static let defaultFont = UIFont.boldSystemFont(ofSize: UIFont.smallSystemFontSize)
+}
+
+#endif

+ 17 - 0
AIEmoji/Common/ThirdParty/MarkdownKit/Sources/UIKit/Elements/Link/MarkdownLink+UIKit.swift

@@ -0,0 +1,17 @@
+//
+//  MarkdownLink+UIKit.swift
+//  MarkdownKit
+//
+//  Created by Bruno Oliveira on 31/01/2019.
+//  Copyright © 2019 Ivan Bruel. All rights reserved.
+//
+
+#if canImport(UIKit)
+
+import UIKit
+
+public extension MarkdownLink {
+  static let defaultColor = UIColor.blue
+}
+
+#endif

+ 39 - 0
AIEmoji/Common/ThirdParty/MarkdownKit/Sources/UIKit/Extensions/UIFont+Traits.swift

@@ -0,0 +1,39 @@
+//
+//  UIFont+Traits.swift
+//  Pods
+//
+//  Created by Ivan Bruel on 19/07/16.
+//
+//
+
+#if canImport(UIKit)
+
+import UIKit
+
+extension UIFont {
+
+  func withTraits(_ traits: UIFontDescriptor.SymbolicTraits...) -> UIFont? {
+    guard let descriptor = fontDescriptor.withSymbolicTraits(UIFontDescriptor.SymbolicTraits(traits)) else {
+        return nil
+    }
+    return UIFont(descriptor: descriptor, size: 0)
+  }
+
+  func bold() -> UIFont {
+    return withTraits(fontDescriptor.symbolicTraits, .traitBold) ?? self
+  }
+
+  func italic() -> UIFont {
+    return withTraits(fontDescriptor.symbolicTraits, .traitItalic) ?? self
+  }
+
+  func isItalic() -> Bool {
+    return fontDescriptor.symbolicTraits.contains(.traitItalic)
+  }
+
+  func isBold() -> Bool {
+    return fontDescriptor.symbolicTraits.contains(.traitBold)
+  }
+}
+
+#endif

+ 18 - 0
AIEmoji/Common/ThirdParty/MarkdownKit/Sources/UIKit/MarkdownParser+UIKit.swift

@@ -0,0 +1,18 @@
+//
+//  MarkdownParser+UIKit.swift
+//  MarkdownKit
+//
+//  Created by Bruno Oliveira on 31/01/2019.
+//  Copyright © 2019 Ivan Bruel. All rights reserved.
+//
+
+#if canImport(UIKit)
+
+import UIKit
+
+public extension MarkdownParser {
+    static let defaultFont = UIFont.systemFont(ofSize: UIFont.smallSystemFontSize)
+    static let defaultColor = UIColor.black
+}
+
+#endif

+ 2 - 1
Podfile

@@ -17,10 +17,11 @@ target 'AIEmoji' do
   pod 'JXSegmentedView'
   pod 'JXPagingView/Paging'
   pod 'Masonry'
-  pod 'SwiftyMarkdown'
   pod 'RealmSwift', '~>10'
   pod 'SwipeCellKit'
   pod 'TSSmalCoacopods', :path => '../TSSmalCoacopods'
+#  pod 'SwiftyMarkdown'
+#  pod "MarkdownKit"
 end
 
 

+ 1 - 5
Podfile.lock

@@ -52,7 +52,6 @@ PODS:
   - RealmSwift (10.54.2):
     - Realm (= 10.54.2)
   - SnapKit (5.7.1)
-  - SwiftyMarkdown (1.2.4)
   - SwipeCellKit (2.7.1)
   - TSSmalCoacopods (0.1.0):
     - Alamofire
@@ -71,7 +70,6 @@ DEPENDENCIES:
   - ObjectMapper
   - RealmSwift (~> 10)
   - SnapKit
-  - SwiftyMarkdown
   - SwipeCellKit
   - TSSmalCoacopods (from `../TSSmalCoacopods`)
 
@@ -95,7 +93,6 @@ SPEC REPOS:
     - Realm
     - RealmSwift
     - SnapKit
-    - SwiftyMarkdown
     - SwipeCellKit
 
 EXTERNAL SOURCES:
@@ -121,10 +118,9 @@ SPEC CHECKSUMS:
   Realm: 16852517a207e98cc6acba9336b56c30d06d84ad
   RealmSwift: bca777b3904ee58a9b16036e1840012f03348060
   SnapKit: d612e99e678a2d3b95bf60b0705ed0a35c03484a
-  SwiftyMarkdown: 7cdec87c6ab5cd9ea0e22ced288e889960649ba5
   SwipeCellKit: 3972254a826da74609926daf59b08d6c72e619ea
   TSSmalCoacopods: 9a7d88d8a76e8317722e5247a6b3b89b0fe32982
 
-PODFILE CHECKSUM: 4872869e53be2b0d09882df702db71719e1773e2
+PODFILE CHECKSUM: 5f1a9b50d5f2041d75518c8ffbc2f8cd02fa11a2
 
 COCOAPODS: 1.16.2