From 1a6a3a9a3c3f0ac909c8e68203df7b9c020d90fb Mon Sep 17 00:00:00 2001 From: Kris Baker Date: Sat, 23 Dec 2017 16:10:54 -0800 Subject: [PATCH] Fix nested blockquotes. Move strong/emphasis font updates to Style methods. Fix TableCell attributedText. Add videoId property to YoutubePlugin. --- Maaku.podspec | 5 +- Maaku.xcodeproj/project.pbxproj | 50 ++++++++++-------- Maaku/Core/DocumentConverter.swift | 6 ++- Maaku/Core/Extensions/TableCell.swift | 8 ++- Maaku/Core/Inline/Emphasis.swift | 20 +------ Maaku/Core/Inline/Strong.swift | 20 +------ Maaku/Core/Style.swift | 52 +++++++++++++++++++ Maaku/Plugins/YoutubePlugin.swift | 5 ++ .../Core/Container/BlockQuoteSpec.swift | 38 ++++++++++++++ MaakuTests/Markdown/nestedblockquote.md | 4 ++ MaakuTests/Plugins/YoutubePluginSpec.swift | 14 +++-- README.md | 2 +- 12 files changed, 156 insertions(+), 68 deletions(-) create mode 100644 MaakuTests/Markdown/nestedblockquote.md diff --git a/Maaku.podspec b/Maaku.podspec index d5ce162..8276a93 100755 --- a/Maaku.podspec +++ b/Maaku.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |s| s.name = "Maaku" - s.version = "0.1.4" + s.version = "0.1.5" s.summary = "Swift cmark wrapper with a Swift friendly representation of the AST" s.description = <<-DESC @@ -22,9 +22,8 @@ Pod::Spec.new do |s| s.default_subspec = 'Core' s.subspec 'CMark' do |core| - core.source_files = "Maaku/*.h", "Maaku/CMark/**/*.swift", "Maaku/libcmark/**/*{.c,.h}" + core.source_files = "Maaku/CMark/**/*.swift", "Maaku/libcmark/**/*{.c,.h}" core.preserve_paths = "Maaku/libcmark/**/*" - core.public_header_files = "Maaku/*.h" core.pod_target_xcconfig = { "SWIFT_INCLUDE_PATHS" => "$(PODS_TARGET_SRCROOT)/Maaku/libcmark/**", "LIBRARY_SEARCH_PATHS" => "$(PODS_TARGET_SRCROOT)/Maaku/" } end diff --git a/Maaku.xcodeproj/project.pbxproj b/Maaku.xcodeproj/project.pbxproj index ed963f6..d7a1ae7 100644 --- a/Maaku.xcodeproj/project.pbxproj +++ b/Maaku.xcodeproj/project.pbxproj @@ -10,8 +10,14 @@ 17649405248FAAFEE117F34C /* Pods_MaakuTestTargets_Maaku_tvOSTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8B36A2A592CD2BAB7BA1C431 /* Pods_MaakuTestTargets_Maaku_tvOSTests.framework */; }; 25FAB41D47754C8A8E77BBCF /* Pods_MaakuTestTargets_MaakuTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B8BE9758EB3D6AF90C8AD72B /* Pods_MaakuTestTargets_MaakuTests.framework */; }; 896300E57540772CB53C4E4C /* Pods_MaakuTestTargets_MaakuMacOSTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1454E0F5F3B889B08D70D0D7 /* Pods_MaakuTestTargets_MaakuMacOSTests.framework */; }; + A2298AE21FEEEF5400A0E275 /* nestedblockquote.md in Resources */ = {isa = PBXBuildFile; fileRef = A2298AE11FEEEF5400A0E275 /* nestedblockquote.md */; }; + A2298AE31FEEEF5400A0E275 /* nestedblockquote.md in Resources */ = {isa = PBXBuildFile; fileRef = A2298AE11FEEEF5400A0E275 /* nestedblockquote.md */; }; + A2298AE41FEEEF5400A0E275 /* nestedblockquote.md in Resources */ = {isa = PBXBuildFile; fileRef = A2298AE11FEEEF5400A0E275 /* nestedblockquote.md */; }; + A2298AE81FEF270800A0E275 /* Maaku.h in Headers */ = {isa = PBXBuildFile; fileRef = A2298AE71FEF270700A0E275 /* Maaku.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A2298AE91FEF270800A0E275 /* Maaku.h in Headers */ = {isa = PBXBuildFile; fileRef = A2298AE71FEF270700A0E275 /* Maaku.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A2298AEA1FEF270800A0E275 /* Maaku.h in Headers */ = {isa = PBXBuildFile; fileRef = A2298AE71FEF270700A0E275 /* Maaku.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A2298AEB1FEF270800A0E275 /* Maaku.h in Headers */ = {isa = PBXBuildFile; fileRef = A2298AE71FEF270700A0E275 /* Maaku.h */; settings = {ATTRIBUTES = (Public, ); }; }; A26822231FEB8B55006780A9 /* YoutubePluginSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = A26822221FEB8B55006780A9 /* YoutubePluginSpec.swift */; }; - A26822321FEB8F50006780A9 /* Maaku.h in Headers */ = {isa = PBXBuildFile; fileRef = A276D4871FEB1EB2006D5715 /* Maaku.h */; settings = {ATTRIBUTES = (Public, ); }; }; A26822331FEB8F63006780A9 /* CMDelimiterType.swift in Sources */ = {isa = PBXBuildFile; fileRef = A276D4AE1FEB21A9006D5715 /* CMDelimiterType.swift */; }; A26822341FEB8F63006780A9 /* CMDocument.swift in Sources */ = {isa = PBXBuildFile; fileRef = A276D4B01FEB21A9006D5715 /* CMDocument.swift */; }; A26822351FEB8F63006780A9 /* CMDocumentOption.swift in Sources */ = {isa = PBXBuildFile; fileRef = A276D4AC1FEB21A9006D5715 /* CMDocumentOption.swift */; }; @@ -202,8 +208,6 @@ A26823A21FEC6F70006780A9 /* maaku.c in Sources */ = {isa = PBXBuildFile; fileRef = A268239F1FEC6F70006780A9 /* maaku.c */; }; A26823A31FEC6F70006780A9 /* maaku.c in Sources */ = {isa = PBXBuildFile; fileRef = A268239F1FEC6F70006780A9 /* maaku.c */; }; A26823C21FECBD0D006780A9 /* Maaku.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A26823B91FECBD0D006780A9 /* Maaku.framework */; }; - A26823D01FECBE86006780A9 /* Maaku.h in Headers */ = {isa = PBXBuildFile; fileRef = A276D4871FEB1EB2006D5715 /* Maaku.h */; settings = {ATTRIBUTES = (Public, ); }; }; - A26823D11FECBE87006780A9 /* Maaku.h in Headers */ = {isa = PBXBuildFile; fileRef = A276D4871FEB1EB2006D5715 /* Maaku.h */; settings = {ATTRIBUTES = (Public, ); }; }; A26823D21FECBEB5006780A9 /* arena.c in Sources */ = {isa = PBXBuildFile; fileRef = A276D5011FEB21A9006D5715 /* arena.c */; }; A26823D31FECBEB5006780A9 /* autolink.c in Sources */ = {isa = PBXBuildFile; fileRef = A26823331FEC3036006780A9 /* autolink.c */; }; A26823D41FECBEB5006780A9 /* autolink.h in Headers */ = {isa = PBXBuildFile; fileRef = A268233F1FEC3037006780A9 /* autolink.h */; }; @@ -473,7 +477,6 @@ A26824DC1FECBF8B006780A9 /* HeadingSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = A276D61F1FEB3D1A006D5715 /* HeadingSpec.swift */; }; A26824DD1FECBF8B006780A9 /* HorizontalRuleSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = A276D6211FEB3D25006D5715 /* HorizontalRuleSpec.swift */; }; A276D48E1FEB1EB2006D5715 /* Maaku.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A276D4841FEB1EB2006D5715 /* Maaku.framework */; }; - A276D4951FEB1EB2006D5715 /* Maaku.h in Headers */ = {isa = PBXBuildFile; fileRef = A276D4871FEB1EB2006D5715 /* Maaku.h */; settings = {ATTRIBUTES = (Public, ); }; }; A276D51B1FEB21A9006D5715 /* YoutubePlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = A276D4A21FEB21A9006D5715 /* YoutubePlugin.swift */; }; A276D5241FEB21A9006D5715 /* CMDocumentOption.swift in Sources */ = {isa = PBXBuildFile; fileRef = A276D4AC1FEB21A9006D5715 /* CMDocumentOption.swift */; }; A276D5251FEB21A9006D5715 /* CMIterator.swift in Sources */ = {isa = PBXBuildFile; fileRef = A276D4AD1FEB21A9006D5715 /* CMIterator.swift */; }; @@ -635,6 +638,8 @@ 8B36A2A592CD2BAB7BA1C431 /* Pods_MaakuTestTargets_Maaku_tvOSTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_MaakuTestTargets_Maaku_tvOSTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 8F945BF16E83D8C1DA2A4716 /* Pods-MaakuTestTargets-Maaku-tvOSTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MaakuTestTargets-Maaku-tvOSTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-MaakuTestTargets-Maaku-tvOSTests/Pods-MaakuTestTargets-Maaku-tvOSTests.debug.xcconfig"; sourceTree = ""; }; 9B6AE0BC6CCFF378FDE156F9 /* Pods-MaakuTestTargets-Maaku-tvOSTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MaakuTestTargets-Maaku-tvOSTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-MaakuTestTargets-Maaku-tvOSTests/Pods-MaakuTestTargets-Maaku-tvOSTests.release.xcconfig"; sourceTree = ""; }; + A2298AE11FEEEF5400A0E275 /* nestedblockquote.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = nestedblockquote.md; sourceTree = ""; }; + A2298AE71FEF270700A0E275 /* Maaku.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Maaku.h; sourceTree = ""; }; A26822221FEB8B55006780A9 /* YoutubePluginSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YoutubePluginSpec.swift; sourceTree = ""; }; A268222A1FEB8F17006780A9 /* Maaku.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Maaku.framework; sourceTree = BUILT_PRODUCTS_DIR; }; A268229B1FEC2703006780A9 /* MaakuTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MaakuTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -674,7 +679,6 @@ A26823B91FECBD0D006780A9 /* Maaku.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Maaku.framework; sourceTree = BUILT_PRODUCTS_DIR; }; A26823C11FECBD0D006780A9 /* MaakuTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MaakuTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; A276D4841FEB1EB2006D5715 /* Maaku.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Maaku.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - A276D4871FEB1EB2006D5715 /* Maaku.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Maaku.h; sourceTree = ""; }; A276D4881FEB1EB2006D5715 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; A276D48D1FEB1EB2006D5715 /* MaakuTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MaakuTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; A276D4941FEB1EB2006D5715 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -961,7 +965,7 @@ A276D4861FEB1EB2006D5715 /* Maaku */ = { isa = PBXGroup; children = ( - A276D4871FEB1EB2006D5715 /* Maaku.h */, + A2298AE71FEF270700A0E275 /* Maaku.h */, A276D4881FEB1EB2006D5715 /* Info.plist */, A276D4AB1FEB21A9006D5715 /* CMark */, A276D4B41FEB21A9006D5715 /* Core */, @@ -1175,28 +1179,29 @@ A276D60B1FEB363A006D5715 /* Markdown */ = { isa = PBXGroup; children = ( - A276D60C1FEB364A006D5715 /* document.md */, - A276D6151FEB3BDA006D5715 /* paragraph.md */, - A276D6191FEB3CA9006D5715 /* htmlblock.md */, + A26823911FEC5595006780A9 /* autolink.md */, + A276D6331FEB3F50006D5715 /* blockquote.md */, A276D6231FEB3D31006D5715 /* codeblock.md */, + A276D60C1FEB364A006D5715 /* document.md */, + A276D6511FEB4657006D5715 /* emphasis.md */, + A276D6351FEB3F5B006D5715 /* footnotedefinition.md */, A276D6251FEB3D3A006D5715 /* heading.md */, A276D6271FEB3D4D006D5715 /* horizontalrule.md */, - A276D6331FEB3F50006D5715 /* blockquote.md */, - A276D6351FEB3F5B006D5715 /* footnotedefinition.md */, - A276D6391FEB3F69006D5715 /* orderedlist.md */, - A276D63B1FEB3F72006D5715 /* unorderedlist.md */, - A276D6511FEB4657006D5715 /* emphasis.md */, + A276D6191FEB3CA9006D5715 /* htmlblock.md */, A276D6531FEB4665006D5715 /* image.md */, A276D6551FEB4673006D5715 /* inlinecode.md */, A276D6571FEB467D006D5715 /* inlinehtml.md */, A276D6591FEB4686006D5715 /* linebreak.md */, - A276D65B1FEB4693006D5715 /* softbreak.md */, A276D65D1FEB469A006D5715 /* link.md */, + A2298AE11FEEEF5400A0E275 /* nestedblockquote.md */, + A276D6391FEB3F69006D5715 /* orderedlist.md */, + A276D6151FEB3BDA006D5715 /* paragraph.md */, + A276D65B1FEB4693006D5715 /* softbreak.md */, + A268238B1FEC517B006780A9 /* strikethrough.md */, A276D65F1FEB46A4006D5715 /* strong.md */, A268236C1FEC3330006780A9 /* table.md */, - A268238B1FEC517B006780A9 /* strikethrough.md */, - A26823911FEC5595006780A9 /* autolink.md */, A26823981FEC5969006780A9 /* tagfilter.md */, + A276D63B1FEB3F72006D5715 /* unorderedlist.md */, ); path = Markdown; sourceTree = ""; @@ -1267,10 +1272,10 @@ A26822841FEB8FAB006780A9 /* registry.h in Headers */, A26822781FEB8FAB006780A9 /* cmark.h in Headers */, A26823591FEC3178006780A9 /* table.h in Headers */, + A2298AE91FEF270800A0E275 /* Maaku.h in Headers */, A26822851FEB8FAB006780A9 /* render.h in Headers */, A26822721FEB8FAB006780A9 /* buffer.h in Headers */, A26822811FEB8FAB006780A9 /* parser.h in Headers */, - A26822321FEB8F50006780A9 /* Maaku.h in Headers */, A26822761FEB8FAB006780A9 /* cmark_extension_api.h in Headers */, A26822821FEB8FAB006780A9 /* plugin.h in Headers */, A268227C1FEB8FAB006780A9 /* html.h in Headers */, @@ -1295,7 +1300,6 @@ A26824101FECBEB5006780A9 /* tagfilter.h in Headers */, A26824121FECBEB5006780A9 /* utf8.h in Headers */, A26823DD1FECBEB5006780A9 /* cmark_version.h in Headers */, - A26823D01FECBE86006780A9 /* Maaku.h in Headers */, A268240A1FECBEB5006780A9 /* strikethrough.h in Headers */, A26823D41FECBEB5006780A9 /* autolink.h in Headers */, A26823FD1FECBEB5006780A9 /* parser.h in Headers */, @@ -1308,6 +1312,7 @@ A26823E41FECBEB5006780A9 /* core-extensions.h in Headers */, A26823F71FECBEB5006780A9 /* maaku.h in Headers */, A26823FA1FECBEB5006780A9 /* map.h in Headers */, + A2298AEA1FEF270800A0E275 /* Maaku.h in Headers */, A26823E61FECBEB5006780A9 /* ext_scanners.h in Headers */, A26824001FECBEB5006780A9 /* plugin.h in Headers */, A26823F21FECBEB5006780A9 /* iterator.h in Headers */, @@ -1335,7 +1340,6 @@ A26824521FECBEB5006780A9 /* tagfilter.h in Headers */, A26824541FECBEB5006780A9 /* utf8.h in Headers */, A268241F1FECBEB5006780A9 /* cmark_version.h in Headers */, - A26823D11FECBE87006780A9 /* Maaku.h in Headers */, A268244C1FECBEB5006780A9 /* strikethrough.h in Headers */, A26824161FECBEB5006780A9 /* autolink.h in Headers */, A268243F1FECBEB5006780A9 /* parser.h in Headers */, @@ -1348,6 +1352,7 @@ A26824261FECBEB5006780A9 /* core-extensions.h in Headers */, A26824391FECBEB5006780A9 /* maaku.h in Headers */, A268243C1FECBEB5006780A9 /* map.h in Headers */, + A2298AEB1FEF270800A0E275 /* Maaku.h in Headers */, A26824281FECBEB5006780A9 /* ext_scanners.h in Headers */, A26824421FECBEB5006780A9 /* plugin.h in Headers */, A26824341FECBEB5006780A9 /* iterator.h in Headers */, @@ -1378,7 +1383,6 @@ A276D5821FEB21A9006D5715 /* iterator.h in Headers */, A26823621FEC3179006780A9 /* strikethrough.h in Headers */, A276D55B1FEB21A9006D5715 /* cmark_export.h in Headers */, - A276D4951FEB1EB2006D5715 /* Maaku.h in Headers */, A276D57E1FEB21A9006D5715 /* inlines.h in Headers */, A276D5671FEB21A9006D5715 /* footnotes.h in Headers */, A276D56C1FEB21A9006D5715 /* node.h in Headers */, @@ -1388,6 +1392,7 @@ A276D5851FEB21A9006D5715 /* utf8.h in Headers */, A26823641FEC3179006780A9 /* table.h in Headers */, A276D5631FEB21A9006D5715 /* chunk.h in Headers */, + A2298AE81FEF270800A0E275 /* Maaku.h in Headers */, A276D5681FEB21A9006D5715 /* parser.h in Headers */, A276D5621FEB21A9006D5715 /* config.h in Headers */, A276D5791FEB21A9006D5715 /* syntax_extension.h in Headers */, @@ -1626,6 +1631,7 @@ A26822BD1FEC274F006780A9 /* document.md in Resources */, A26822C41FEC274F006780A9 /* footnotedefinition.md in Resources */, A26822C71FEC274F006780A9 /* emphasis.md in Resources */, + A2298AE31FEEEF5400A0E275 /* nestedblockquote.md in Resources */, A26822CB1FEC274F006780A9 /* linebreak.md in Resources */, A26823841FEC4DED006780A9 /* table.md in Resources */, A268238D1FEC517B006780A9 /* strikethrough.md in Resources */, @@ -1669,6 +1675,7 @@ A26824AF1FECBF72006780A9 /* document.md in Resources */, A26824B61FECBF72006780A9 /* footnotedefinition.md in Resources */, A26824B91FECBF72006780A9 /* emphasis.md in Resources */, + A2298AE41FEEEF5400A0E275 /* nestedblockquote.md in Resources */, A26824BD1FECBF72006780A9 /* linebreak.md in Resources */, A26824C11FECBF72006780A9 /* table.md in Resources */, A26824C21FECBF72006780A9 /* strikethrough.md in Resources */, @@ -1705,6 +1712,7 @@ A276D63A1FEB3F69006D5715 /* orderedlist.md in Resources */, A276D6361FEB3F5B006D5715 /* footnotedefinition.md in Resources */, A276D6521FEB4657006D5715 /* emphasis.md in Resources */, + A2298AE21FEEEF5400A0E275 /* nestedblockquote.md in Resources */, A276D65A1FEB4686006D5715 /* linebreak.md in Resources */, A268236D1FEC3330006780A9 /* table.md in Resources */, A268238C1FEC517B006780A9 /* strikethrough.md in Resources */, diff --git a/Maaku/Core/DocumentConverter.swift b/Maaku/Core/DocumentConverter.swift index f42912e..c7adde3 100644 --- a/Maaku/Core/DocumentConverter.swift +++ b/Maaku/Core/DocumentConverter.swift @@ -236,7 +236,11 @@ extension DocumentConverter: CMParserDelegate { public func parserDidEndBlockQuote(parser: CMParser) { var blockItems: [Block] = [] - while let item = nodes.last as? Block, !(item is BlockQuote) { + while let item = nodes.last as? Block { + if let quote = item as? BlockQuote, quote.items.count == 0 { + break + } + blockItems.insert(item, at: 0) nodes.removeLast() } diff --git a/Maaku/Core/Extensions/TableCell.swift b/Maaku/Core/Extensions/TableCell.swift index bf7eed8..7e0f585 100644 --- a/Maaku/Core/Extensions/TableCell.swift +++ b/Maaku/Core/Extensions/TableCell.swift @@ -35,7 +35,13 @@ public struct TableCell: Node { public extension TableCell { public func attributedText(style: Style) -> NSAttributedString { - return NSAttributedString() + let attributed = NSMutableAttributedString() + + for item in items { + attributed.append(item.attributedText(style: style.font(current: style.currentFont))) + } + + return attributed } } diff --git a/Maaku/Core/Inline/Emphasis.swift b/Maaku/Core/Inline/Emphasis.swift index d5c63ef..3f62d75 100644 --- a/Maaku/Core/Inline/Emphasis.swift +++ b/Maaku/Core/Inline/Emphasis.swift @@ -36,26 +36,8 @@ public extension Emphasis { public func attributedText(style: Style) -> NSAttributedString { let attributed = NSMutableAttributedString() - var emphasisFont = style.currentFont - var traits = style.currentFont.fontDescriptor.symbolicTraits - - #if os(OSX) - traits.insert(.italic) - let descriptor = style.currentFont.fontDescriptor.withSymbolicTraits(traits) - - if let font = Font(descriptor: descriptor, size: 0.0) { - emphasisFont = font - } - #else - traits.insert(.traitItalic) - - if let descriptor = style.currentFont.fontDescriptor.withSymbolicTraits(traits) { - emphasisFont = UIFont(descriptor: descriptor, size: 0.0) - } - #endif - for item in items { - attributed.append(item.attributedText(style: style.font(current: emphasisFont))) + attributed.append(item.attributedText(style: style.emphasis())) } return attributed diff --git a/Maaku/Core/Inline/Strong.swift b/Maaku/Core/Inline/Strong.swift index 309565e..f456594 100644 --- a/Maaku/Core/Inline/Strong.swift +++ b/Maaku/Core/Inline/Strong.swift @@ -37,26 +37,8 @@ public extension Strong { public func attributedText(style: Style) -> NSAttributedString { let attributed = NSMutableAttributedString() - var strongFont = style.currentFont - var traits = style.currentFont.fontDescriptor.symbolicTraits - - #if os(OSX) - traits.insert(.bold) - let descriptor = style.currentFont.fontDescriptor.withSymbolicTraits(traits) - - if let font = Font(descriptor: descriptor, size: 0.0) { - strongFont = font - } - #else - traits.insert(.traitBold) - - if let descriptor = style.currentFont.fontDescriptor.withSymbolicTraits(traits) { - strongFont = UIFont(descriptor: descriptor, size: 0.0) - } - #endif - for item in items { - attributed.append(item.attributedText(style: style.font(current: strongFont))) + attributed.append(item.attributedText(style: style.strong())) } return attributed diff --git a/Maaku/Core/Style.swift b/Maaku/Core/Style.swift index 8463c1c..1802ab5 100644 --- a/Maaku/Core/Style.swift +++ b/Maaku/Core/Style.swift @@ -351,6 +351,58 @@ public extension Style { return Style(currentFont: currentFont, h1Font: h1Font, h2Font: h2Font, h3Font: h3Font, h4Font: h4Font, h5Font: h5Font, h6Font: h6Font, paragraphFont: paragraphFont, currentForegroundColor: currentForegroundColor, h1ForegroundColor: h1ForegroundColor, h2ForegroundColor: h2ForegroundColor, h3ForegroundColor: h3ForegroundColor, h4ForegroundColor: h4ForegroundColor, h5ForegroundColor: h5ForegroundColor, h6ForegroundColor: h6ForegroundColor, paragraphForegroundColor: paragraphForegroundColor, linkForegroundColor: linkForegroundColor, hasStrikethrough: false) } + /// Returns an updated Style with a bold/strong font. + /// + /// - Returns: + /// - The updated Style. + public func strong() -> Style { + var strongFont = currentFont + var traits = currentFont.fontDescriptor.symbolicTraits + + #if os(OSX) + traits.insert(.bold) + let descriptor = currentFont.fontDescriptor.withSymbolicTraits(traits) + + if let font = Font(descriptor: descriptor, size: 0.0) { + strongFont = font + } + #else + traits.insert(.traitBold) + + if let descriptor = currentFont.fontDescriptor.withSymbolicTraits(traits) { + strongFont = UIFont(descriptor: descriptor, size: 0.0) + } + #endif + + return Style(currentFont: strongFont, h1Font: h1Font, h2Font: h2Font, h3Font: h3Font, h4Font: h4Font, h5Font: h5Font, h6Font: h6Font, paragraphFont: paragraphFont, currentForegroundColor: currentForegroundColor, h1ForegroundColor: h1ForegroundColor, h2ForegroundColor: h2ForegroundColor, h3ForegroundColor: h3ForegroundColor, h4ForegroundColor: h4ForegroundColor, h5ForegroundColor: h5ForegroundColor, h6ForegroundColor: h6ForegroundColor, paragraphForegroundColor: paragraphForegroundColor, linkForegroundColor: linkForegroundColor, hasStrikethrough: false) + } + + /// Returns an updated Style with an italic/emphasis font. + /// + /// - Returns: + /// - The updated Style. + public func emphasis() -> Style { + var emphasisFont = currentFont + var traits = currentFont.fontDescriptor.symbolicTraits + + #if os(OSX) + traits.insert(.italic) + let descriptor = currentFont.fontDescriptor.withSymbolicTraits(traits) + + if let font = Font(descriptor: descriptor, size: 0.0) { + emphasisFont = font + } + #else + traits.insert(.traitItalic) + + if let descriptor = currentFont.fontDescriptor.withSymbolicTraits(traits) { + emphasisFont = UIFont(descriptor: descriptor, size: 0.0) + } + #endif + + return Style(currentFont: emphasisFont, h1Font: h1Font, h2Font: h2Font, h3Font: h3Font, h4Font: h4Font, h5Font: h5Font, h6Font: h6Font, paragraphFont: paragraphFont, currentForegroundColor: currentForegroundColor, h1ForegroundColor: h1ForegroundColor, h2ForegroundColor: h2ForegroundColor, h3ForegroundColor: h3ForegroundColor, h4ForegroundColor: h4ForegroundColor, h5ForegroundColor: h5ForegroundColor, h6ForegroundColor: h6ForegroundColor, paragraphForegroundColor: paragraphForegroundColor, linkForegroundColor: linkForegroundColor, hasStrikethrough: false) + } + /// Returns the font for the specified heading. /// /// - Parameters: diff --git a/Maaku/Plugins/YoutubePlugin.swift b/Maaku/Plugins/YoutubePlugin.swift index dab6ba7..9bfbe20 100755 --- a/Maaku/Plugins/YoutubePlugin.swift +++ b/Maaku/Plugins/YoutubePlugin.swift @@ -41,6 +41,11 @@ public struct YoutubePlugin: Plugin { /// The youtube video URL. public let url: URL + /// The youtube video id. + public var videoId: String? { + return url.path.components(separatedBy: "/").last + } + public init(url: URL) { self.url = url } diff --git a/MaakuTests/Core/Container/BlockQuoteSpec.swift b/MaakuTests/Core/Container/BlockQuoteSpec.swift index 9cb6d71..9621564 100644 --- a/MaakuTests/Core/Container/BlockQuoteSpec.swift +++ b/MaakuTests/Core/Container/BlockQuoteSpec.swift @@ -40,6 +40,44 @@ class BlockQuoteSpec: QuickSpec { XCTFail("\(error.localizedDescription)") } } + + describe("Nested BlockQuote") { + let md = loadExample("nestedblockquote") + + guard let text = md else { + XCTFail("example blockquote nil") + return + } + + do { + let document = try Document(text: text) + + it("initializes the document") { + expect(document.count).to(equal(2)) + } + + it("parses the blockquote") { + expect(document[1]).to(beAKindOf(BlockQuote.self)) + } + + let blockquote = document[1] as! BlockQuote + + it("parses the nested blockquote") { + expect(blockquote.items.count).to(equal(2)) + expect(blockquote.items[1]).to(beAKindOf(BlockQuote.self)) + } + + let nestedBlockquote = blockquote.items[1] as! BlockQuote + + it("parses the next nested blockquote") { + expect(nestedBlockquote.items.count).to(equal(2)) + expect(nestedBlockquote.items[1]).to(beAKindOf(BlockQuote.self)) + } + } + catch let error { + XCTFail("\(error.localizedDescription)") + } + } } } diff --git a/MaakuTests/Markdown/nestedblockquote.md b/MaakuTests/Markdown/nestedblockquote.md new file mode 100644 index 0000000..196ab2d --- /dev/null +++ b/MaakuTests/Markdown/nestedblockquote.md @@ -0,0 +1,4 @@ +text +> quoted text +> > deeper layer +> > > even deeper layer diff --git a/MaakuTests/Plugins/YoutubePluginSpec.swift b/MaakuTests/Plugins/YoutubePluginSpec.swift index 0b87f44..a878c56 100644 --- a/MaakuTests/Plugins/YoutubePluginSpec.swift +++ b/MaakuTests/Plugins/YoutubePluginSpec.swift @@ -18,7 +18,7 @@ class YoutubePluginSpec: QuickSpec { describe("YoutubePlugin") { do { PluginManager.registerParsers(parsers: [YoutubePluginParser()]) - let document = try Document(text: "[youtubevideo](source::https://youtu.be/cugj1h6PuK0)\n") + let document = try Document(text: "[youtubevideo](source::https://youtu.be/kkdBB1hVLX0)\n") it("initializes the document") { expect(document.count).to(equal(1)) @@ -26,8 +26,16 @@ class YoutubePluginSpec: QuickSpec { it("parses the plugin") { expect(document[0]).to(beAKindOf(YoutubePlugin.self)) - let plugin = document[0] as! YoutubePlugin - expect(plugin.url).to(equal(URL(string: "https://youtu.be/cugj1h6PuK0"))) + } + + let plugin = document[0] as! YoutubePlugin + + it("sets the url") { + expect(plugin.url).to(equal(URL(string: "https://youtu.be/kkdBB1hVLX0"))) + } + + it("gets the video id") { + expect(plugin.videoId).to(equal("kkdBB1hVLX0")) } } catch let error { diff --git a/README.md b/README.md index d0a66ae..19d9cce 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # Maaku -The Maaku framework provides a Swift wrapper around cmark with the addition of a Swift friendly representation of the AST +The Maaku framework provides a Swift wrapper around gfm cmark with the addition of a Swift friendly representation of the AST [![](https://travis-ci.org/KristopherGBaker/Maaku.svg?branch=master)](https://travis-ci.org/KristopherGBaker/Maaku)