├── .github └── workflows │ └── swift.yml ├── .gitignore ├── CODE_OF_CONDUCT.md ├── LICENSE ├── Package.swift ├── Parma.podspec ├── Parma.xcodeproj ├── Down_Info.plist ├── GeneratedModuleMap │ └── libcmark │ │ └── module.modulemap ├── ParmaTests_Info.plist ├── Parma_Info.plist ├── libcmark_Info.plist ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ ├── IDEWorkspaceChecks.plist │ │ └── WorkspaceSettings.xcsettings └── xcshareddata │ ├── IDETemplateMacros.plist │ └── xcschemes │ └── Parma.xcscheme ├── README.md ├── Sample ├── Sample.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ └── xcshareddata │ │ └── IDETemplateMacros.plist ├── Shared │ ├── Assets.xcassets │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ ├── ContentView.swift │ ├── SampleApp.swift │ └── SampleMarkdown.md ├── iOS │ └── Info.plist └── macOS │ ├── Info.plist │ └── macOS.entitlements ├── Sources └── Parma │ ├── Composer │ ├── CodeElementComposer.swift │ ├── Composer.swift │ ├── ComposingContext.swift │ ├── ElementComposer.swift │ ├── EmphasisElementComposer.swift │ ├── HeadingElementComposer.swift │ ├── ImageElementComposer.swift │ ├── LinkElementComposer.swift │ ├── ListElementComposer.swift │ ├── ListItemElementComposer.swift │ ├── ParagraphElementComposer.swift │ ├── PlainTextComposer.swift │ ├── StrongElementComposer.swift │ └── UnknownElementComposer.swift │ ├── Element │ ├── Element.swift │ ├── HeadingLevel.swift │ ├── ListAttributes.swift │ ├── ListDelimiter.swift │ └── ListType.swift │ ├── Parma.swift │ ├── ParmaCore.swift │ └── Render │ ├── ParmaRender.swift │ └── ParmaRenderable.swift └── Tests ├── LinuxMain.swift └── ParmaTests ├── ParmaTests.swift └── XCTestManifests.swift /.github/workflows/swift.yml: -------------------------------------------------------------------------------- 1 | name: Swift 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | pull_request: 7 | branches: [ main ] 8 | 9 | jobs: 10 | build: 11 | 12 | runs-on: macos-latest 13 | 14 | steps: 15 | - uses: actions/checkout@v2 16 | - name: Build 17 | run: swift build -v 18 | - name: Run tests 19 | run: swift test -v 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | 3 | # Created by https://www.toptal.com/developers/gitignore/api/swift 4 | # Edit at https://www.toptal.com/developers/gitignore?templates=swift 5 | 6 | ### Swift ### 7 | # Xcode 8 | # 9 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 10 | 11 | ## User settings 12 | xcuserdata/ 13 | 14 | ## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9) 15 | *.xcscmblueprint 16 | *.xccheckout 17 | 18 | ## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4) 19 | build/ 20 | DerivedData/ 21 | *.moved-aside 22 | *.pbxuser 23 | !default.pbxuser 24 | *.mode1v3 25 | !default.mode1v3 26 | *.mode2v3 27 | !default.mode2v3 28 | *.perspectivev3 29 | !default.perspectivev3 30 | 31 | ## Obj-C/Swift specific 32 | *.hmap 33 | 34 | ## App packaging 35 | *.ipa 36 | *.dSYM.zip 37 | *.dSYM 38 | 39 | ## Playgrounds 40 | timeline.xctimeline 41 | playground.xcworkspace 42 | 43 | # Swift Package Manager 44 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 45 | Packages/ 46 | Package.pins 47 | Package.resolved 48 | # *.xcodeproj 49 | # Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata 50 | # hence it is not needed unless you have added a package configuration file to your project 51 | .swiftpm/ 52 | 53 | .build/ 54 | 55 | # CocoaPods 56 | # We recommend against adding the Pods directory to your .gitignore. However 57 | # you should judge for yourself, the pros and cons are mentioned at: 58 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 59 | # Pods/ 60 | # Add this line if you want to avoid checking in source code from the Xcode workspace 61 | # *.xcworkspace 62 | 63 | # Carthage 64 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 65 | # Carthage/Checkouts 66 | 67 | Carthage/Build/ 68 | 69 | # Accio dependency management 70 | Dependencies/ 71 | .accio/ 72 | 73 | # fastlane 74 | # It is recommended to not store the screenshots in the git repo. 75 | # Instead, use fastlane to re-generate the screenshots whenever they are needed. 76 | # For more information about the recommended setup visit: 77 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 78 | 79 | fastlane/report.xml 80 | fastlane/Preview.html 81 | fastlane/screenshots/**/*.png 82 | fastlane/test_output 83 | 84 | # Code Injection 85 | # After new code Injection tools there's a generated folder /iOSInjectionProject 86 | # https://github.com/johnno1962/injectionforxcode 87 | 88 | iOSInjectionProject/ 89 | 90 | # End of https://www.toptal.com/developers/gitignore/api/swift -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at wxclx98@gmail.com. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 72 | 73 | [homepage]: https://www.contributor-covenant.org 74 | 75 | For answers to common questions about this code of conduct, see 76 | https://www.contributor-covenant.org/faq 77 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Leonard Chan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:5.2 2 | // The swift-tools-version declares the minimum version of Swift required to build this package. 3 | 4 | import PackageDescription 5 | 6 | let package = Package( 7 | name: "Parma", 8 | platforms: [ 9 | .macOS("10.15"), 10 | .iOS("13.0"), 11 | .watchOS("7.0") 12 | ], 13 | products: [ 14 | .library( 15 | name: "Parma", 16 | targets: ["Parma"]), 17 | ], 18 | dependencies: [ 19 | .package(url: "https://github.com/iwasrobbed/Down", from: "0.9.3") 20 | ], 21 | targets: [ 22 | .target( 23 | name: "Parma", 24 | dependencies: ["Down"]), 25 | .testTarget( 26 | name: "ParmaTests", 27 | dependencies: ["Parma"]), 28 | ] 29 | ) 30 | -------------------------------------------------------------------------------- /Parma.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = 'Parma' 3 | s.version = '0.3.0' 4 | s.summary = 'A SwiftUI view for displaying Markdown with customizable appearances.' 5 | s.description = 'Display Markdown using pure SwiftUI components. Taking advantages of ViewBuilder to make custom appearances for Text and View.' 6 | s.homepage = 'https://github.com/dasautoooo/Parma' 7 | s.license = { :type => 'MIT', :file => 'LICENSE' } 8 | s.author = { 'Leonard Chan' => 'wxclx98@gmail.com' } 9 | s.source = { :git => 'https://github.com/dasautoooo/Parma.git', :tag => "v" + s.version.to_s } 10 | s.social_media_url = 'https://twitter.com/DasAutoooo' 11 | 12 | s.swift_version = '5.0' 13 | 14 | s.ios.deployment_target = '13.0' 15 | s.osx.deployment_target = '10.15' 16 | 17 | s.source_files = 'Sources/**/*' 18 | 19 | s.dependency 'Down', '~> 0.9.3' 20 | end 21 | -------------------------------------------------------------------------------- /Parma.xcodeproj/Down_Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | CFBundleDevelopmentRegion 5 | en 6 | CFBundleExecutable 7 | $(EXECUTABLE_NAME) 8 | CFBundleIdentifier 9 | $(PRODUCT_BUNDLE_IDENTIFIER) 10 | CFBundleInfoDictionaryVersion 11 | 6.0 12 | CFBundleName 13 | $(PRODUCT_NAME) 14 | CFBundlePackageType 15 | FMWK 16 | CFBundleShortVersionString 17 | 1.0 18 | CFBundleSignature 19 | ???? 20 | CFBundleVersion 21 | $(CURRENT_PROJECT_VERSION) 22 | NSPrincipalClass 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /Parma.xcodeproj/GeneratedModuleMap/libcmark/module.modulemap: -------------------------------------------------------------------------------- 1 | module libcmark { 2 | umbrella "../../../.build/checkouts/Down/Source/cmark" 3 | export * 4 | } 5 | -------------------------------------------------------------------------------- /Parma.xcodeproj/ParmaTests_Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | CFBundleDevelopmentRegion 5 | en 6 | CFBundleExecutable 7 | $(EXECUTABLE_NAME) 8 | CFBundleIdentifier 9 | $(PRODUCT_BUNDLE_IDENTIFIER) 10 | CFBundleInfoDictionaryVersion 11 | 6.0 12 | CFBundleName 13 | $(PRODUCT_NAME) 14 | CFBundlePackageType 15 | BNDL 16 | CFBundleShortVersionString 17 | 1.0 18 | CFBundleSignature 19 | ???? 20 | CFBundleVersion 21 | $(CURRENT_PROJECT_VERSION) 22 | NSPrincipalClass 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /Parma.xcodeproj/Parma_Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | CFBundleDevelopmentRegion 5 | en 6 | CFBundleExecutable 7 | $(EXECUTABLE_NAME) 8 | CFBundleIdentifier 9 | $(PRODUCT_BUNDLE_IDENTIFIER) 10 | CFBundleInfoDictionaryVersion 11 | 6.0 12 | CFBundleName 13 | $(PRODUCT_NAME) 14 | CFBundlePackageType 15 | FMWK 16 | CFBundleShortVersionString 17 | 1.0 18 | CFBundleSignature 19 | ???? 20 | CFBundleVersion 21 | $(CURRENT_PROJECT_VERSION) 22 | NSPrincipalClass 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /Parma.xcodeproj/libcmark_Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | CFBundleDevelopmentRegion 5 | en 6 | CFBundleExecutable 7 | $(EXECUTABLE_NAME) 8 | CFBundleIdentifier 9 | $(PRODUCT_BUNDLE_IDENTIFIER) 10 | CFBundleInfoDictionaryVersion 11 | 6.0 12 | CFBundleName 13 | $(PRODUCT_NAME) 14 | CFBundlePackageType 15 | FMWK 16 | CFBundleShortVersionString 17 | 1.0 18 | CFBundleSignature 19 | ???? 20 | CFBundleVersion 21 | $(CURRENT_PROJECT_VERSION) 22 | NSPrincipalClass 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /Parma.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXAggregateTarget section */ 10 | "Parma::ParmaPackageTests::ProductTarget" /* ParmaPackageTests */ = { 11 | isa = PBXAggregateTarget; 12 | buildConfigurationList = OBJ_280 /* Build configuration list for PBXAggregateTarget "ParmaPackageTests" */; 13 | buildPhases = ( 14 | ); 15 | dependencies = ( 16 | OBJ_283 /* PBXTargetDependency */, 17 | ); 18 | name = ParmaPackageTests; 19 | productName = ParmaPackageTests; 20 | }; 21 | /* End PBXAggregateTarget section */ 22 | 23 | /* Begin PBXBuildFile section */ 24 | OBJ_169 /* BaseNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_42 /* BaseNode.swift */; }; 25 | OBJ_170 /* BlockQuote.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_43 /* BlockQuote.swift */; }; 26 | OBJ_171 /* Code.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_44 /* Code.swift */; }; 27 | OBJ_172 /* CodeBlock.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_45 /* CodeBlock.swift */; }; 28 | OBJ_173 /* CustomBlock.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_46 /* CustomBlock.swift */; }; 29 | OBJ_174 /* CustomInline.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_47 /* CustomInline.swift */; }; 30 | OBJ_175 /* Document.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_48 /* Document.swift */; }; 31 | OBJ_176 /* Emphasis.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_49 /* Emphasis.swift */; }; 32 | OBJ_177 /* Heading.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_50 /* Heading.swift */; }; 33 | OBJ_178 /* HtmlBlock.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_51 /* HtmlBlock.swift */; }; 34 | OBJ_179 /* HtmlInline.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_52 /* HtmlInline.swift */; }; 35 | OBJ_180 /* Image.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_53 /* Image.swift */; }; 36 | OBJ_181 /* Item.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_54 /* Item.swift */; }; 37 | OBJ_182 /* LineBreak.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_55 /* LineBreak.swift */; }; 38 | OBJ_183 /* Link.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_56 /* Link.swift */; }; 39 | OBJ_184 /* List.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_57 /* List.swift */; }; 40 | OBJ_185 /* Node.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_58 /* Node.swift */; }; 41 | OBJ_186 /* Paragraph.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_59 /* Paragraph.swift */; }; 42 | OBJ_187 /* SoftBreak.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_60 /* SoftBreak.swift */; }; 43 | OBJ_188 /* Strong.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_61 /* Strong.swift */; }; 44 | OBJ_189 /* Text.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_62 /* Text.swift */; }; 45 | OBJ_190 /* ThematicBreak.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_63 /* ThematicBreak.swift */; }; 46 | OBJ_191 /* ColorCollection.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_66 /* ColorCollection.swift */; }; 47 | OBJ_192 /* FontCollection.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_67 /* FontCollection.swift */; }; 48 | OBJ_193 /* ParagraphStyleCollection.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_68 /* ParagraphStyleCollection.swift */; }; 49 | OBJ_194 /* BlockBackgroundColorAttribute.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_70 /* BlockBackgroundColorAttribute.swift */; }; 50 | OBJ_195 /* QuoteStripeAttribute.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_71 /* QuoteStripeAttribute.swift */; }; 51 | OBJ_196 /* ThematicBreakAttribute.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_72 /* ThematicBreakAttribute.swift */; }; 52 | OBJ_197 /* CGPoint+Translate.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_75 /* CGPoint+Translate.swift */; }; 53 | OBJ_198 /* CGRect+Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_76 /* CGRect+Helpers.swift */; }; 54 | OBJ_199 /* NSAttributedString+Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_77 /* NSAttributedString+Helpers.swift */; }; 55 | OBJ_200 /* NSMutableAttributedString+Attributes.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_78 /* NSMutableAttributedString+Attributes.swift */; }; 56 | OBJ_201 /* UIFont+Traits.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_79 /* UIFont+Traits.swift */; }; 57 | OBJ_202 /* ListItemParagraphStyler.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_80 /* ListItemParagraphStyler.swift */; }; 58 | OBJ_203 /* DownDebugLayoutManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_82 /* DownDebugLayoutManager.swift */; }; 59 | OBJ_204 /* DownLayoutManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_83 /* DownLayoutManager.swift */; }; 60 | OBJ_205 /* CodeBlockOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_85 /* CodeBlockOptions.swift */; }; 61 | OBJ_206 /* ListItemOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_86 /* ListItemOptions.swift */; }; 62 | OBJ_207 /* QuoteStripeOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_87 /* QuoteStripeOptions.swift */; }; 63 | OBJ_208 /* ThematicBreakOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_88 /* ThematicBreakOptions.swift */; }; 64 | OBJ_209 /* DownStyler.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_90 /* DownStyler.swift */; }; 65 | OBJ_210 /* DownStylerConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_91 /* DownStylerConfiguration.swift */; }; 66 | OBJ_211 /* Styler.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_92 /* Styler.swift */; }; 67 | OBJ_212 /* DownDebugTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_94 /* DownDebugTextView.swift */; }; 68 | OBJ_213 /* DownTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_95 /* DownTextView.swift */; }; 69 | OBJ_214 /* AttributedStringVisitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_97 /* AttributedStringVisitor.swift */; }; 70 | OBJ_215 /* DebugVisitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_98 /* DebugVisitor.swift */; }; 71 | OBJ_216 /* ListItemPrefixGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_99 /* ListItemPrefixGenerator.swift */; }; 72 | OBJ_217 /* Vistor.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_100 /* Vistor.swift */; }; 73 | OBJ_218 /* Down.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_101 /* Down.swift */; }; 74 | OBJ_219 /* DownErrors.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_103 /* DownErrors.swift */; }; 75 | OBJ_220 /* DownOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_104 /* DownOptions.swift */; }; 76 | OBJ_221 /* NSAttributedString+HTML.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_106 /* NSAttributedString+HTML.swift */; }; 77 | OBJ_222 /* String+ToHTML.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_107 /* String+ToHTML.swift */; }; 78 | OBJ_223 /* DownASTRenderable.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_109 /* DownASTRenderable.swift */; }; 79 | OBJ_224 /* DownAttributedStringRenderable.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_110 /* DownAttributedStringRenderable.swift */; }; 80 | OBJ_225 /* DownCommonMarkRenderable.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_111 /* DownCommonMarkRenderable.swift */; }; 81 | OBJ_226 /* DownGroffRenderable.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_112 /* DownGroffRenderable.swift */; }; 82 | OBJ_227 /* DownHTMLRenderable.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_113 /* DownHTMLRenderable.swift */; }; 83 | OBJ_228 /* DownLaTeXRenderable.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_114 /* DownLaTeXRenderable.swift */; }; 84 | OBJ_229 /* DownRenderable.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_115 /* DownRenderable.swift */; }; 85 | OBJ_230 /* DownXMLRenderable.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_116 /* DownXMLRenderable.swift */; }; 86 | OBJ_231 /* DownView.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_118 /* DownView.swift */; }; 87 | OBJ_233 /* libcmark.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = "Down::libcmark::Product" /* libcmark.framework */; }; 88 | OBJ_241 /* Package.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_156 /* Package.swift */; }; 89 | OBJ_247 /* CodeElementComposer.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_10 /* CodeElementComposer.swift */; }; 90 | OBJ_248 /* Composer.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_11 /* Composer.swift */; }; 91 | OBJ_249 /* ComposingContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_12 /* ComposingContext.swift */; }; 92 | OBJ_250 /* ElementComposer.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_13 /* ElementComposer.swift */; }; 93 | OBJ_251 /* EmphasisElementComposer.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_14 /* EmphasisElementComposer.swift */; }; 94 | OBJ_252 /* HeadingElementComposer.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_15 /* HeadingElementComposer.swift */; }; 95 | OBJ_253 /* ImageElementComposer.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_16 /* ImageElementComposer.swift */; }; 96 | OBJ_254 /* LinkElementComposer.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_17 /* LinkElementComposer.swift */; }; 97 | OBJ_255 /* ListElementComposer.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_18 /* ListElementComposer.swift */; }; 98 | OBJ_256 /* ListItemElementComposer.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_19 /* ListItemElementComposer.swift */; }; 99 | OBJ_257 /* ParagraphElementComposer.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_20 /* ParagraphElementComposer.swift */; }; 100 | OBJ_258 /* PlainTextComposer.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_21 /* PlainTextComposer.swift */; }; 101 | OBJ_259 /* StrongElementComposer.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_22 /* StrongElementComposer.swift */; }; 102 | OBJ_260 /* UnknownElementComposer.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_23 /* UnknownElementComposer.swift */; }; 103 | OBJ_261 /* Element.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_25 /* Element.swift */; }; 104 | OBJ_262 /* HeadingLevel.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_26 /* HeadingLevel.swift */; }; 105 | OBJ_263 /* ListType.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_27 /* ListType.swift */; }; 106 | OBJ_264 /* Parma.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_28 /* Parma.swift */; }; 107 | OBJ_265 /* ParmaCore.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_29 /* ParmaCore.swift */; }; 108 | OBJ_266 /* ParmaRender.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_31 /* ParmaRender.swift */; }; 109 | OBJ_267 /* ParmaRenderable.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_32 /* ParmaRenderable.swift */; }; 110 | OBJ_269 /* Down.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = "Down::Down::Product" /* Down.framework */; }; 111 | OBJ_270 /* libcmark.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = "Down::libcmark::Product" /* libcmark.framework */; }; 112 | OBJ_278 /* Package.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_6 /* Package.swift */; }; 113 | OBJ_289 /* ParmaTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_35 /* ParmaTests.swift */; }; 114 | OBJ_290 /* XCTestManifests.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_36 /* XCTestManifests.swift */; }; 115 | OBJ_292 /* Parma.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = "Parma::Parma::Product" /* Parma.framework */; }; 116 | OBJ_293 /* Down.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = "Down::Down::Product" /* Down.framework */; }; 117 | OBJ_294 /* libcmark.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = "Down::libcmark::Product" /* libcmark.framework */; }; 118 | OBJ_302 /* blocks.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_120 /* blocks.c */; }; 119 | OBJ_303 /* buffer.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_121 /* buffer.c */; }; 120 | OBJ_304 /* cmark.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_122 /* cmark.c */; }; 121 | OBJ_305 /* cmark_ctype.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_123 /* cmark_ctype.c */; }; 122 | OBJ_306 /* commonmark.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_124 /* commonmark.c */; }; 123 | OBJ_307 /* houdini_href_e.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_125 /* houdini_href_e.c */; }; 124 | OBJ_308 /* houdini_html_e.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_126 /* houdini_html_e.c */; }; 125 | OBJ_309 /* houdini_html_u.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_127 /* houdini_html_u.c */; }; 126 | OBJ_310 /* html.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_128 /* html.c */; }; 127 | OBJ_311 /* inlines.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_129 /* inlines.c */; }; 128 | OBJ_312 /* iterator.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_130 /* iterator.c */; }; 129 | OBJ_313 /* latex.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_131 /* latex.c */; }; 130 | OBJ_314 /* man.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_132 /* man.c */; }; 131 | OBJ_315 /* node.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_133 /* node.c */; }; 132 | OBJ_316 /* references.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_134 /* references.c */; }; 133 | OBJ_317 /* render.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_135 /* render.c */; }; 134 | OBJ_318 /* scanners.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_136 /* scanners.c */; }; 135 | OBJ_319 /* utf8.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_137 /* utf8.c */; }; 136 | OBJ_320 /* xml.c in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_138 /* xml.c */; }; 137 | /* End PBXBuildFile section */ 138 | 139 | /* Begin PBXContainerItemProxy section */ 140 | D709BF4D24E97CC80070BEE2 /* PBXContainerItemProxy */ = { 141 | isa = PBXContainerItemProxy; 142 | containerPortal = OBJ_1 /* Project object */; 143 | proxyType = 1; 144 | remoteGlobalIDString = "Down::Down"; 145 | remoteInfo = Down; 146 | }; 147 | D709BF4E24E97CC80070BEE2 /* PBXContainerItemProxy */ = { 148 | isa = PBXContainerItemProxy; 149 | containerPortal = OBJ_1 /* Project object */; 150 | proxyType = 1; 151 | remoteGlobalIDString = "Down::libcmark"; 152 | remoteInfo = libcmark; 153 | }; 154 | D709BF4F24E97CC80070BEE2 /* PBXContainerItemProxy */ = { 155 | isa = PBXContainerItemProxy; 156 | containerPortal = OBJ_1 /* Project object */; 157 | proxyType = 1; 158 | remoteGlobalIDString = "Down::libcmark"; 159 | remoteInfo = libcmark; 160 | }; 161 | D709BF5024E97CC80070BEE2 /* PBXContainerItemProxy */ = { 162 | isa = PBXContainerItemProxy; 163 | containerPortal = OBJ_1 /* Project object */; 164 | proxyType = 1; 165 | remoteGlobalIDString = "Parma::Parma"; 166 | remoteInfo = Parma; 167 | }; 168 | D709BF5124E97CC80070BEE2 /* PBXContainerItemProxy */ = { 169 | isa = PBXContainerItemProxy; 170 | containerPortal = OBJ_1 /* Project object */; 171 | proxyType = 1; 172 | remoteGlobalIDString = "Down::Down"; 173 | remoteInfo = Down; 174 | }; 175 | D709BF5224E97CC80070BEE2 /* PBXContainerItemProxy */ = { 176 | isa = PBXContainerItemProxy; 177 | containerPortal = OBJ_1 /* Project object */; 178 | proxyType = 1; 179 | remoteGlobalIDString = "Down::libcmark"; 180 | remoteInfo = libcmark; 181 | }; 182 | D709BF5324E97CCA0070BEE2 /* PBXContainerItemProxy */ = { 183 | isa = PBXContainerItemProxy; 184 | containerPortal = OBJ_1 /* Project object */; 185 | proxyType = 1; 186 | remoteGlobalIDString = "Parma::ParmaTests"; 187 | remoteInfo = ParmaTests; 188 | }; 189 | /* End PBXContainerItemProxy section */ 190 | 191 | /* Begin PBXFileReference section */ 192 | "Down::Down::Product" /* Down.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Down.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 193 | "Down::libcmark::Product" /* libcmark.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = libcmark.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 194 | OBJ_10 /* CodeElementComposer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CodeElementComposer.swift; sourceTree = ""; }; 195 | OBJ_100 /* Vistor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Vistor.swift; sourceTree = ""; }; 196 | OBJ_101 /* Down.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Down.swift; sourceTree = ""; }; 197 | OBJ_103 /* DownErrors.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DownErrors.swift; sourceTree = ""; }; 198 | OBJ_104 /* DownOptions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DownOptions.swift; sourceTree = ""; }; 199 | OBJ_106 /* NSAttributedString+HTML.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSAttributedString+HTML.swift"; sourceTree = ""; }; 200 | OBJ_107 /* String+ToHTML.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+ToHTML.swift"; sourceTree = ""; }; 201 | OBJ_109 /* DownASTRenderable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DownASTRenderable.swift; sourceTree = ""; }; 202 | OBJ_11 /* Composer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Composer.swift; sourceTree = ""; }; 203 | OBJ_110 /* DownAttributedStringRenderable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DownAttributedStringRenderable.swift; sourceTree = ""; }; 204 | OBJ_111 /* DownCommonMarkRenderable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DownCommonMarkRenderable.swift; sourceTree = ""; }; 205 | OBJ_112 /* DownGroffRenderable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DownGroffRenderable.swift; sourceTree = ""; }; 206 | OBJ_113 /* DownHTMLRenderable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DownHTMLRenderable.swift; sourceTree = ""; }; 207 | OBJ_114 /* DownLaTeXRenderable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DownLaTeXRenderable.swift; sourceTree = ""; }; 208 | OBJ_115 /* DownRenderable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DownRenderable.swift; sourceTree = ""; }; 209 | OBJ_116 /* DownXMLRenderable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DownXMLRenderable.swift; sourceTree = ""; }; 210 | OBJ_118 /* DownView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DownView.swift; sourceTree = ""; }; 211 | OBJ_12 /* ComposingContext.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposingContext.swift; sourceTree = ""; }; 212 | OBJ_120 /* blocks.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = blocks.c; sourceTree = ""; }; 213 | OBJ_121 /* buffer.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = buffer.c; sourceTree = ""; }; 214 | OBJ_122 /* cmark.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = cmark.c; sourceTree = ""; }; 215 | OBJ_123 /* cmark_ctype.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = cmark_ctype.c; sourceTree = ""; }; 216 | OBJ_124 /* commonmark.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = commonmark.c; sourceTree = ""; }; 217 | OBJ_125 /* houdini_href_e.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = houdini_href_e.c; sourceTree = ""; }; 218 | OBJ_126 /* houdini_html_e.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = houdini_html_e.c; sourceTree = ""; }; 219 | OBJ_127 /* houdini_html_u.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = houdini_html_u.c; sourceTree = ""; }; 220 | OBJ_128 /* html.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = html.c; sourceTree = ""; }; 221 | OBJ_129 /* inlines.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = inlines.c; sourceTree = ""; }; 222 | OBJ_13 /* ElementComposer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ElementComposer.swift; sourceTree = ""; }; 223 | OBJ_130 /* iterator.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = iterator.c; sourceTree = ""; }; 224 | OBJ_131 /* latex.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = latex.c; sourceTree = ""; }; 225 | OBJ_132 /* man.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = man.c; sourceTree = ""; }; 226 | OBJ_133 /* node.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = node.c; sourceTree = ""; }; 227 | OBJ_134 /* references.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = references.c; sourceTree = ""; }; 228 | OBJ_135 /* render.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = render.c; sourceTree = ""; }; 229 | OBJ_136 /* scanners.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = scanners.c; sourceTree = ""; }; 230 | OBJ_137 /* utf8.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = utf8.c; sourceTree = ""; }; 231 | OBJ_138 /* xml.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = xml.c; sourceTree = ""; }; 232 | OBJ_139 /* cmark_export.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = cmark_export.h; sourceTree = ""; }; 233 | OBJ_14 /* EmphasisElementComposer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmphasisElementComposer.swift; sourceTree = ""; }; 234 | OBJ_140 /* config.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = config.h; sourceTree = ""; }; 235 | OBJ_141 /* chunk.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = chunk.h; sourceTree = ""; }; 236 | OBJ_142 /* parser.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = parser.h; sourceTree = ""; }; 237 | OBJ_143 /* scanners.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = scanners.h; sourceTree = ""; }; 238 | OBJ_144 /* node.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = node.h; sourceTree = ""; }; 239 | OBJ_145 /* cmark_version.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = cmark_version.h; sourceTree = ""; }; 240 | OBJ_146 /* cmark_ctype.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = cmark_ctype.h; sourceTree = ""; }; 241 | OBJ_147 /* buffer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = buffer.h; sourceTree = ""; }; 242 | OBJ_148 /* cmark.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = cmark.h; sourceTree = ""; }; 243 | OBJ_149 /* inlines.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = inlines.h; sourceTree = ""; }; 244 | OBJ_15 /* HeadingElementComposer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadingElementComposer.swift; sourceTree = ""; }; 245 | OBJ_150 /* houdini.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = houdini.h; sourceTree = ""; }; 246 | OBJ_151 /* iterator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = iterator.h; sourceTree = ""; }; 247 | OBJ_152 /* utf8.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = utf8.h; sourceTree = ""; }; 248 | OBJ_153 /* references.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = references.h; sourceTree = ""; }; 249 | OBJ_154 /* render.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = render.h; sourceTree = ""; }; 250 | OBJ_155 /* module.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; name = module.modulemap; path = /Users/leonard/Documents/Development/Parma/Parma.xcodeproj/GeneratedModuleMap/libcmark/module.modulemap; sourceTree = ""; }; 251 | OBJ_156 /* Package.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; name = Package.swift; path = /Users/leonard/Documents/Development/Parma/.build/checkouts/Down/Package.swift; sourceTree = ""; }; 252 | OBJ_16 /* ImageElementComposer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageElementComposer.swift; sourceTree = ""; }; 253 | OBJ_162 /* LICENSE */ = {isa = PBXFileReference; lastKnownFileType = text; path = LICENSE; sourceTree = ""; }; 254 | OBJ_163 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; 255 | OBJ_17 /* LinkElementComposer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkElementComposer.swift; sourceTree = ""; }; 256 | OBJ_18 /* ListElementComposer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListElementComposer.swift; sourceTree = ""; }; 257 | OBJ_19 /* ListItemElementComposer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListItemElementComposer.swift; sourceTree = ""; }; 258 | OBJ_20 /* ParagraphElementComposer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParagraphElementComposer.swift; sourceTree = ""; }; 259 | OBJ_21 /* PlainTextComposer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlainTextComposer.swift; sourceTree = ""; }; 260 | OBJ_22 /* StrongElementComposer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StrongElementComposer.swift; sourceTree = ""; }; 261 | OBJ_23 /* UnknownElementComposer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnknownElementComposer.swift; sourceTree = ""; }; 262 | OBJ_25 /* Element.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Element.swift; sourceTree = ""; }; 263 | OBJ_26 /* HeadingLevel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadingLevel.swift; sourceTree = ""; }; 264 | OBJ_27 /* ListType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListType.swift; sourceTree = ""; }; 265 | OBJ_28 /* Parma.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Parma.swift; sourceTree = ""; }; 266 | OBJ_29 /* ParmaCore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParmaCore.swift; sourceTree = ""; }; 267 | OBJ_31 /* ParmaRender.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParmaRender.swift; sourceTree = ""; }; 268 | OBJ_32 /* ParmaRenderable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParmaRenderable.swift; sourceTree = ""; }; 269 | OBJ_35 /* ParmaTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParmaTests.swift; sourceTree = ""; }; 270 | OBJ_36 /* XCTestManifests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XCTestManifests.swift; sourceTree = ""; }; 271 | OBJ_42 /* BaseNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseNode.swift; sourceTree = ""; }; 272 | OBJ_43 /* BlockQuote.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlockQuote.swift; sourceTree = ""; }; 273 | OBJ_44 /* Code.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Code.swift; sourceTree = ""; }; 274 | OBJ_45 /* CodeBlock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CodeBlock.swift; sourceTree = ""; }; 275 | OBJ_46 /* CustomBlock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomBlock.swift; sourceTree = ""; }; 276 | OBJ_47 /* CustomInline.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomInline.swift; sourceTree = ""; }; 277 | OBJ_48 /* Document.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Document.swift; sourceTree = ""; }; 278 | OBJ_49 /* Emphasis.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Emphasis.swift; sourceTree = ""; }; 279 | OBJ_50 /* Heading.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Heading.swift; sourceTree = ""; }; 280 | OBJ_51 /* HtmlBlock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HtmlBlock.swift; sourceTree = ""; }; 281 | OBJ_52 /* HtmlInline.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HtmlInline.swift; sourceTree = ""; }; 282 | OBJ_53 /* Image.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Image.swift; sourceTree = ""; }; 283 | OBJ_54 /* Item.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Item.swift; sourceTree = ""; }; 284 | OBJ_55 /* LineBreak.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LineBreak.swift; sourceTree = ""; }; 285 | OBJ_56 /* Link.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Link.swift; sourceTree = ""; }; 286 | OBJ_57 /* List.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = List.swift; sourceTree = ""; }; 287 | OBJ_58 /* Node.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Node.swift; sourceTree = ""; }; 288 | OBJ_59 /* Paragraph.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Paragraph.swift; sourceTree = ""; }; 289 | OBJ_6 /* Package.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; path = Package.swift; sourceTree = ""; }; 290 | OBJ_60 /* SoftBreak.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SoftBreak.swift; sourceTree = ""; }; 291 | OBJ_61 /* Strong.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Strong.swift; sourceTree = ""; }; 292 | OBJ_62 /* Text.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Text.swift; sourceTree = ""; }; 293 | OBJ_63 /* ThematicBreak.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThematicBreak.swift; sourceTree = ""; }; 294 | OBJ_66 /* ColorCollection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorCollection.swift; sourceTree = ""; }; 295 | OBJ_67 /* FontCollection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FontCollection.swift; sourceTree = ""; }; 296 | OBJ_68 /* ParagraphStyleCollection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParagraphStyleCollection.swift; sourceTree = ""; }; 297 | OBJ_70 /* BlockBackgroundColorAttribute.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlockBackgroundColorAttribute.swift; sourceTree = ""; }; 298 | OBJ_71 /* QuoteStripeAttribute.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuoteStripeAttribute.swift; sourceTree = ""; }; 299 | OBJ_72 /* ThematicBreakAttribute.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThematicBreakAttribute.swift; sourceTree = ""; }; 300 | OBJ_75 /* CGPoint+Translate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CGPoint+Translate.swift"; sourceTree = ""; }; 301 | OBJ_76 /* CGRect+Helpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CGRect+Helpers.swift"; sourceTree = ""; }; 302 | OBJ_77 /* NSAttributedString+Helpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSAttributedString+Helpers.swift"; sourceTree = ""; }; 303 | OBJ_78 /* NSMutableAttributedString+Attributes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSMutableAttributedString+Attributes.swift"; sourceTree = ""; }; 304 | OBJ_79 /* UIFont+Traits.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIFont+Traits.swift"; sourceTree = ""; }; 305 | OBJ_80 /* ListItemParagraphStyler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListItemParagraphStyler.swift; sourceTree = ""; }; 306 | OBJ_82 /* DownDebugLayoutManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DownDebugLayoutManager.swift; sourceTree = ""; }; 307 | OBJ_83 /* DownLayoutManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DownLayoutManager.swift; sourceTree = ""; }; 308 | OBJ_85 /* CodeBlockOptions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CodeBlockOptions.swift; sourceTree = ""; }; 309 | OBJ_86 /* ListItemOptions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListItemOptions.swift; sourceTree = ""; }; 310 | OBJ_87 /* QuoteStripeOptions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuoteStripeOptions.swift; sourceTree = ""; }; 311 | OBJ_88 /* ThematicBreakOptions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThematicBreakOptions.swift; sourceTree = ""; }; 312 | OBJ_90 /* DownStyler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DownStyler.swift; sourceTree = ""; }; 313 | OBJ_91 /* DownStylerConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DownStylerConfiguration.swift; sourceTree = ""; }; 314 | OBJ_92 /* Styler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Styler.swift; sourceTree = ""; }; 315 | OBJ_94 /* DownDebugTextView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DownDebugTextView.swift; sourceTree = ""; }; 316 | OBJ_95 /* DownTextView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DownTextView.swift; sourceTree = ""; }; 317 | OBJ_97 /* AttributedStringVisitor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttributedStringVisitor.swift; sourceTree = ""; }; 318 | OBJ_98 /* DebugVisitor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DebugVisitor.swift; sourceTree = ""; }; 319 | OBJ_99 /* ListItemPrefixGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListItemPrefixGenerator.swift; sourceTree = ""; }; 320 | "Parma::Parma::Product" /* Parma.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Parma.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 321 | "Parma::ParmaTests::Product" /* ParmaTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; path = ParmaTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 322 | /* End PBXFileReference section */ 323 | 324 | /* Begin PBXFrameworksBuildPhase section */ 325 | OBJ_232 /* Frameworks */ = { 326 | isa = PBXFrameworksBuildPhase; 327 | buildActionMask = 0; 328 | files = ( 329 | OBJ_233 /* libcmark.framework in Frameworks */, 330 | ); 331 | runOnlyForDeploymentPostprocessing = 0; 332 | }; 333 | OBJ_268 /* Frameworks */ = { 334 | isa = PBXFrameworksBuildPhase; 335 | buildActionMask = 0; 336 | files = ( 337 | OBJ_269 /* Down.framework in Frameworks */, 338 | OBJ_270 /* libcmark.framework in Frameworks */, 339 | ); 340 | runOnlyForDeploymentPostprocessing = 0; 341 | }; 342 | OBJ_291 /* Frameworks */ = { 343 | isa = PBXFrameworksBuildPhase; 344 | buildActionMask = 0; 345 | files = ( 346 | OBJ_292 /* Parma.framework in Frameworks */, 347 | OBJ_293 /* Down.framework in Frameworks */, 348 | OBJ_294 /* libcmark.framework in Frameworks */, 349 | ); 350 | runOnlyForDeploymentPostprocessing = 0; 351 | }; 352 | OBJ_321 /* Frameworks */ = { 353 | isa = PBXFrameworksBuildPhase; 354 | buildActionMask = 0; 355 | files = ( 356 | ); 357 | runOnlyForDeploymentPostprocessing = 0; 358 | }; 359 | /* End PBXFrameworksBuildPhase section */ 360 | 361 | /* Begin PBXGroup section */ 362 | D7FE77A324EEBB020077853A /* Frameworks */ = { 363 | isa = PBXGroup; 364 | children = ( 365 | ); 366 | name = Frameworks; 367 | sourceTree = ""; 368 | }; 369 | OBJ_102 /* Enums & Options */ = { 370 | isa = PBXGroup; 371 | children = ( 372 | OBJ_103 /* DownErrors.swift */, 373 | OBJ_104 /* DownOptions.swift */, 374 | ); 375 | path = "Enums & Options"; 376 | sourceTree = ""; 377 | }; 378 | OBJ_105 /* Extensions */ = { 379 | isa = PBXGroup; 380 | children = ( 381 | OBJ_106 /* NSAttributedString+HTML.swift */, 382 | OBJ_107 /* String+ToHTML.swift */, 383 | ); 384 | path = Extensions; 385 | sourceTree = ""; 386 | }; 387 | OBJ_108 /* Renderers */ = { 388 | isa = PBXGroup; 389 | children = ( 390 | OBJ_109 /* DownASTRenderable.swift */, 391 | OBJ_110 /* DownAttributedStringRenderable.swift */, 392 | OBJ_111 /* DownCommonMarkRenderable.swift */, 393 | OBJ_112 /* DownGroffRenderable.swift */, 394 | OBJ_113 /* DownHTMLRenderable.swift */, 395 | OBJ_114 /* DownLaTeXRenderable.swift */, 396 | OBJ_115 /* DownRenderable.swift */, 397 | OBJ_116 /* DownXMLRenderable.swift */, 398 | ); 399 | path = Renderers; 400 | sourceTree = ""; 401 | }; 402 | OBJ_117 /* Views */ = { 403 | isa = PBXGroup; 404 | children = ( 405 | OBJ_118 /* DownView.swift */, 406 | ); 407 | path = Views; 408 | sourceTree = ""; 409 | }; 410 | OBJ_119 /* libcmark */ = { 411 | isa = PBXGroup; 412 | children = ( 413 | OBJ_120 /* blocks.c */, 414 | OBJ_121 /* buffer.c */, 415 | OBJ_122 /* cmark.c */, 416 | OBJ_123 /* cmark_ctype.c */, 417 | OBJ_124 /* commonmark.c */, 418 | OBJ_125 /* houdini_href_e.c */, 419 | OBJ_126 /* houdini_html_e.c */, 420 | OBJ_127 /* houdini_html_u.c */, 421 | OBJ_128 /* html.c */, 422 | OBJ_129 /* inlines.c */, 423 | OBJ_130 /* iterator.c */, 424 | OBJ_131 /* latex.c */, 425 | OBJ_132 /* man.c */, 426 | OBJ_133 /* node.c */, 427 | OBJ_134 /* references.c */, 428 | OBJ_135 /* render.c */, 429 | OBJ_136 /* scanners.c */, 430 | OBJ_137 /* utf8.c */, 431 | OBJ_138 /* xml.c */, 432 | OBJ_139 /* cmark_export.h */, 433 | OBJ_140 /* config.h */, 434 | OBJ_141 /* chunk.h */, 435 | OBJ_142 /* parser.h */, 436 | OBJ_143 /* scanners.h */, 437 | OBJ_144 /* node.h */, 438 | OBJ_145 /* cmark_version.h */, 439 | OBJ_146 /* cmark_ctype.h */, 440 | OBJ_147 /* buffer.h */, 441 | OBJ_148 /* cmark.h */, 442 | OBJ_149 /* inlines.h */, 443 | OBJ_150 /* houdini.h */, 444 | OBJ_151 /* iterator.h */, 445 | OBJ_152 /* utf8.h */, 446 | OBJ_153 /* references.h */, 447 | OBJ_154 /* render.h */, 448 | OBJ_155 /* module.modulemap */, 449 | ); 450 | name = libcmark; 451 | path = .build/checkouts/Down/Source/cmark; 452 | sourceTree = SOURCE_ROOT; 453 | }; 454 | OBJ_157 /* Products */ = { 455 | isa = PBXGroup; 456 | children = ( 457 | "Down::Down::Product" /* Down.framework */, 458 | "Parma::Parma::Product" /* Parma.framework */, 459 | "Down::libcmark::Product" /* libcmark.framework */, 460 | "Parma::ParmaTests::Product" /* ParmaTests.xctest */, 461 | ); 462 | name = Products; 463 | sourceTree = BUILT_PRODUCTS_DIR; 464 | }; 465 | OBJ_24 /* Element */ = { 466 | isa = PBXGroup; 467 | children = ( 468 | OBJ_25 /* Element.swift */, 469 | OBJ_26 /* HeadingLevel.swift */, 470 | OBJ_27 /* ListType.swift */, 471 | ); 472 | path = Element; 473 | sourceTree = ""; 474 | }; 475 | OBJ_30 /* Render */ = { 476 | isa = PBXGroup; 477 | children = ( 478 | OBJ_31 /* ParmaRender.swift */, 479 | OBJ_32 /* ParmaRenderable.swift */, 480 | ); 481 | path = Render; 482 | sourceTree = ""; 483 | }; 484 | OBJ_33 /* Tests */ = { 485 | isa = PBXGroup; 486 | children = ( 487 | OBJ_34 /* ParmaTests */, 488 | ); 489 | name = Tests; 490 | sourceTree = SOURCE_ROOT; 491 | }; 492 | OBJ_34 /* ParmaTests */ = { 493 | isa = PBXGroup; 494 | children = ( 495 | OBJ_35 /* ParmaTests.swift */, 496 | OBJ_36 /* XCTestManifests.swift */, 497 | ); 498 | name = ParmaTests; 499 | path = Tests/ParmaTests; 500 | sourceTree = SOURCE_ROOT; 501 | }; 502 | OBJ_37 /* Dependencies */ = { 503 | isa = PBXGroup; 504 | children = ( 505 | OBJ_38 /* Down 0.9.3 */, 506 | ); 507 | name = Dependencies; 508 | sourceTree = ""; 509 | }; 510 | OBJ_38 /* Down 0.9.3 */ = { 511 | isa = PBXGroup; 512 | children = ( 513 | OBJ_39 /* Down */, 514 | OBJ_119 /* libcmark */, 515 | OBJ_156 /* Package.swift */, 516 | ); 517 | name = "Down 0.9.3"; 518 | sourceTree = SOURCE_ROOT; 519 | }; 520 | OBJ_39 /* Down */ = { 521 | isa = PBXGroup; 522 | children = ( 523 | OBJ_40 /* AST */, 524 | OBJ_101 /* Down.swift */, 525 | OBJ_102 /* Enums & Options */, 526 | OBJ_105 /* Extensions */, 527 | OBJ_108 /* Renderers */, 528 | OBJ_117 /* Views */, 529 | ); 530 | name = Down; 531 | path = .build/checkouts/Down/Source; 532 | sourceTree = SOURCE_ROOT; 533 | }; 534 | OBJ_40 /* AST */ = { 535 | isa = PBXGroup; 536 | children = ( 537 | OBJ_41 /* Nodes */, 538 | OBJ_64 /* Styling */, 539 | OBJ_96 /* Visitors */, 540 | ); 541 | path = AST; 542 | sourceTree = ""; 543 | }; 544 | OBJ_41 /* Nodes */ = { 545 | isa = PBXGroup; 546 | children = ( 547 | OBJ_42 /* BaseNode.swift */, 548 | OBJ_43 /* BlockQuote.swift */, 549 | OBJ_44 /* Code.swift */, 550 | OBJ_45 /* CodeBlock.swift */, 551 | OBJ_46 /* CustomBlock.swift */, 552 | OBJ_47 /* CustomInline.swift */, 553 | OBJ_48 /* Document.swift */, 554 | OBJ_49 /* Emphasis.swift */, 555 | OBJ_50 /* Heading.swift */, 556 | OBJ_51 /* HtmlBlock.swift */, 557 | OBJ_52 /* HtmlInline.swift */, 558 | OBJ_53 /* Image.swift */, 559 | OBJ_54 /* Item.swift */, 560 | OBJ_55 /* LineBreak.swift */, 561 | OBJ_56 /* Link.swift */, 562 | OBJ_57 /* List.swift */, 563 | OBJ_58 /* Node.swift */, 564 | OBJ_59 /* Paragraph.swift */, 565 | OBJ_60 /* SoftBreak.swift */, 566 | OBJ_61 /* Strong.swift */, 567 | OBJ_62 /* Text.swift */, 568 | OBJ_63 /* ThematicBreak.swift */, 569 | ); 570 | path = Nodes; 571 | sourceTree = ""; 572 | }; 573 | OBJ_5 = { 574 | isa = PBXGroup; 575 | children = ( 576 | OBJ_6 /* Package.swift */, 577 | OBJ_7 /* Sources */, 578 | OBJ_33 /* Tests */, 579 | OBJ_37 /* Dependencies */, 580 | OBJ_157 /* Products */, 581 | OBJ_162 /* LICENSE */, 582 | OBJ_163 /* README.md */, 583 | D7FE77A324EEBB020077853A /* Frameworks */, 584 | ); 585 | sourceTree = ""; 586 | }; 587 | OBJ_64 /* Styling */ = { 588 | isa = PBXGroup; 589 | children = ( 590 | OBJ_65 /* Attribute Collections */, 591 | OBJ_69 /* Custom Attributes */, 592 | OBJ_73 /* Helpers */, 593 | OBJ_81 /* Layout Managers */, 594 | OBJ_84 /* Options */, 595 | OBJ_89 /* Stylers */, 596 | OBJ_93 /* Text Views */, 597 | ); 598 | path = Styling; 599 | sourceTree = ""; 600 | }; 601 | OBJ_65 /* Attribute Collections */ = { 602 | isa = PBXGroup; 603 | children = ( 604 | OBJ_66 /* ColorCollection.swift */, 605 | OBJ_67 /* FontCollection.swift */, 606 | OBJ_68 /* ParagraphStyleCollection.swift */, 607 | ); 608 | path = "Attribute Collections"; 609 | sourceTree = ""; 610 | }; 611 | OBJ_69 /* Custom Attributes */ = { 612 | isa = PBXGroup; 613 | children = ( 614 | OBJ_70 /* BlockBackgroundColorAttribute.swift */, 615 | OBJ_71 /* QuoteStripeAttribute.swift */, 616 | OBJ_72 /* ThematicBreakAttribute.swift */, 617 | ); 618 | path = "Custom Attributes"; 619 | sourceTree = ""; 620 | }; 621 | OBJ_7 /* Sources */ = { 622 | isa = PBXGroup; 623 | children = ( 624 | OBJ_8 /* Parma */, 625 | ); 626 | name = Sources; 627 | sourceTree = SOURCE_ROOT; 628 | }; 629 | OBJ_73 /* Helpers */ = { 630 | isa = PBXGroup; 631 | children = ( 632 | OBJ_74 /* Extensions */, 633 | OBJ_80 /* ListItemParagraphStyler.swift */, 634 | ); 635 | path = Helpers; 636 | sourceTree = ""; 637 | }; 638 | OBJ_74 /* Extensions */ = { 639 | isa = PBXGroup; 640 | children = ( 641 | OBJ_75 /* CGPoint+Translate.swift */, 642 | OBJ_76 /* CGRect+Helpers.swift */, 643 | OBJ_77 /* NSAttributedString+Helpers.swift */, 644 | OBJ_78 /* NSMutableAttributedString+Attributes.swift */, 645 | OBJ_79 /* UIFont+Traits.swift */, 646 | ); 647 | path = Extensions; 648 | sourceTree = ""; 649 | }; 650 | OBJ_8 /* Parma */ = { 651 | isa = PBXGroup; 652 | children = ( 653 | OBJ_28 /* Parma.swift */, 654 | OBJ_29 /* ParmaCore.swift */, 655 | OBJ_9 /* Composer */, 656 | OBJ_24 /* Element */, 657 | OBJ_30 /* Render */, 658 | ); 659 | name = Parma; 660 | path = Sources/Parma; 661 | sourceTree = SOURCE_ROOT; 662 | }; 663 | OBJ_81 /* Layout Managers */ = { 664 | isa = PBXGroup; 665 | children = ( 666 | OBJ_82 /* DownDebugLayoutManager.swift */, 667 | OBJ_83 /* DownLayoutManager.swift */, 668 | ); 669 | path = "Layout Managers"; 670 | sourceTree = ""; 671 | }; 672 | OBJ_84 /* Options */ = { 673 | isa = PBXGroup; 674 | children = ( 675 | OBJ_85 /* CodeBlockOptions.swift */, 676 | OBJ_86 /* ListItemOptions.swift */, 677 | OBJ_87 /* QuoteStripeOptions.swift */, 678 | OBJ_88 /* ThematicBreakOptions.swift */, 679 | ); 680 | path = Options; 681 | sourceTree = ""; 682 | }; 683 | OBJ_89 /* Stylers */ = { 684 | isa = PBXGroup; 685 | children = ( 686 | OBJ_90 /* DownStyler.swift */, 687 | OBJ_91 /* DownStylerConfiguration.swift */, 688 | OBJ_92 /* Styler.swift */, 689 | ); 690 | path = Stylers; 691 | sourceTree = ""; 692 | }; 693 | OBJ_9 /* Composer */ = { 694 | isa = PBXGroup; 695 | children = ( 696 | OBJ_10 /* CodeElementComposer.swift */, 697 | OBJ_11 /* Composer.swift */, 698 | OBJ_12 /* ComposingContext.swift */, 699 | OBJ_13 /* ElementComposer.swift */, 700 | OBJ_14 /* EmphasisElementComposer.swift */, 701 | OBJ_15 /* HeadingElementComposer.swift */, 702 | OBJ_16 /* ImageElementComposer.swift */, 703 | OBJ_17 /* LinkElementComposer.swift */, 704 | OBJ_18 /* ListElementComposer.swift */, 705 | OBJ_19 /* ListItemElementComposer.swift */, 706 | OBJ_20 /* ParagraphElementComposer.swift */, 707 | OBJ_21 /* PlainTextComposer.swift */, 708 | OBJ_22 /* StrongElementComposer.swift */, 709 | OBJ_23 /* UnknownElementComposer.swift */, 710 | ); 711 | path = Composer; 712 | sourceTree = ""; 713 | }; 714 | OBJ_93 /* Text Views */ = { 715 | isa = PBXGroup; 716 | children = ( 717 | OBJ_94 /* DownDebugTextView.swift */, 718 | OBJ_95 /* DownTextView.swift */, 719 | ); 720 | path = "Text Views"; 721 | sourceTree = ""; 722 | }; 723 | OBJ_96 /* Visitors */ = { 724 | isa = PBXGroup; 725 | children = ( 726 | OBJ_97 /* AttributedStringVisitor.swift */, 727 | OBJ_98 /* DebugVisitor.swift */, 728 | OBJ_99 /* ListItemPrefixGenerator.swift */, 729 | OBJ_100 /* Vistor.swift */, 730 | ); 731 | path = Visitors; 732 | sourceTree = ""; 733 | }; 734 | /* End PBXGroup section */ 735 | 736 | /* Begin PBXNativeTarget section */ 737 | "Down::Down" /* Down */ = { 738 | isa = PBXNativeTarget; 739 | buildConfigurationList = OBJ_165 /* Build configuration list for PBXNativeTarget "Down" */; 740 | buildPhases = ( 741 | OBJ_168 /* Sources */, 742 | OBJ_232 /* Frameworks */, 743 | ); 744 | buildRules = ( 745 | ); 746 | dependencies = ( 747 | OBJ_234 /* PBXTargetDependency */, 748 | ); 749 | name = Down; 750 | productName = Down; 751 | productReference = "Down::Down::Product" /* Down.framework */; 752 | productType = "com.apple.product-type.framework"; 753 | }; 754 | "Down::SwiftPMPackageDescription" /* DownPackageDescription */ = { 755 | isa = PBXNativeTarget; 756 | buildConfigurationList = OBJ_237 /* Build configuration list for PBXNativeTarget "DownPackageDescription" */; 757 | buildPhases = ( 758 | OBJ_240 /* Sources */, 759 | ); 760 | buildRules = ( 761 | ); 762 | dependencies = ( 763 | ); 764 | name = DownPackageDescription; 765 | productName = DownPackageDescription; 766 | productType = "com.apple.product-type.framework"; 767 | }; 768 | "Down::libcmark" /* libcmark */ = { 769 | isa = PBXNativeTarget; 770 | buildConfigurationList = OBJ_298 /* Build configuration list for PBXNativeTarget "libcmark" */; 771 | buildPhases = ( 772 | OBJ_301 /* Sources */, 773 | OBJ_321 /* Frameworks */, 774 | ); 775 | buildRules = ( 776 | ); 777 | dependencies = ( 778 | ); 779 | name = libcmark; 780 | productName = libcmark; 781 | productReference = "Down::libcmark::Product" /* libcmark.framework */; 782 | productType = "com.apple.product-type.framework"; 783 | }; 784 | "Parma::Parma" /* Parma */ = { 785 | isa = PBXNativeTarget; 786 | buildConfigurationList = OBJ_243 /* Build configuration list for PBXNativeTarget "Parma" */; 787 | buildPhases = ( 788 | OBJ_246 /* Sources */, 789 | OBJ_268 /* Frameworks */, 790 | ); 791 | buildRules = ( 792 | ); 793 | dependencies = ( 794 | OBJ_271 /* PBXTargetDependency */, 795 | OBJ_272 /* PBXTargetDependency */, 796 | ); 797 | name = Parma; 798 | productName = Parma; 799 | productReference = "Parma::Parma::Product" /* Parma.framework */; 800 | productType = "com.apple.product-type.framework"; 801 | }; 802 | "Parma::ParmaTests" /* ParmaTests */ = { 803 | isa = PBXNativeTarget; 804 | buildConfigurationList = OBJ_285 /* Build configuration list for PBXNativeTarget "ParmaTests" */; 805 | buildPhases = ( 806 | OBJ_288 /* Sources */, 807 | OBJ_291 /* Frameworks */, 808 | ); 809 | buildRules = ( 810 | ); 811 | dependencies = ( 812 | OBJ_295 /* PBXTargetDependency */, 813 | OBJ_296 /* PBXTargetDependency */, 814 | OBJ_297 /* PBXTargetDependency */, 815 | ); 816 | name = ParmaTests; 817 | productName = ParmaTests; 818 | productReference = "Parma::ParmaTests::Product" /* ParmaTests.xctest */; 819 | productType = "com.apple.product-type.bundle.unit-test"; 820 | }; 821 | "Parma::SwiftPMPackageDescription" /* ParmaPackageDescription */ = { 822 | isa = PBXNativeTarget; 823 | buildConfigurationList = OBJ_274 /* Build configuration list for PBXNativeTarget "ParmaPackageDescription" */; 824 | buildPhases = ( 825 | OBJ_277 /* Sources */, 826 | ); 827 | buildRules = ( 828 | ); 829 | dependencies = ( 830 | ); 831 | name = ParmaPackageDescription; 832 | productName = ParmaPackageDescription; 833 | productType = "com.apple.product-type.framework"; 834 | }; 835 | /* End PBXNativeTarget section */ 836 | 837 | /* Begin PBXProject section */ 838 | OBJ_1 /* Project object */ = { 839 | isa = PBXProject; 840 | attributes = { 841 | LastSwiftMigration = 9999; 842 | LastSwiftUpdateCheck = 1200; 843 | LastUpgradeCheck = 9999; 844 | }; 845 | buildConfigurationList = OBJ_2 /* Build configuration list for PBXProject "Parma" */; 846 | compatibilityVersion = "Xcode 3.2"; 847 | developmentRegion = en; 848 | hasScannedForEncodings = 0; 849 | knownRegions = ( 850 | en, 851 | ); 852 | mainGroup = OBJ_5; 853 | productRefGroup = OBJ_157 /* Products */; 854 | projectDirPath = ""; 855 | projectRoot = ""; 856 | targets = ( 857 | "Parma::Parma" /* Parma */, 858 | "Down::Down" /* Down */, 859 | "Down::SwiftPMPackageDescription" /* DownPackageDescription */, 860 | "Parma::SwiftPMPackageDescription" /* ParmaPackageDescription */, 861 | "Parma::ParmaPackageTests::ProductTarget" /* ParmaPackageTests */, 862 | "Parma::ParmaTests" /* ParmaTests */, 863 | "Down::libcmark" /* libcmark */, 864 | ); 865 | }; 866 | /* End PBXProject section */ 867 | 868 | /* Begin PBXSourcesBuildPhase section */ 869 | OBJ_168 /* Sources */ = { 870 | isa = PBXSourcesBuildPhase; 871 | buildActionMask = 0; 872 | files = ( 873 | OBJ_169 /* BaseNode.swift in Sources */, 874 | OBJ_170 /* BlockQuote.swift in Sources */, 875 | OBJ_171 /* Code.swift in Sources */, 876 | OBJ_172 /* CodeBlock.swift in Sources */, 877 | OBJ_173 /* CustomBlock.swift in Sources */, 878 | OBJ_174 /* CustomInline.swift in Sources */, 879 | OBJ_175 /* Document.swift in Sources */, 880 | OBJ_176 /* Emphasis.swift in Sources */, 881 | OBJ_177 /* Heading.swift in Sources */, 882 | OBJ_178 /* HtmlBlock.swift in Sources */, 883 | OBJ_179 /* HtmlInline.swift in Sources */, 884 | OBJ_180 /* Image.swift in Sources */, 885 | OBJ_181 /* Item.swift in Sources */, 886 | OBJ_182 /* LineBreak.swift in Sources */, 887 | OBJ_183 /* Link.swift in Sources */, 888 | OBJ_184 /* List.swift in Sources */, 889 | OBJ_185 /* Node.swift in Sources */, 890 | OBJ_186 /* Paragraph.swift in Sources */, 891 | OBJ_187 /* SoftBreak.swift in Sources */, 892 | OBJ_188 /* Strong.swift in Sources */, 893 | OBJ_189 /* Text.swift in Sources */, 894 | OBJ_190 /* ThematicBreak.swift in Sources */, 895 | OBJ_191 /* ColorCollection.swift in Sources */, 896 | OBJ_192 /* FontCollection.swift in Sources */, 897 | OBJ_193 /* ParagraphStyleCollection.swift in Sources */, 898 | OBJ_194 /* BlockBackgroundColorAttribute.swift in Sources */, 899 | OBJ_195 /* QuoteStripeAttribute.swift in Sources */, 900 | OBJ_196 /* ThematicBreakAttribute.swift in Sources */, 901 | OBJ_197 /* CGPoint+Translate.swift in Sources */, 902 | OBJ_198 /* CGRect+Helpers.swift in Sources */, 903 | OBJ_199 /* NSAttributedString+Helpers.swift in Sources */, 904 | OBJ_200 /* NSMutableAttributedString+Attributes.swift in Sources */, 905 | OBJ_201 /* UIFont+Traits.swift in Sources */, 906 | OBJ_202 /* ListItemParagraphStyler.swift in Sources */, 907 | OBJ_203 /* DownDebugLayoutManager.swift in Sources */, 908 | OBJ_204 /* DownLayoutManager.swift in Sources */, 909 | OBJ_205 /* CodeBlockOptions.swift in Sources */, 910 | OBJ_206 /* ListItemOptions.swift in Sources */, 911 | OBJ_207 /* QuoteStripeOptions.swift in Sources */, 912 | OBJ_208 /* ThematicBreakOptions.swift in Sources */, 913 | OBJ_209 /* DownStyler.swift in Sources */, 914 | OBJ_210 /* DownStylerConfiguration.swift in Sources */, 915 | OBJ_211 /* Styler.swift in Sources */, 916 | OBJ_212 /* DownDebugTextView.swift in Sources */, 917 | OBJ_213 /* DownTextView.swift in Sources */, 918 | OBJ_214 /* AttributedStringVisitor.swift in Sources */, 919 | OBJ_215 /* DebugVisitor.swift in Sources */, 920 | OBJ_216 /* ListItemPrefixGenerator.swift in Sources */, 921 | OBJ_217 /* Vistor.swift in Sources */, 922 | OBJ_218 /* Down.swift in Sources */, 923 | OBJ_219 /* DownErrors.swift in Sources */, 924 | OBJ_220 /* DownOptions.swift in Sources */, 925 | OBJ_221 /* NSAttributedString+HTML.swift in Sources */, 926 | OBJ_222 /* String+ToHTML.swift in Sources */, 927 | OBJ_223 /* DownASTRenderable.swift in Sources */, 928 | OBJ_224 /* DownAttributedStringRenderable.swift in Sources */, 929 | OBJ_225 /* DownCommonMarkRenderable.swift in Sources */, 930 | OBJ_226 /* DownGroffRenderable.swift in Sources */, 931 | OBJ_227 /* DownHTMLRenderable.swift in Sources */, 932 | OBJ_228 /* DownLaTeXRenderable.swift in Sources */, 933 | OBJ_229 /* DownRenderable.swift in Sources */, 934 | OBJ_230 /* DownXMLRenderable.swift in Sources */, 935 | OBJ_231 /* DownView.swift in Sources */, 936 | ); 937 | runOnlyForDeploymentPostprocessing = 0; 938 | }; 939 | OBJ_240 /* Sources */ = { 940 | isa = PBXSourcesBuildPhase; 941 | buildActionMask = 0; 942 | files = ( 943 | OBJ_241 /* Package.swift in Sources */, 944 | ); 945 | runOnlyForDeploymentPostprocessing = 0; 946 | }; 947 | OBJ_246 /* Sources */ = { 948 | isa = PBXSourcesBuildPhase; 949 | buildActionMask = 0; 950 | files = ( 951 | OBJ_247 /* CodeElementComposer.swift in Sources */, 952 | OBJ_248 /* Composer.swift in Sources */, 953 | OBJ_249 /* ComposingContext.swift in Sources */, 954 | OBJ_250 /* ElementComposer.swift in Sources */, 955 | OBJ_251 /* EmphasisElementComposer.swift in Sources */, 956 | OBJ_252 /* HeadingElementComposer.swift in Sources */, 957 | OBJ_253 /* ImageElementComposer.swift in Sources */, 958 | OBJ_254 /* LinkElementComposer.swift in Sources */, 959 | OBJ_255 /* ListElementComposer.swift in Sources */, 960 | OBJ_256 /* ListItemElementComposer.swift in Sources */, 961 | OBJ_257 /* ParagraphElementComposer.swift in Sources */, 962 | OBJ_258 /* PlainTextComposer.swift in Sources */, 963 | OBJ_259 /* StrongElementComposer.swift in Sources */, 964 | OBJ_260 /* UnknownElementComposer.swift in Sources */, 965 | OBJ_261 /* Element.swift in Sources */, 966 | OBJ_262 /* HeadingLevel.swift in Sources */, 967 | OBJ_263 /* ListType.swift in Sources */, 968 | OBJ_264 /* Parma.swift in Sources */, 969 | OBJ_265 /* ParmaCore.swift in Sources */, 970 | OBJ_266 /* ParmaRender.swift in Sources */, 971 | OBJ_267 /* ParmaRenderable.swift in Sources */, 972 | ); 973 | runOnlyForDeploymentPostprocessing = 0; 974 | }; 975 | OBJ_277 /* Sources */ = { 976 | isa = PBXSourcesBuildPhase; 977 | buildActionMask = 0; 978 | files = ( 979 | OBJ_278 /* Package.swift in Sources */, 980 | ); 981 | runOnlyForDeploymentPostprocessing = 0; 982 | }; 983 | OBJ_288 /* Sources */ = { 984 | isa = PBXSourcesBuildPhase; 985 | buildActionMask = 0; 986 | files = ( 987 | OBJ_289 /* ParmaTests.swift in Sources */, 988 | OBJ_290 /* XCTestManifests.swift in Sources */, 989 | ); 990 | runOnlyForDeploymentPostprocessing = 0; 991 | }; 992 | OBJ_301 /* Sources */ = { 993 | isa = PBXSourcesBuildPhase; 994 | buildActionMask = 0; 995 | files = ( 996 | OBJ_302 /* blocks.c in Sources */, 997 | OBJ_303 /* buffer.c in Sources */, 998 | OBJ_304 /* cmark.c in Sources */, 999 | OBJ_305 /* cmark_ctype.c in Sources */, 1000 | OBJ_306 /* commonmark.c in Sources */, 1001 | OBJ_307 /* houdini_href_e.c in Sources */, 1002 | OBJ_308 /* houdini_html_e.c in Sources */, 1003 | OBJ_309 /* houdini_html_u.c in Sources */, 1004 | OBJ_310 /* html.c in Sources */, 1005 | OBJ_311 /* inlines.c in Sources */, 1006 | OBJ_312 /* iterator.c in Sources */, 1007 | OBJ_313 /* latex.c in Sources */, 1008 | OBJ_314 /* man.c in Sources */, 1009 | OBJ_315 /* node.c in Sources */, 1010 | OBJ_316 /* references.c in Sources */, 1011 | OBJ_317 /* render.c in Sources */, 1012 | OBJ_318 /* scanners.c in Sources */, 1013 | OBJ_319 /* utf8.c in Sources */, 1014 | OBJ_320 /* xml.c in Sources */, 1015 | ); 1016 | runOnlyForDeploymentPostprocessing = 0; 1017 | }; 1018 | /* End PBXSourcesBuildPhase section */ 1019 | 1020 | /* Begin PBXTargetDependency section */ 1021 | OBJ_234 /* PBXTargetDependency */ = { 1022 | isa = PBXTargetDependency; 1023 | target = "Down::libcmark" /* libcmark */; 1024 | targetProxy = D709BF4E24E97CC80070BEE2 /* PBXContainerItemProxy */; 1025 | }; 1026 | OBJ_271 /* PBXTargetDependency */ = { 1027 | isa = PBXTargetDependency; 1028 | target = "Down::Down" /* Down */; 1029 | targetProxy = D709BF4D24E97CC80070BEE2 /* PBXContainerItemProxy */; 1030 | }; 1031 | OBJ_272 /* PBXTargetDependency */ = { 1032 | isa = PBXTargetDependency; 1033 | target = "Down::libcmark" /* libcmark */; 1034 | targetProxy = D709BF4F24E97CC80070BEE2 /* PBXContainerItemProxy */; 1035 | }; 1036 | OBJ_283 /* PBXTargetDependency */ = { 1037 | isa = PBXTargetDependency; 1038 | target = "Parma::ParmaTests" /* ParmaTests */; 1039 | targetProxy = D709BF5324E97CCA0070BEE2 /* PBXContainerItemProxy */; 1040 | }; 1041 | OBJ_295 /* PBXTargetDependency */ = { 1042 | isa = PBXTargetDependency; 1043 | target = "Parma::Parma" /* Parma */; 1044 | targetProxy = D709BF5024E97CC80070BEE2 /* PBXContainerItemProxy */; 1045 | }; 1046 | OBJ_296 /* PBXTargetDependency */ = { 1047 | isa = PBXTargetDependency; 1048 | target = "Down::Down" /* Down */; 1049 | targetProxy = D709BF5124E97CC80070BEE2 /* PBXContainerItemProxy */; 1050 | }; 1051 | OBJ_297 /* PBXTargetDependency */ = { 1052 | isa = PBXTargetDependency; 1053 | target = "Down::libcmark" /* libcmark */; 1054 | targetProxy = D709BF5224E97CC80070BEE2 /* PBXContainerItemProxy */; 1055 | }; 1056 | /* End PBXTargetDependency section */ 1057 | 1058 | /* Begin XCBuildConfiguration section */ 1059 | OBJ_166 /* Debug */ = { 1060 | isa = XCBuildConfiguration; 1061 | buildSettings = { 1062 | ENABLE_TESTABILITY = YES; 1063 | FRAMEWORK_SEARCH_PATHS = ( 1064 | "$(inherited)", 1065 | "$(PLATFORM_DIR)/Developer/Library/Frameworks", 1066 | ); 1067 | HEADER_SEARCH_PATHS = ( 1068 | "$(inherited)", 1069 | "$(SRCROOT)/.build/checkouts/Down/Source/cmark", 1070 | "$(SRCROOT)/Parma.xcodeproj/GeneratedModuleMap/libcmark", 1071 | ); 1072 | INFOPLIST_FILE = Parma.xcodeproj/Down_Info.plist; 1073 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 1074 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) $(TOOLCHAIN_DIR)/usr/lib/swift/macosx"; 1075 | MACOSX_DEPLOYMENT_TARGET = 10.11; 1076 | OTHER_CFLAGS = "$(inherited)"; 1077 | OTHER_LDFLAGS = "$(inherited)"; 1078 | OTHER_SWIFT_FLAGS = "$(inherited) -Xcc -fmodule-map-file=$(SRCROOT)/Parma.xcodeproj/GeneratedModuleMap/libcmark/module.modulemap"; 1079 | PRODUCT_BUNDLE_IDENTIFIER = Down; 1080 | PRODUCT_MODULE_NAME = "$(TARGET_NAME:c99extidentifier)"; 1081 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; 1082 | SKIP_INSTALL = YES; 1083 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited)"; 1084 | SWIFT_VERSION = 5.0; 1085 | TARGET_NAME = Down; 1086 | TVOS_DEPLOYMENT_TARGET = 9.0; 1087 | WATCHOS_DEPLOYMENT_TARGET = 2.0; 1088 | }; 1089 | name = Debug; 1090 | }; 1091 | OBJ_167 /* Release */ = { 1092 | isa = XCBuildConfiguration; 1093 | buildSettings = { 1094 | ENABLE_TESTABILITY = YES; 1095 | FRAMEWORK_SEARCH_PATHS = ( 1096 | "$(inherited)", 1097 | "$(PLATFORM_DIR)/Developer/Library/Frameworks", 1098 | ); 1099 | HEADER_SEARCH_PATHS = ( 1100 | "$(inherited)", 1101 | "$(SRCROOT)/.build/checkouts/Down/Source/cmark", 1102 | "$(SRCROOT)/Parma.xcodeproj/GeneratedModuleMap/libcmark", 1103 | ); 1104 | INFOPLIST_FILE = Parma.xcodeproj/Down_Info.plist; 1105 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 1106 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) $(TOOLCHAIN_DIR)/usr/lib/swift/macosx"; 1107 | MACOSX_DEPLOYMENT_TARGET = 10.11; 1108 | OTHER_CFLAGS = "$(inherited)"; 1109 | OTHER_LDFLAGS = "$(inherited)"; 1110 | OTHER_SWIFT_FLAGS = "$(inherited) -Xcc -fmodule-map-file=$(SRCROOT)/Parma.xcodeproj/GeneratedModuleMap/libcmark/module.modulemap"; 1111 | PRODUCT_BUNDLE_IDENTIFIER = Down; 1112 | PRODUCT_MODULE_NAME = "$(TARGET_NAME:c99extidentifier)"; 1113 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; 1114 | SKIP_INSTALL = YES; 1115 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited)"; 1116 | SWIFT_VERSION = 5.0; 1117 | TARGET_NAME = Down; 1118 | TVOS_DEPLOYMENT_TARGET = 9.0; 1119 | WATCHOS_DEPLOYMENT_TARGET = 2.0; 1120 | }; 1121 | name = Release; 1122 | }; 1123 | OBJ_238 /* Debug */ = { 1124 | isa = XCBuildConfiguration; 1125 | buildSettings = { 1126 | IPHONEOS_DEPLOYMENT_TARGET = 13.0; 1127 | LD = /usr/bin/true; 1128 | OTHER_SWIFT_FLAGS = "-swift-version 5 -I $(TOOLCHAIN_DIR)/usr/lib/swift/pm/4_2 -sdk /Applications/Xcode-beta.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.0.sdk -package-description-version 5.1.0"; 1129 | SWIFT_VERSION = 5.0; 1130 | TVOS_DEPLOYMENT_TARGET = 13.0; 1131 | }; 1132 | name = Debug; 1133 | }; 1134 | OBJ_239 /* Release */ = { 1135 | isa = XCBuildConfiguration; 1136 | buildSettings = { 1137 | IPHONEOS_DEPLOYMENT_TARGET = 13.0; 1138 | LD = /usr/bin/true; 1139 | OTHER_SWIFT_FLAGS = "-swift-version 5 -I $(TOOLCHAIN_DIR)/usr/lib/swift/pm/4_2 -sdk /Applications/Xcode-beta.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.0.sdk -package-description-version 5.1.0"; 1140 | SWIFT_VERSION = 5.0; 1141 | TVOS_DEPLOYMENT_TARGET = 13.0; 1142 | }; 1143 | name = Release; 1144 | }; 1145 | OBJ_244 /* Debug */ = { 1146 | isa = XCBuildConfiguration; 1147 | buildSettings = { 1148 | ENABLE_TESTABILITY = YES; 1149 | FRAMEWORK_SEARCH_PATHS = ( 1150 | "$(inherited)", 1151 | "$(PLATFORM_DIR)/Developer/Library/Frameworks", 1152 | ); 1153 | HEADER_SEARCH_PATHS = ( 1154 | "$(inherited)", 1155 | "$(SRCROOT)/.build/checkouts/Down/Source/cmark", 1156 | "$(SRCROOT)/Parma.xcodeproj/GeneratedModuleMap/libcmark", 1157 | ); 1158 | INFOPLIST_FILE = Parma.xcodeproj/Parma_Info.plist; 1159 | IPHONEOS_DEPLOYMENT_TARGET = 13.0; 1160 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) $(TOOLCHAIN_DIR)/usr/lib/swift/macosx"; 1161 | MACOSX_DEPLOYMENT_TARGET = 10.15; 1162 | OTHER_CFLAGS = "$(inherited)"; 1163 | OTHER_LDFLAGS = "$(inherited)"; 1164 | OTHER_SWIFT_FLAGS = "$(inherited) -Xcc -fmodule-map-file=$(SRCROOT)/Parma.xcodeproj/GeneratedModuleMap/libcmark/module.modulemap"; 1165 | PRODUCT_BUNDLE_IDENTIFIER = Parma; 1166 | PRODUCT_MODULE_NAME = "$(TARGET_NAME:c99extidentifier)"; 1167 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; 1168 | SKIP_INSTALL = YES; 1169 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited)"; 1170 | SWIFT_VERSION = 5.0; 1171 | TARGET_NAME = Parma; 1172 | TVOS_DEPLOYMENT_TARGET = 9.0; 1173 | WATCHOS_DEPLOYMENT_TARGET = 2.0; 1174 | }; 1175 | name = Debug; 1176 | }; 1177 | OBJ_245 /* Release */ = { 1178 | isa = XCBuildConfiguration; 1179 | buildSettings = { 1180 | ENABLE_TESTABILITY = YES; 1181 | FRAMEWORK_SEARCH_PATHS = ( 1182 | "$(inherited)", 1183 | "$(PLATFORM_DIR)/Developer/Library/Frameworks", 1184 | ); 1185 | HEADER_SEARCH_PATHS = ( 1186 | "$(inherited)", 1187 | "$(SRCROOT)/.build/checkouts/Down/Source/cmark", 1188 | "$(SRCROOT)/Parma.xcodeproj/GeneratedModuleMap/libcmark", 1189 | ); 1190 | INFOPLIST_FILE = Parma.xcodeproj/Parma_Info.plist; 1191 | IPHONEOS_DEPLOYMENT_TARGET = 13.0; 1192 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) $(TOOLCHAIN_DIR)/usr/lib/swift/macosx"; 1193 | MACOSX_DEPLOYMENT_TARGET = 10.15; 1194 | OTHER_CFLAGS = "$(inherited)"; 1195 | OTHER_LDFLAGS = "$(inherited)"; 1196 | OTHER_SWIFT_FLAGS = "$(inherited) -Xcc -fmodule-map-file=$(SRCROOT)/Parma.xcodeproj/GeneratedModuleMap/libcmark/module.modulemap"; 1197 | PRODUCT_BUNDLE_IDENTIFIER = Parma; 1198 | PRODUCT_MODULE_NAME = "$(TARGET_NAME:c99extidentifier)"; 1199 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; 1200 | SKIP_INSTALL = YES; 1201 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited)"; 1202 | SWIFT_VERSION = 5.0; 1203 | TARGET_NAME = Parma; 1204 | TVOS_DEPLOYMENT_TARGET = 9.0; 1205 | WATCHOS_DEPLOYMENT_TARGET = 2.0; 1206 | }; 1207 | name = Release; 1208 | }; 1209 | OBJ_275 /* Debug */ = { 1210 | isa = XCBuildConfiguration; 1211 | buildSettings = { 1212 | IPHONEOS_DEPLOYMENT_TARGET = 13.0; 1213 | LD = /usr/bin/true; 1214 | OTHER_SWIFT_FLAGS = "-swift-version 5 -I $(TOOLCHAIN_DIR)/usr/lib/swift/pm/4_2 -sdk /Applications/Xcode-beta.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.0.sdk -package-description-version 5.3.0"; 1215 | SWIFT_VERSION = 5.0; 1216 | TVOS_DEPLOYMENT_TARGET = 13.0; 1217 | }; 1218 | name = Debug; 1219 | }; 1220 | OBJ_276 /* Release */ = { 1221 | isa = XCBuildConfiguration; 1222 | buildSettings = { 1223 | IPHONEOS_DEPLOYMENT_TARGET = 13.0; 1224 | LD = /usr/bin/true; 1225 | OTHER_SWIFT_FLAGS = "-swift-version 5 -I $(TOOLCHAIN_DIR)/usr/lib/swift/pm/4_2 -sdk /Applications/Xcode-beta.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.0.sdk -package-description-version 5.3.0"; 1226 | SWIFT_VERSION = 5.0; 1227 | TVOS_DEPLOYMENT_TARGET = 13.0; 1228 | }; 1229 | name = Release; 1230 | }; 1231 | OBJ_281 /* Debug */ = { 1232 | isa = XCBuildConfiguration; 1233 | buildSettings = { 1234 | IPHONEOS_DEPLOYMENT_TARGET = 13.0; 1235 | TVOS_DEPLOYMENT_TARGET = 13.0; 1236 | }; 1237 | name = Debug; 1238 | }; 1239 | OBJ_282 /* Release */ = { 1240 | isa = XCBuildConfiguration; 1241 | buildSettings = { 1242 | IPHONEOS_DEPLOYMENT_TARGET = 13.0; 1243 | TVOS_DEPLOYMENT_TARGET = 13.0; 1244 | }; 1245 | name = Release; 1246 | }; 1247 | OBJ_286 /* Debug */ = { 1248 | isa = XCBuildConfiguration; 1249 | buildSettings = { 1250 | CLANG_ENABLE_MODULES = YES; 1251 | EMBEDDED_CONTENT_CONTAINS_SWIFT = YES; 1252 | FRAMEWORK_SEARCH_PATHS = ( 1253 | "$(inherited)", 1254 | "$(PLATFORM_DIR)/Developer/Library/Frameworks", 1255 | ); 1256 | HEADER_SEARCH_PATHS = ( 1257 | "$(inherited)", 1258 | "$(SRCROOT)/.build/checkouts/Down/Source/cmark", 1259 | "$(SRCROOT)/Parma.xcodeproj/GeneratedModuleMap/libcmark", 1260 | ); 1261 | INFOPLIST_FILE = Parma.xcodeproj/ParmaTests_Info.plist; 1262 | IPHONEOS_DEPLOYMENT_TARGET = 13.0; 1263 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @loader_path/../Frameworks @loader_path/Frameworks"; 1264 | MACOSX_DEPLOYMENT_TARGET = 11.0; 1265 | OTHER_CFLAGS = "$(inherited)"; 1266 | OTHER_LDFLAGS = "$(inherited)"; 1267 | OTHER_SWIFT_FLAGS = "$(inherited) -Xcc -fmodule-map-file=$(SRCROOT)/Parma.xcodeproj/GeneratedModuleMap/libcmark/module.modulemap"; 1268 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited)"; 1269 | SWIFT_VERSION = 5.0; 1270 | TARGET_NAME = ParmaTests; 1271 | TVOS_DEPLOYMENT_TARGET = 9.0; 1272 | WATCHOS_DEPLOYMENT_TARGET = 2.0; 1273 | }; 1274 | name = Debug; 1275 | }; 1276 | OBJ_287 /* Release */ = { 1277 | isa = XCBuildConfiguration; 1278 | buildSettings = { 1279 | CLANG_ENABLE_MODULES = YES; 1280 | EMBEDDED_CONTENT_CONTAINS_SWIFT = YES; 1281 | FRAMEWORK_SEARCH_PATHS = ( 1282 | "$(inherited)", 1283 | "$(PLATFORM_DIR)/Developer/Library/Frameworks", 1284 | ); 1285 | HEADER_SEARCH_PATHS = ( 1286 | "$(inherited)", 1287 | "$(SRCROOT)/.build/checkouts/Down/Source/cmark", 1288 | "$(SRCROOT)/Parma.xcodeproj/GeneratedModuleMap/libcmark", 1289 | ); 1290 | INFOPLIST_FILE = Parma.xcodeproj/ParmaTests_Info.plist; 1291 | IPHONEOS_DEPLOYMENT_TARGET = 13.0; 1292 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @loader_path/../Frameworks @loader_path/Frameworks"; 1293 | MACOSX_DEPLOYMENT_TARGET = 11.0; 1294 | OTHER_CFLAGS = "$(inherited)"; 1295 | OTHER_LDFLAGS = "$(inherited)"; 1296 | OTHER_SWIFT_FLAGS = "$(inherited) -Xcc -fmodule-map-file=$(SRCROOT)/Parma.xcodeproj/GeneratedModuleMap/libcmark/module.modulemap"; 1297 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited)"; 1298 | SWIFT_VERSION = 5.0; 1299 | TARGET_NAME = ParmaTests; 1300 | TVOS_DEPLOYMENT_TARGET = 9.0; 1301 | WATCHOS_DEPLOYMENT_TARGET = 2.0; 1302 | }; 1303 | name = Release; 1304 | }; 1305 | OBJ_299 /* Debug */ = { 1306 | isa = XCBuildConfiguration; 1307 | buildSettings = { 1308 | DEFINES_MODULE = NO; 1309 | ENABLE_TESTABILITY = YES; 1310 | FRAMEWORK_SEARCH_PATHS = ( 1311 | "$(inherited)", 1312 | "$(PLATFORM_DIR)/Developer/Library/Frameworks", 1313 | ); 1314 | HEADER_SEARCH_PATHS = ( 1315 | "$(inherited)", 1316 | "$(SRCROOT)/.build/checkouts/Down/Source/cmark", 1317 | ); 1318 | INFOPLIST_FILE = Parma.xcodeproj/libcmark_Info.plist; 1319 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 1320 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) $(TOOLCHAIN_DIR)/usr/lib/swift/macosx"; 1321 | MACOSX_DEPLOYMENT_TARGET = 10.11; 1322 | OTHER_CFLAGS = "$(inherited)"; 1323 | OTHER_LDFLAGS = "$(inherited)"; 1324 | OTHER_SWIFT_FLAGS = "$(inherited)"; 1325 | PRODUCT_BUNDLE_IDENTIFIER = libcmark; 1326 | PRODUCT_MODULE_NAME = "$(TARGET_NAME:c99extidentifier)"; 1327 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; 1328 | SKIP_INSTALL = YES; 1329 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited)"; 1330 | TARGET_NAME = libcmark; 1331 | TVOS_DEPLOYMENT_TARGET = 9.0; 1332 | WATCHOS_DEPLOYMENT_TARGET = 2.0; 1333 | }; 1334 | name = Debug; 1335 | }; 1336 | OBJ_3 /* Debug */ = { 1337 | isa = XCBuildConfiguration; 1338 | buildSettings = { 1339 | CLANG_ENABLE_OBJC_ARC = YES; 1340 | COMBINE_HIDPI_IMAGES = YES; 1341 | COPY_PHASE_STRIP = NO; 1342 | DEBUG_INFORMATION_FORMAT = dwarf; 1343 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 1344 | ENABLE_NS_ASSERTIONS = YES; 1345 | GCC_OPTIMIZATION_LEVEL = 0; 1346 | GCC_PREPROCESSOR_DEFINITIONS = ( 1347 | "$(inherited)", 1348 | "SWIFT_PACKAGE=1", 1349 | "DEBUG=1", 1350 | ); 1351 | IPHONEOS_DEPLOYMENT_TARGET = 13.0; 1352 | MACOSX_DEPLOYMENT_TARGET = 10.15; 1353 | ONLY_ACTIVE_ARCH = YES; 1354 | OTHER_SWIFT_FLAGS = "$(inherited) -DXcode"; 1355 | PRODUCT_NAME = "$(TARGET_NAME)"; 1356 | SDKROOT = macosx; 1357 | SUPPORTED_PLATFORMS = "macosx iphoneos iphonesimulator appletvos appletvsimulator watchos watchsimulator"; 1358 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) SWIFT_PACKAGE DEBUG"; 1359 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 1360 | USE_HEADERMAP = NO; 1361 | }; 1362 | name = Debug; 1363 | }; 1364 | OBJ_300 /* Release */ = { 1365 | isa = XCBuildConfiguration; 1366 | buildSettings = { 1367 | DEFINES_MODULE = NO; 1368 | ENABLE_TESTABILITY = YES; 1369 | FRAMEWORK_SEARCH_PATHS = ( 1370 | "$(inherited)", 1371 | "$(PLATFORM_DIR)/Developer/Library/Frameworks", 1372 | ); 1373 | HEADER_SEARCH_PATHS = ( 1374 | "$(inherited)", 1375 | "$(SRCROOT)/.build/checkouts/Down/Source/cmark", 1376 | ); 1377 | INFOPLIST_FILE = Parma.xcodeproj/libcmark_Info.plist; 1378 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 1379 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) $(TOOLCHAIN_DIR)/usr/lib/swift/macosx"; 1380 | MACOSX_DEPLOYMENT_TARGET = 10.11; 1381 | OTHER_CFLAGS = "$(inherited)"; 1382 | OTHER_LDFLAGS = "$(inherited)"; 1383 | OTHER_SWIFT_FLAGS = "$(inherited)"; 1384 | PRODUCT_BUNDLE_IDENTIFIER = libcmark; 1385 | PRODUCT_MODULE_NAME = "$(TARGET_NAME:c99extidentifier)"; 1386 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; 1387 | SKIP_INSTALL = YES; 1388 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited)"; 1389 | TARGET_NAME = libcmark; 1390 | TVOS_DEPLOYMENT_TARGET = 9.0; 1391 | WATCHOS_DEPLOYMENT_TARGET = 2.0; 1392 | }; 1393 | name = Release; 1394 | }; 1395 | OBJ_4 /* Release */ = { 1396 | isa = XCBuildConfiguration; 1397 | buildSettings = { 1398 | CLANG_ENABLE_OBJC_ARC = YES; 1399 | COMBINE_HIDPI_IMAGES = YES; 1400 | COPY_PHASE_STRIP = YES; 1401 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 1402 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 1403 | GCC_OPTIMIZATION_LEVEL = s; 1404 | GCC_PREPROCESSOR_DEFINITIONS = ( 1405 | "$(inherited)", 1406 | "SWIFT_PACKAGE=1", 1407 | ); 1408 | IPHONEOS_DEPLOYMENT_TARGET = 13.0; 1409 | MACOSX_DEPLOYMENT_TARGET = 10.15; 1410 | OTHER_SWIFT_FLAGS = "$(inherited) -DXcode"; 1411 | PRODUCT_NAME = "$(TARGET_NAME)"; 1412 | SDKROOT = macosx; 1413 | SUPPORTED_PLATFORMS = "macosx iphoneos iphonesimulator appletvos appletvsimulator watchos watchsimulator"; 1414 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) SWIFT_PACKAGE"; 1415 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 1416 | USE_HEADERMAP = NO; 1417 | }; 1418 | name = Release; 1419 | }; 1420 | /* End XCBuildConfiguration section */ 1421 | 1422 | /* Begin XCConfigurationList section */ 1423 | OBJ_165 /* Build configuration list for PBXNativeTarget "Down" */ = { 1424 | isa = XCConfigurationList; 1425 | buildConfigurations = ( 1426 | OBJ_166 /* Debug */, 1427 | OBJ_167 /* Release */, 1428 | ); 1429 | defaultConfigurationIsVisible = 0; 1430 | defaultConfigurationName = Release; 1431 | }; 1432 | OBJ_2 /* Build configuration list for PBXProject "Parma" */ = { 1433 | isa = XCConfigurationList; 1434 | buildConfigurations = ( 1435 | OBJ_3 /* Debug */, 1436 | OBJ_4 /* Release */, 1437 | ); 1438 | defaultConfigurationIsVisible = 0; 1439 | defaultConfigurationName = Release; 1440 | }; 1441 | OBJ_237 /* Build configuration list for PBXNativeTarget "DownPackageDescription" */ = { 1442 | isa = XCConfigurationList; 1443 | buildConfigurations = ( 1444 | OBJ_238 /* Debug */, 1445 | OBJ_239 /* Release */, 1446 | ); 1447 | defaultConfigurationIsVisible = 0; 1448 | defaultConfigurationName = Release; 1449 | }; 1450 | OBJ_243 /* Build configuration list for PBXNativeTarget "Parma" */ = { 1451 | isa = XCConfigurationList; 1452 | buildConfigurations = ( 1453 | OBJ_244 /* Debug */, 1454 | OBJ_245 /* Release */, 1455 | ); 1456 | defaultConfigurationIsVisible = 0; 1457 | defaultConfigurationName = Release; 1458 | }; 1459 | OBJ_274 /* Build configuration list for PBXNativeTarget "ParmaPackageDescription" */ = { 1460 | isa = XCConfigurationList; 1461 | buildConfigurations = ( 1462 | OBJ_275 /* Debug */, 1463 | OBJ_276 /* Release */, 1464 | ); 1465 | defaultConfigurationIsVisible = 0; 1466 | defaultConfigurationName = Release; 1467 | }; 1468 | OBJ_280 /* Build configuration list for PBXAggregateTarget "ParmaPackageTests" */ = { 1469 | isa = XCConfigurationList; 1470 | buildConfigurations = ( 1471 | OBJ_281 /* Debug */, 1472 | OBJ_282 /* Release */, 1473 | ); 1474 | defaultConfigurationIsVisible = 0; 1475 | defaultConfigurationName = Release; 1476 | }; 1477 | OBJ_285 /* Build configuration list for PBXNativeTarget "ParmaTests" */ = { 1478 | isa = XCConfigurationList; 1479 | buildConfigurations = ( 1480 | OBJ_286 /* Debug */, 1481 | OBJ_287 /* Release */, 1482 | ); 1483 | defaultConfigurationIsVisible = 0; 1484 | defaultConfigurationName = Release; 1485 | }; 1486 | OBJ_298 /* Build configuration list for PBXNativeTarget "libcmark" */ = { 1487 | isa = XCConfigurationList; 1488 | buildConfigurations = ( 1489 | OBJ_299 /* Debug */, 1490 | OBJ_300 /* Release */, 1491 | ); 1492 | defaultConfigurationIsVisible = 0; 1493 | defaultConfigurationName = Release; 1494 | }; 1495 | /* End XCConfigurationList section */ 1496 | }; 1497 | rootObject = OBJ_1 /* Project object */; 1498 | } 1499 | -------------------------------------------------------------------------------- /Parma.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | -------------------------------------------------------------------------------- /Parma.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Parma.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded 6 | 7 | 8 | -------------------------------------------------------------------------------- /Parma.xcodeproj/xcshareddata/IDETemplateMacros.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | FILEHEADER 6 | 7 | // ___FILENAME___ 8 | // Parma 9 | // 10 | // Created by ___USERNAME___ on ___DATE___. 11 | // 12 | // Copyright (c) ___YEAR___ Leonard Chan <wxclx98@gmail.com> 13 | // 14 | // MIT license, see LICENSE file for details 15 | 16 | 17 | -------------------------------------------------------------------------------- /Parma.xcodeproj/xcshareddata/xcschemes/Parma.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 43 | 44 | 50 | 51 | 57 | 58 | 59 | 60 | 62 | 63 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Parma 2 | Display Markdown using pure SwiftUI components. Taking advantages of `ViewBuilder` to make custom appearances for `Text` and `View`. 3 | 4 | ## Example 5 | ```swift 6 | import Parma 7 | 8 | struct ContentView: View { 9 | var markdown = "I'm **Strong**." 10 | 11 | var body: some View { 12 | Parma(markdown) 13 | } 14 | } 15 | ``` 16 | For more examples, please refer to [demo][1] app. 17 | 18 | ## Markdown Support 19 | ### Already Supported 20 | * Heading level 1-6 21 | * Paragraph 22 | * Multi-level bullet list 23 | * Multi-level ordered list 24 | * Period delimiter 25 | * Parenthesis delimiter 26 | * Image (Needs extra configurations) 27 | * Inline text 28 | * Strong 29 | * Emphasis 30 | * Code 31 | 32 | ### Possibly Support in Future Versions 33 | * Divider 34 | * Block quote 35 | * Code block 36 | 37 | ### Unsupported 38 | * Inline hyperlink 39 | 40 | ## Installation 41 | ### Requirement 42 | * Xcode 11.0 or later 43 | * Swift 5 or later 44 | * iOS 13.0 / macOS 10.15 or later deployment targets 45 | 46 | ### Swift Package Manager 47 | [Swift Package Manager][2] is a tool for managing the distribution of Swift code. It’s integrated with the Swift build system to automate the process of downloading, compiling, and linking dependencies on all platforms. 48 | 49 | Adding `Parma` as a dependency by [using Xcode’s GUI][3], the package url is `https://github.com/dasautoooo/Parma` . 50 | 51 | ### CocoaPods 52 | [CocoaPods](https://cocoapods.org) is a dependency manager for Cocoa projects. For usage and installation instructions, visit their website. To integrate `Parma` into your Xcode project using CocoaPods, specify it in your `Podfile`: 53 | 54 | ```ruby 55 | pod 'Parma' 56 | ``` 57 | 58 | 59 | ## Appearance Customization 60 | To customize `Text` styles and `View`s, create a new render which conform to protocol `ParmaRenderable`, and only reimplement those that fit your purposes. Finally, assign the customized render as a new render when create `Parma` view. 61 | 62 | ```swift 63 | import Parma 64 | 65 | struct ContentView: View { 66 | var markdown = "I'm **Strong**." 67 | 68 | var body: some View { 69 | Parma(markdown, render: MyRender()) 70 | } 71 | } 72 | 73 | struct MyRender: ParmaRenderable { 74 | ... 75 | } 76 | ``` 77 | 78 | There's a [DemoApp][4] that modified some of these delegate methods below for everyone to take as a reference. 79 | 80 | ```swift 81 | /// Define the heading text style. 82 | /// - Parameters: 83 | /// - level: The level of heading. 84 | /// - textView: The textView generated from captured heading string. 85 | func heading(level: HeadingLevel?, textView: Text) -> Text 86 | 87 | /// Define the paragraph text style. 88 | /// - Parameter text: The text string captured from paragraph. 89 | func paragraph(text: String) -> Text 90 | 91 | /// Define the text style for plain text. Do NOT recommend to alter this if there's no special purpose. 92 | /// - Parameter text: The text string captured from markdown. 93 | func plainText(_ text: String) -> Text 94 | 95 | /// Define the strong text style. 96 | /// - Parameter textView: The textView generated from captured strong string. 97 | func strong(textView: Text) -> Text 98 | 99 | /// Define the emphasis text style. 100 | /// - Parameter textView: The textView generated from captured emphasis string. 101 | func emphasis(textView: Text) -> Text 102 | 103 | /// Define the link text style. 104 | /// - Parameters: 105 | /// - textView: The textView generated from captured link string. 106 | /// - destination: The destination of the link. 107 | func link(textView: Text, destination: String?) -> Text 108 | 109 | /// Define the code text style. 110 | /// - Parameter text: The text string captured from code. 111 | func code(_ text: String) -> Text 112 | 113 | /// Define the style of heading view. 114 | /// - Parameters: 115 | /// - level: The level of heading. 116 | /// - view: The view contains heading text. 117 | func headingBlock(level: HeadingLevel?, view: AnyView) -> AnyView 118 | 119 | /// Define the style of paragraph view. 120 | /// - Parameter view: The view contains view(s) which belong(s) to this paragraph. 121 | func paragraphBlock(view: AnyView) -> AnyView 122 | 123 | /// Define the style of list item. 124 | /// - Parameter attributes: Attributes of the list containing the item. Those must be considered for proper item rendering. 125 | /// - Parameter index: Normalized index of the list item. For exemple, the index of the third item of a one level list would be `[2]` and the second item of a sublist appearing fourth in it's parent list would be `[3, 1]`. 126 | /// - Parameter view: The view contains view(s) which belong(s) to this item. 127 | func listItem(attributes: ListAttributes, index: [Int], view: AnyView) -> AnyView 128 | 129 | /// Define the style of image view. 130 | /// - Parameter urlString: The url string for this image view. 131 | /// - Parameter altTextView: The view contains alt text. 132 | func imageView(with urlString: String, altTextView: AnyView?) -> AnyView 133 | ``` 134 | 135 | ## Name Origin 136 | [Parma][5] is a city in the northern Italy, which is famous for its architecture, music and art. The reason of choosing this city name as the project name is [Giambattista Bodoni][6], a famous typographer, who spent most his lifetime living and working in this city. 137 | 138 | Bodoni was an Italian typographer, type-designer in Parma. During his lifespan, he designed many typefaces that known as [Bodoni][7] nowadays. Each Mac has Bodoni font installed, and free to use. 139 | 140 | ## Credit 141 | The package is built upon [Down][8], which is a markdown parser in Swift. 142 | 143 | [1]: https://github.com/dasautoooo/ParmaDemo 144 | [2]: https://swift.org/package-manager/ 145 | [3]: https://developer.apple.com/documentation/xcode/adding_package_dependencies_to_your_app 146 | [4]: https://github.com/dasautoooo/ParmaDemo 147 | [5]: https://en.wikipedia.org/wiki/Parma 148 | [6]: https://en.wikipedia.org/wiki/Giambattista_Bodoni 149 | [7]: https://en.wikipedia.org/wiki/Bodoni 150 | [8]: https://github.com/iwasrobbed/Down 151 | -------------------------------------------------------------------------------- /Sample/Sample.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 50; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | D7548DC824EEC7E200600D43 /* Parma.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D7FE786524EEC78C0077853A /* Parma.framework */; }; 11 | D7548DC924EEC7E200600D43 /* Parma.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = D7FE786524EEC78C0077853A /* Parma.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 12 | D7548DCB24EEC81800600D43 /* Parma.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D7FE786524EEC78C0077853A /* Parma.framework */; }; 13 | D7548DCC24EEC81800600D43 /* Parma.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = D7FE786524EEC78C0077853A /* Parma.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 14 | D7548DCF24EECA8D00600D43 /* SampleMarkdown.md in Resources */ = {isa = PBXBuildFile; fileRef = D7548DCE24EECA8D00600D43 /* SampleMarkdown.md */; }; 15 | D7548DD024EECA8D00600D43 /* SampleMarkdown.md in Resources */ = {isa = PBXBuildFile; fileRef = D7548DCE24EECA8D00600D43 /* SampleMarkdown.md */; }; 16 | D7FE784C24EEC75B0077853A /* SampleApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7FE783924EEC7590077853A /* SampleApp.swift */; }; 17 | D7FE784D24EEC75B0077853A /* SampleApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7FE783924EEC7590077853A /* SampleApp.swift */; }; 18 | D7FE784E24EEC75B0077853A /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7FE783A24EEC7590077853A /* ContentView.swift */; }; 19 | D7FE784F24EEC75B0077853A /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7FE783A24EEC7590077853A /* ContentView.swift */; }; 20 | D7FE785024EEC75B0077853A /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D7FE783B24EEC75B0077853A /* Assets.xcassets */; }; 21 | D7FE785124EEC75B0077853A /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D7FE783B24EEC75B0077853A /* Assets.xcassets */; }; 22 | /* End PBXBuildFile section */ 23 | 24 | /* Begin PBXContainerItemProxy section */ 25 | D7FE786424EEC78C0077853A /* PBXContainerItemProxy */ = { 26 | isa = PBXContainerItemProxy; 27 | containerPortal = D7FE785A24EEC78B0077853A /* Parma.xcodeproj */; 28 | proxyType = 2; 29 | remoteGlobalIDString = "Parma::Parma::Product"; 30 | remoteInfo = Parma; 31 | }; 32 | D7FE786624EEC78C0077853A /* PBXContainerItemProxy */ = { 33 | isa = PBXContainerItemProxy; 34 | containerPortal = D7FE785A24EEC78B0077853A /* Parma.xcodeproj */; 35 | proxyType = 2; 36 | remoteGlobalIDString = "Down::Down::Product"; 37 | remoteInfo = Down; 38 | }; 39 | D7FE786824EEC78C0077853A /* PBXContainerItemProxy */ = { 40 | isa = PBXContainerItemProxy; 41 | containerPortal = D7FE785A24EEC78B0077853A /* Parma.xcodeproj */; 42 | proxyType = 2; 43 | remoteGlobalIDString = "Parma::ParmaTests::Product"; 44 | remoteInfo = ParmaTests; 45 | }; 46 | D7FE786A24EEC78C0077853A /* PBXContainerItemProxy */ = { 47 | isa = PBXContainerItemProxy; 48 | containerPortal = D7FE785A24EEC78B0077853A /* Parma.xcodeproj */; 49 | proxyType = 2; 50 | remoteGlobalIDString = "Down::libcmark::Product"; 51 | remoteInfo = libcmark; 52 | }; 53 | /* End PBXContainerItemProxy section */ 54 | 55 | /* Begin PBXCopyFilesBuildPhase section */ 56 | D7548DCA24EEC7E200600D43 /* Embed Frameworks */ = { 57 | isa = PBXCopyFilesBuildPhase; 58 | buildActionMask = 2147483647; 59 | dstPath = ""; 60 | dstSubfolderSpec = 10; 61 | files = ( 62 | D7548DC924EEC7E200600D43 /* Parma.framework in Embed Frameworks */, 63 | ); 64 | name = "Embed Frameworks"; 65 | runOnlyForDeploymentPostprocessing = 0; 66 | }; 67 | D7548DCD24EEC81800600D43 /* Embed Frameworks */ = { 68 | isa = PBXCopyFilesBuildPhase; 69 | buildActionMask = 2147483647; 70 | dstPath = ""; 71 | dstSubfolderSpec = 10; 72 | files = ( 73 | D7548DCC24EEC81800600D43 /* Parma.framework in Embed Frameworks */, 74 | ); 75 | name = "Embed Frameworks"; 76 | runOnlyForDeploymentPostprocessing = 0; 77 | }; 78 | /* End PBXCopyFilesBuildPhase section */ 79 | 80 | /* Begin PBXFileReference section */ 81 | D7548DCE24EECA8D00600D43 /* SampleMarkdown.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = SampleMarkdown.md; sourceTree = ""; }; 82 | D7FE783924EEC7590077853A /* SampleApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SampleApp.swift; sourceTree = ""; }; 83 | D7FE783A24EEC7590077853A /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; 84 | D7FE783B24EEC75B0077853A /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 85 | D7FE784024EEC75B0077853A /* Sample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Sample.app; sourceTree = BUILT_PRODUCTS_DIR; }; 86 | D7FE784324EEC75B0077853A /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 87 | D7FE784824EEC75B0077853A /* Sample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Sample.app; sourceTree = BUILT_PRODUCTS_DIR; }; 88 | D7FE784A24EEC75B0077853A /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 89 | D7FE784B24EEC75B0077853A /* macOS.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = macOS.entitlements; sourceTree = ""; }; 90 | D7FE785A24EEC78B0077853A /* Parma.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Parma.xcodeproj; path = ../Parma.xcodeproj; sourceTree = ""; }; 91 | /* End PBXFileReference section */ 92 | 93 | /* Begin PBXFrameworksBuildPhase section */ 94 | D7FE783D24EEC75B0077853A /* Frameworks */ = { 95 | isa = PBXFrameworksBuildPhase; 96 | buildActionMask = 2147483647; 97 | files = ( 98 | D7548DC824EEC7E200600D43 /* Parma.framework in Frameworks */, 99 | ); 100 | runOnlyForDeploymentPostprocessing = 0; 101 | }; 102 | D7FE784524EEC75B0077853A /* Frameworks */ = { 103 | isa = PBXFrameworksBuildPhase; 104 | buildActionMask = 2147483647; 105 | files = ( 106 | D7548DCB24EEC81800600D43 /* Parma.framework in Frameworks */, 107 | ); 108 | runOnlyForDeploymentPostprocessing = 0; 109 | }; 110 | /* End PBXFrameworksBuildPhase section */ 111 | 112 | /* Begin PBXGroup section */ 113 | D7548DC024EEC7E200600D43 /* Frameworks */ = { 114 | isa = PBXGroup; 115 | children = ( 116 | ); 117 | name = Frameworks; 118 | sourceTree = ""; 119 | }; 120 | D7FE783324EEC7580077853A = { 121 | isa = PBXGroup; 122 | children = ( 123 | D7FE785A24EEC78B0077853A /* Parma.xcodeproj */, 124 | D7FE783824EEC7590077853A /* Shared */, 125 | D7FE784224EEC75B0077853A /* iOS */, 126 | D7FE784924EEC75B0077853A /* macOS */, 127 | D7FE784124EEC75B0077853A /* Products */, 128 | D7548DC024EEC7E200600D43 /* Frameworks */, 129 | ); 130 | sourceTree = ""; 131 | }; 132 | D7FE783824EEC7590077853A /* Shared */ = { 133 | isa = PBXGroup; 134 | children = ( 135 | D7FE783924EEC7590077853A /* SampleApp.swift */, 136 | D7FE783A24EEC7590077853A /* ContentView.swift */, 137 | D7548DCE24EECA8D00600D43 /* SampleMarkdown.md */, 138 | D7FE783B24EEC75B0077853A /* Assets.xcassets */, 139 | ); 140 | path = Shared; 141 | sourceTree = ""; 142 | }; 143 | D7FE784124EEC75B0077853A /* Products */ = { 144 | isa = PBXGroup; 145 | children = ( 146 | D7FE784024EEC75B0077853A /* Sample.app */, 147 | D7FE784824EEC75B0077853A /* Sample.app */, 148 | ); 149 | name = Products; 150 | sourceTree = ""; 151 | }; 152 | D7FE784224EEC75B0077853A /* iOS */ = { 153 | isa = PBXGroup; 154 | children = ( 155 | D7FE784324EEC75B0077853A /* Info.plist */, 156 | ); 157 | path = iOS; 158 | sourceTree = ""; 159 | }; 160 | D7FE784924EEC75B0077853A /* macOS */ = { 161 | isa = PBXGroup; 162 | children = ( 163 | D7FE784A24EEC75B0077853A /* Info.plist */, 164 | D7FE784B24EEC75B0077853A /* macOS.entitlements */, 165 | ); 166 | path = macOS; 167 | sourceTree = ""; 168 | }; 169 | D7FE785B24EEC78B0077853A /* Products */ = { 170 | isa = PBXGroup; 171 | children = ( 172 | D7FE786524EEC78C0077853A /* Parma.framework */, 173 | D7FE786724EEC78C0077853A /* Down.framework */, 174 | D7FE786924EEC78C0077853A /* ParmaTests.xctest */, 175 | D7FE786B24EEC78C0077853A /* libcmark.framework */, 176 | ); 177 | name = Products; 178 | sourceTree = ""; 179 | }; 180 | /* End PBXGroup section */ 181 | 182 | /* Begin PBXNativeTarget section */ 183 | D7FE783F24EEC75B0077853A /* Sample (iOS) */ = { 184 | isa = PBXNativeTarget; 185 | buildConfigurationList = D7FE785424EEC75B0077853A /* Build configuration list for PBXNativeTarget "Sample (iOS)" */; 186 | buildPhases = ( 187 | D7FE783C24EEC75B0077853A /* Sources */, 188 | D7FE783D24EEC75B0077853A /* Frameworks */, 189 | D7FE783E24EEC75B0077853A /* Resources */, 190 | D7548DCA24EEC7E200600D43 /* Embed Frameworks */, 191 | ); 192 | buildRules = ( 193 | ); 194 | dependencies = ( 195 | ); 196 | name = "Sample (iOS)"; 197 | productName = "Sample (iOS)"; 198 | productReference = D7FE784024EEC75B0077853A /* Sample.app */; 199 | productType = "com.apple.product-type.application"; 200 | }; 201 | D7FE784724EEC75B0077853A /* Sample (macOS) */ = { 202 | isa = PBXNativeTarget; 203 | buildConfigurationList = D7FE785724EEC75B0077853A /* Build configuration list for PBXNativeTarget "Sample (macOS)" */; 204 | buildPhases = ( 205 | D7FE784424EEC75B0077853A /* Sources */, 206 | D7FE784524EEC75B0077853A /* Frameworks */, 207 | D7FE784624EEC75B0077853A /* Resources */, 208 | D7548DCD24EEC81800600D43 /* Embed Frameworks */, 209 | ); 210 | buildRules = ( 211 | ); 212 | dependencies = ( 213 | ); 214 | name = "Sample (macOS)"; 215 | productName = "Sample (macOS)"; 216 | productReference = D7FE784824EEC75B0077853A /* Sample.app */; 217 | productType = "com.apple.product-type.application"; 218 | }; 219 | /* End PBXNativeTarget section */ 220 | 221 | /* Begin PBXProject section */ 222 | D7FE783424EEC7580077853A /* Project object */ = { 223 | isa = PBXProject; 224 | attributes = { 225 | LastSwiftUpdateCheck = 1200; 226 | LastUpgradeCheck = 1200; 227 | TargetAttributes = { 228 | D7FE783F24EEC75B0077853A = { 229 | CreatedOnToolsVersion = 12.0; 230 | }; 231 | D7FE784724EEC75B0077853A = { 232 | CreatedOnToolsVersion = 12.0; 233 | }; 234 | }; 235 | }; 236 | buildConfigurationList = D7FE783724EEC7580077853A /* Build configuration list for PBXProject "Sample" */; 237 | compatibilityVersion = "Xcode 9.3"; 238 | developmentRegion = en; 239 | hasScannedForEncodings = 0; 240 | knownRegions = ( 241 | en, 242 | Base, 243 | ); 244 | mainGroup = D7FE783324EEC7580077853A; 245 | productRefGroup = D7FE784124EEC75B0077853A /* Products */; 246 | projectDirPath = ""; 247 | projectReferences = ( 248 | { 249 | ProductGroup = D7FE785B24EEC78B0077853A /* Products */; 250 | ProjectRef = D7FE785A24EEC78B0077853A /* Parma.xcodeproj */; 251 | }, 252 | ); 253 | projectRoot = ""; 254 | targets = ( 255 | D7FE783F24EEC75B0077853A /* Sample (iOS) */, 256 | D7FE784724EEC75B0077853A /* Sample (macOS) */, 257 | ); 258 | }; 259 | /* End PBXProject section */ 260 | 261 | /* Begin PBXReferenceProxy section */ 262 | D7FE786524EEC78C0077853A /* Parma.framework */ = { 263 | isa = PBXReferenceProxy; 264 | fileType = wrapper.framework; 265 | path = Parma.framework; 266 | remoteRef = D7FE786424EEC78C0077853A /* PBXContainerItemProxy */; 267 | sourceTree = BUILT_PRODUCTS_DIR; 268 | }; 269 | D7FE786724EEC78C0077853A /* Down.framework */ = { 270 | isa = PBXReferenceProxy; 271 | fileType = wrapper.framework; 272 | path = Down.framework; 273 | remoteRef = D7FE786624EEC78C0077853A /* PBXContainerItemProxy */; 274 | sourceTree = BUILT_PRODUCTS_DIR; 275 | }; 276 | D7FE786924EEC78C0077853A /* ParmaTests.xctest */ = { 277 | isa = PBXReferenceProxy; 278 | fileType = wrapper.cfbundle; 279 | path = ParmaTests.xctest; 280 | remoteRef = D7FE786824EEC78C0077853A /* PBXContainerItemProxy */; 281 | sourceTree = BUILT_PRODUCTS_DIR; 282 | }; 283 | D7FE786B24EEC78C0077853A /* libcmark.framework */ = { 284 | isa = PBXReferenceProxy; 285 | fileType = wrapper.framework; 286 | path = libcmark.framework; 287 | remoteRef = D7FE786A24EEC78C0077853A /* PBXContainerItemProxy */; 288 | sourceTree = BUILT_PRODUCTS_DIR; 289 | }; 290 | /* End PBXReferenceProxy section */ 291 | 292 | /* Begin PBXResourcesBuildPhase section */ 293 | D7FE783E24EEC75B0077853A /* Resources */ = { 294 | isa = PBXResourcesBuildPhase; 295 | buildActionMask = 2147483647; 296 | files = ( 297 | D7548DCF24EECA8D00600D43 /* SampleMarkdown.md in Resources */, 298 | D7FE785024EEC75B0077853A /* Assets.xcassets in Resources */, 299 | ); 300 | runOnlyForDeploymentPostprocessing = 0; 301 | }; 302 | D7FE784624EEC75B0077853A /* Resources */ = { 303 | isa = PBXResourcesBuildPhase; 304 | buildActionMask = 2147483647; 305 | files = ( 306 | D7548DD024EECA8D00600D43 /* SampleMarkdown.md in Resources */, 307 | D7FE785124EEC75B0077853A /* Assets.xcassets in Resources */, 308 | ); 309 | runOnlyForDeploymentPostprocessing = 0; 310 | }; 311 | /* End PBXResourcesBuildPhase section */ 312 | 313 | /* Begin PBXSourcesBuildPhase section */ 314 | D7FE783C24EEC75B0077853A /* Sources */ = { 315 | isa = PBXSourcesBuildPhase; 316 | buildActionMask = 2147483647; 317 | files = ( 318 | D7FE784E24EEC75B0077853A /* ContentView.swift in Sources */, 319 | D7FE784C24EEC75B0077853A /* SampleApp.swift in Sources */, 320 | ); 321 | runOnlyForDeploymentPostprocessing = 0; 322 | }; 323 | D7FE784424EEC75B0077853A /* Sources */ = { 324 | isa = PBXSourcesBuildPhase; 325 | buildActionMask = 2147483647; 326 | files = ( 327 | D7FE784F24EEC75B0077853A /* ContentView.swift in Sources */, 328 | D7FE784D24EEC75B0077853A /* SampleApp.swift in Sources */, 329 | ); 330 | runOnlyForDeploymentPostprocessing = 0; 331 | }; 332 | /* End PBXSourcesBuildPhase section */ 333 | 334 | /* Begin XCBuildConfiguration section */ 335 | D7FE785224EEC75B0077853A /* Debug */ = { 336 | isa = XCBuildConfiguration; 337 | buildSettings = { 338 | ALWAYS_SEARCH_USER_PATHS = NO; 339 | CLANG_ANALYZER_NONNULL = YES; 340 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 341 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 342 | CLANG_CXX_LIBRARY = "libc++"; 343 | CLANG_ENABLE_MODULES = YES; 344 | CLANG_ENABLE_OBJC_ARC = YES; 345 | CLANG_ENABLE_OBJC_WEAK = YES; 346 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 347 | CLANG_WARN_BOOL_CONVERSION = YES; 348 | CLANG_WARN_COMMA = YES; 349 | CLANG_WARN_CONSTANT_CONVERSION = YES; 350 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 351 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 352 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 353 | CLANG_WARN_EMPTY_BODY = YES; 354 | CLANG_WARN_ENUM_CONVERSION = YES; 355 | CLANG_WARN_INFINITE_RECURSION = YES; 356 | CLANG_WARN_INT_CONVERSION = YES; 357 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 358 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 359 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 360 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 361 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 362 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 363 | CLANG_WARN_STRICT_PROTOTYPES = YES; 364 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 365 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 366 | CLANG_WARN_UNREACHABLE_CODE = YES; 367 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 368 | COPY_PHASE_STRIP = NO; 369 | DEBUG_INFORMATION_FORMAT = dwarf; 370 | ENABLE_STRICT_OBJC_MSGSEND = YES; 371 | ENABLE_TESTABILITY = YES; 372 | GCC_C_LANGUAGE_STANDARD = gnu11; 373 | GCC_DYNAMIC_NO_PIC = NO; 374 | GCC_NO_COMMON_BLOCKS = YES; 375 | GCC_OPTIMIZATION_LEVEL = 0; 376 | GCC_PREPROCESSOR_DEFINITIONS = ( 377 | "DEBUG=1", 378 | "$(inherited)", 379 | ); 380 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 381 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 382 | GCC_WARN_UNDECLARED_SELECTOR = YES; 383 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 384 | GCC_WARN_UNUSED_FUNCTION = YES; 385 | GCC_WARN_UNUSED_VARIABLE = YES; 386 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 387 | MTL_FAST_MATH = YES; 388 | ONLY_ACTIVE_ARCH = YES; 389 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 390 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 391 | }; 392 | name = Debug; 393 | }; 394 | D7FE785324EEC75B0077853A /* Release */ = { 395 | isa = XCBuildConfiguration; 396 | buildSettings = { 397 | ALWAYS_SEARCH_USER_PATHS = NO; 398 | CLANG_ANALYZER_NONNULL = YES; 399 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 400 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 401 | CLANG_CXX_LIBRARY = "libc++"; 402 | CLANG_ENABLE_MODULES = YES; 403 | CLANG_ENABLE_OBJC_ARC = YES; 404 | CLANG_ENABLE_OBJC_WEAK = YES; 405 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 406 | CLANG_WARN_BOOL_CONVERSION = YES; 407 | CLANG_WARN_COMMA = YES; 408 | CLANG_WARN_CONSTANT_CONVERSION = YES; 409 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 410 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 411 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 412 | CLANG_WARN_EMPTY_BODY = YES; 413 | CLANG_WARN_ENUM_CONVERSION = YES; 414 | CLANG_WARN_INFINITE_RECURSION = YES; 415 | CLANG_WARN_INT_CONVERSION = YES; 416 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 417 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 418 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 419 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 420 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 421 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 422 | CLANG_WARN_STRICT_PROTOTYPES = YES; 423 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 424 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 425 | CLANG_WARN_UNREACHABLE_CODE = YES; 426 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 427 | COPY_PHASE_STRIP = NO; 428 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 429 | ENABLE_NS_ASSERTIONS = NO; 430 | ENABLE_STRICT_OBJC_MSGSEND = YES; 431 | GCC_C_LANGUAGE_STANDARD = gnu11; 432 | GCC_NO_COMMON_BLOCKS = YES; 433 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 434 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 435 | GCC_WARN_UNDECLARED_SELECTOR = YES; 436 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 437 | GCC_WARN_UNUSED_FUNCTION = YES; 438 | GCC_WARN_UNUSED_VARIABLE = YES; 439 | MTL_ENABLE_DEBUG_INFO = NO; 440 | MTL_FAST_MATH = YES; 441 | SWIFT_COMPILATION_MODE = wholemodule; 442 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 443 | }; 444 | name = Release; 445 | }; 446 | D7FE785524EEC75B0077853A /* Debug */ = { 447 | isa = XCBuildConfiguration; 448 | buildSettings = { 449 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 450 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 451 | CODE_SIGN_STYLE = Automatic; 452 | DEVELOPMENT_TEAM = 64ZYG66RMG; 453 | ENABLE_PREVIEWS = YES; 454 | INFOPLIST_FILE = iOS/Info.plist; 455 | IPHONEOS_DEPLOYMENT_TARGET = 14.0; 456 | LD_RUNPATH_SEARCH_PATHS = ( 457 | "$(inherited)", 458 | "@executable_path/Frameworks", 459 | ); 460 | PRODUCT_BUNDLE_IDENTIFIER = com.dasautoooo.Sample; 461 | PRODUCT_NAME = Sample; 462 | SDKROOT = iphoneos; 463 | SWIFT_INCLUDE_PATHS = "${SRCROOT}/../.build/checkouts/Down/Source/cmark/**"; 464 | SWIFT_VERSION = 5.0; 465 | TARGETED_DEVICE_FAMILY = "1,2"; 466 | }; 467 | name = Debug; 468 | }; 469 | D7FE785624EEC75B0077853A /* Release */ = { 470 | isa = XCBuildConfiguration; 471 | buildSettings = { 472 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 473 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 474 | CODE_SIGN_STYLE = Automatic; 475 | DEVELOPMENT_TEAM = 64ZYG66RMG; 476 | ENABLE_PREVIEWS = YES; 477 | INFOPLIST_FILE = iOS/Info.plist; 478 | IPHONEOS_DEPLOYMENT_TARGET = 14.0; 479 | LD_RUNPATH_SEARCH_PATHS = ( 480 | "$(inherited)", 481 | "@executable_path/Frameworks", 482 | ); 483 | PRODUCT_BUNDLE_IDENTIFIER = com.dasautoooo.Sample; 484 | PRODUCT_NAME = Sample; 485 | SDKROOT = iphoneos; 486 | SWIFT_INCLUDE_PATHS = "${SRCROOT}/../.build/checkouts/Down/Source/cmark/**"; 487 | SWIFT_VERSION = 5.0; 488 | TARGETED_DEVICE_FAMILY = "1,2"; 489 | VALIDATE_PRODUCT = YES; 490 | }; 491 | name = Release; 492 | }; 493 | D7FE785824EEC75B0077853A /* Debug */ = { 494 | isa = XCBuildConfiguration; 495 | buildSettings = { 496 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 497 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 498 | CODE_SIGN_ENTITLEMENTS = macOS/macOS.entitlements; 499 | CODE_SIGN_STYLE = Automatic; 500 | COMBINE_HIDPI_IMAGES = YES; 501 | DEVELOPMENT_TEAM = 64ZYG66RMG; 502 | ENABLE_HARDENED_RUNTIME = YES; 503 | ENABLE_PREVIEWS = YES; 504 | INFOPLIST_FILE = macOS/Info.plist; 505 | LD_RUNPATH_SEARCH_PATHS = ( 506 | "$(inherited)", 507 | "@executable_path/../Frameworks", 508 | ); 509 | MACOSX_DEPLOYMENT_TARGET = 11.0; 510 | PRODUCT_BUNDLE_IDENTIFIER = com.dasautoooo.Sample; 511 | PRODUCT_NAME = Sample; 512 | SDKROOT = macosx; 513 | SWIFT_INCLUDE_PATHS = "${SRCROOT}/../.build/checkouts/Down/Source/cmark/**"; 514 | SWIFT_VERSION = 5.0; 515 | }; 516 | name = Debug; 517 | }; 518 | D7FE785924EEC75B0077853A /* Release */ = { 519 | isa = XCBuildConfiguration; 520 | buildSettings = { 521 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 522 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 523 | CODE_SIGN_ENTITLEMENTS = macOS/macOS.entitlements; 524 | CODE_SIGN_STYLE = Automatic; 525 | COMBINE_HIDPI_IMAGES = YES; 526 | DEVELOPMENT_TEAM = 64ZYG66RMG; 527 | ENABLE_HARDENED_RUNTIME = YES; 528 | ENABLE_PREVIEWS = YES; 529 | INFOPLIST_FILE = macOS/Info.plist; 530 | LD_RUNPATH_SEARCH_PATHS = ( 531 | "$(inherited)", 532 | "@executable_path/../Frameworks", 533 | ); 534 | MACOSX_DEPLOYMENT_TARGET = 11.0; 535 | PRODUCT_BUNDLE_IDENTIFIER = com.dasautoooo.Sample; 536 | PRODUCT_NAME = Sample; 537 | SDKROOT = macosx; 538 | SWIFT_INCLUDE_PATHS = "${SRCROOT}/../.build/checkouts/Down/Source/cmark/**"; 539 | SWIFT_VERSION = 5.0; 540 | }; 541 | name = Release; 542 | }; 543 | /* End XCBuildConfiguration section */ 544 | 545 | /* Begin XCConfigurationList section */ 546 | D7FE783724EEC7580077853A /* Build configuration list for PBXProject "Sample" */ = { 547 | isa = XCConfigurationList; 548 | buildConfigurations = ( 549 | D7FE785224EEC75B0077853A /* Debug */, 550 | D7FE785324EEC75B0077853A /* Release */, 551 | ); 552 | defaultConfigurationIsVisible = 0; 553 | defaultConfigurationName = Release; 554 | }; 555 | D7FE785424EEC75B0077853A /* Build configuration list for PBXNativeTarget "Sample (iOS)" */ = { 556 | isa = XCConfigurationList; 557 | buildConfigurations = ( 558 | D7FE785524EEC75B0077853A /* Debug */, 559 | D7FE785624EEC75B0077853A /* Release */, 560 | ); 561 | defaultConfigurationIsVisible = 0; 562 | defaultConfigurationName = Release; 563 | }; 564 | D7FE785724EEC75B0077853A /* Build configuration list for PBXNativeTarget "Sample (macOS)" */ = { 565 | isa = XCConfigurationList; 566 | buildConfigurations = ( 567 | D7FE785824EEC75B0077853A /* Debug */, 568 | D7FE785924EEC75B0077853A /* Release */, 569 | ); 570 | defaultConfigurationIsVisible = 0; 571 | defaultConfigurationName = Release; 572 | }; 573 | /* End XCConfigurationList section */ 574 | }; 575 | rootObject = D7FE783424EEC7580077853A /* Project object */; 576 | } 577 | -------------------------------------------------------------------------------- /Sample/Sample.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Sample/Sample.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Sample/Sample.xcodeproj/xcshareddata/IDETemplateMacros.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | FILEHEADER 6 | 7 | // ___FILENAME___ 8 | // Parma 9 | // 10 | // Created by ___USERNAME___ on ___DATE___. 11 | // 12 | // Copyright (c) ___YEAR___ Leonard Chan <wxclx98@gmail.com> 13 | // 14 | // MIT license, see LICENSE file for details 15 | 16 | 17 | -------------------------------------------------------------------------------- /Sample/Shared/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Sample/Shared/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "scale" : "2x", 6 | "size" : "20x20" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "scale" : "3x", 11 | "size" : "20x20" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "scale" : "2x", 16 | "size" : "29x29" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "scale" : "3x", 21 | "size" : "29x29" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "scale" : "2x", 26 | "size" : "40x40" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "scale" : "3x", 31 | "size" : "40x40" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "scale" : "2x", 36 | "size" : "60x60" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "scale" : "3x", 41 | "size" : "60x60" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "scale" : "1x", 46 | "size" : "20x20" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "scale" : "2x", 51 | "size" : "20x20" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "scale" : "1x", 56 | "size" : "29x29" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "scale" : "2x", 61 | "size" : "29x29" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "scale" : "1x", 66 | "size" : "40x40" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "scale" : "2x", 71 | "size" : "40x40" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "scale" : "1x", 76 | "size" : "76x76" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "scale" : "2x", 81 | "size" : "76x76" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "scale" : "2x", 86 | "size" : "83.5x83.5" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "scale" : "1x", 91 | "size" : "1024x1024" 92 | }, 93 | { 94 | "idiom" : "mac", 95 | "scale" : "1x", 96 | "size" : "16x16" 97 | }, 98 | { 99 | "idiom" : "mac", 100 | "scale" : "2x", 101 | "size" : "16x16" 102 | }, 103 | { 104 | "idiom" : "mac", 105 | "scale" : "1x", 106 | "size" : "32x32" 107 | }, 108 | { 109 | "idiom" : "mac", 110 | "scale" : "2x", 111 | "size" : "32x32" 112 | }, 113 | { 114 | "idiom" : "mac", 115 | "scale" : "1x", 116 | "size" : "128x128" 117 | }, 118 | { 119 | "idiom" : "mac", 120 | "scale" : "2x", 121 | "size" : "128x128" 122 | }, 123 | { 124 | "idiom" : "mac", 125 | "scale" : "1x", 126 | "size" : "256x256" 127 | }, 128 | { 129 | "idiom" : "mac", 130 | "scale" : "2x", 131 | "size" : "256x256" 132 | }, 133 | { 134 | "idiom" : "mac", 135 | "scale" : "1x", 136 | "size" : "512x512" 137 | }, 138 | { 139 | "idiom" : "mac", 140 | "scale" : "2x", 141 | "size" : "512x512" 142 | } 143 | ], 144 | "info" : { 145 | "author" : "xcode", 146 | "version" : 1 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /Sample/Shared/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Sample/Shared/ContentView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentView.swift 3 | // Parma 4 | // 5 | // Created by leonard on 8/20/20. 6 | // 7 | // Copyright (c) 2020 Leonard Chan 8 | // 9 | // MIT license, see LICENSE file for details 10 | 11 | import SwiftUI 12 | import Parma 13 | 14 | struct ContentView: View { 15 | @State var markdown: String = "" 16 | 17 | var body: some View { 18 | ScrollView { 19 | Parma(markdown) 20 | .padding(.horizontal, 24) 21 | } 22 | .onAppear { 23 | let url = Bundle.main.url(forResource: "SampleMarkdown", withExtension: "md")! 24 | markdown = try! String(contentsOf: url) 25 | } 26 | } 27 | } 28 | 29 | struct ContentView_Previews: PreviewProvider { 30 | static var previews: some View { 31 | ContentView() 32 | } 33 | } 34 | 35 | struct MyRender: ParmaRenderable { 36 | func heading(level: HeadingLevel?, textView: Text) -> Text { 37 | switch level { 38 | case .one: 39 | return textView.font(.system(.largeTitle, design: .serif)).bold() 40 | case .two: 41 | return textView.font(.system(.title, design: .serif)).bold() 42 | case .three: 43 | return textView.font(.system(.title2)).bold() 44 | default: 45 | return textView.font(.system(.title3)).bold() 46 | } 47 | } 48 | 49 | func headingBlock(level: HeadingLevel?, view: AnyView) -> AnyView { 50 | switch level { 51 | case .one, .two: 52 | return AnyView( 53 | VStack(alignment: .leading, spacing: 2) { 54 | view 55 | .padding(.top, 4) 56 | Rectangle() 57 | .foregroundColor(.pink) 58 | .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: 1, alignment: .center) 59 | .padding(.bottom, 8) 60 | } 61 | ) 62 | default: 63 | return AnyView(view.padding(.bottom, 4)) 64 | } 65 | } 66 | 67 | public func paragraphBlock(view: AnyView) -> AnyView { 68 | struct ExpandableView: View { 69 | @State var lineLimit: Int? = nil 70 | let view: AnyView 71 | 72 | var body: some View { 73 | view 74 | .lineLimit(lineLimit) 75 | .padding(.bottom, 8) 76 | .onTapGesture { 77 | if lineLimit == nil { 78 | lineLimit = 1 79 | } else { 80 | lineLimit = nil 81 | } 82 | } 83 | } 84 | } 85 | 86 | // AnyView(view.padding(.bottom, 8)) 87 | return AnyView(ExpandableView(view: view)) 88 | } 89 | 90 | 91 | func listItem(attributes: ListAttributes, index: [Int], view: AnyView) -> AnyView { 92 | let delimiter: String 93 | switch attributes.delimiter { 94 | case .period: 95 | delimiter = "." 96 | case .parenthesis: 97 | delimiter = ")" 98 | } 99 | 100 | let separator: String 101 | switch attributes.type { 102 | case .bullet: 103 | separator = index.count % 2 == 1 ? "•" : "◦" 104 | case .ordered: 105 | separator = index 106 | .map({ String($0) }) 107 | .joined(separator: ".") 108 | .appending(delimiter) 109 | } 110 | 111 | return AnyView( 112 | HStack(alignment: .top, spacing: 4) { 113 | Text(separator) 114 | view 115 | } 116 | ) 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /Sample/Shared/SampleApp.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SampleApp.swift 3 | // Parma 4 | // 5 | // Created by leonard on 8/20/20. 6 | // 7 | // Copyright (c) 2020 Leonard Chan 8 | // 9 | // MIT license, see LICENSE file for details 10 | 11 | import SwiftUI 12 | 13 | @main 14 | struct SampleApp: App { 15 | var body: some Scene { 16 | WindowGroup { 17 | ContentView() 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Sample/Shared/SampleMarkdown.md: -------------------------------------------------------------------------------- 1 | # Parma 2 | 3 | **Parma** is a city in the northern Italian region of Emilia-Romagna famous for its architecture, music, art, prosciutto (ham), cheese and surrounding countryside. It is home to the University of Parma, one of the oldest universities in the world. Parma is divided into two parts by the stream of the same name. The district on the far side of the river is *Oltretorrente*. Parma's Etruscan name was adapted by Romans to describe the round shield called *Parma*. 4 | 5 | ![Parma][image-1] 6 | 7 | The Italian poet Attilio Bertolucci (born in a hamlet in the countryside) wrote: "As a capital city it had to have a river. As a little capital it received a stream, which is often dry". 8 | 9 | **Contents** 10 | 1. Culture 11 | 1. Food and cuisine 12 | 1. People 13 | 1. Painters and sculptors 14 | 1. Others 15 | 16 | ## Culture 17 | ### Food and cuisine 18 | Parma is famous for its food and rich gastronomical tradition: two of its specialties are Parmigiano Reggiano cheese (also produced in Reggio Emilia), and Prosciutto di Parma (Parma ham), both given Protected Designation of Origin status. Parma also claims several stuffed pasta dishes like "tortelli d'erbetta" and "anolini in brodo". 19 | 20 | ![Parma Night][image-2] 21 | 22 | ### People 23 | * **Painters and sculptors** 24 | * **Michelangelo Anselmi**, painter born in Tuscany 25 | * **Benedetto Antelami**, architect and sculptor 26 | * **Alessandro Araldi**, painter 27 | * **Sisto Badalocchio**, painter 28 | * **Jacopo Bertoia** (Giacomo Zanguidi or Jacopo Zanguidi or Bertoja), painter 29 | * **Amedeo Bocchi**, painter 30 | * **Giulio Carmignani**, painter 31 | * **Antonio da Correggio** (Antonio Allegri), born in Correggio (Reggio Emilia), painter 32 | * **Francesco Marmitta**, painter 33 | * **Filippo Mazzola**, painter 34 | * **Francesco Mazzola**, best known as Il Parmigianino, painter 35 | * **Girolamo Mazzola Bedoli**, painter 36 | * **Giovanni Maria Francesco Rondani**, painter 37 | * **Bartolomeo Schedoni**, painter 38 | * **Others** 39 | * **Vittorio Adorni**, cyclist 40 | * **Giovanni Amighetti**, composer, musician 41 | * **Amoretti Brothers**, typographers and typefounders, Bodoni's opponents 42 | * **Giambattista Bodoni**, typographer 43 | 44 | # Giambattista Bodoni 45 | **Giambattista Bodoni** was an Italian typographer, type-designer, compositor, printer and publisher in **Parma**. 46 | ![Giambattista Bodoni by Giuseppe Lucatelli][image-3] 47 | He first took the type-designs of Pierre Simon Fournier as his exemplars, but afterwards became an admirer of the more modelled types of **John Baskerville**; and he and Firmin Didot evolved a style of type called "Modern," in which the letters are cut in such a way as to produce a strong contrast between the thick and thin parts of their body. Bodoni designed many typefaces, each one in a large range of type sizes. He is even more admired as a compositor than as a type designer, as the large range of sizes which he cut enabled him to compose his pages with the greatest possible subtlety of spacing. Like Baskerville, he sets off his texts with wide margins and uses little or no illustrations or decorations. 48 | ![Quosque Tandem][image-4] 49 | There have been several modern revivals of his typefaces, all called *Bodoni*. They are often used as display faces. 50 | 51 | # Bodoni 52 | **Bodoni** is the name given to the serif typefaces first designed by **Giambattista Bodoni** (1740–1813) in the late eighteenth century and frequently revived since. Bodoni's typefaces are classified as **Didone** or **modern**. Bodoni followed the ideas of John Baskerville, as found in the printing type **Baskerville**—increased stroke contrast reflecting developing printing technology and a more vertical axis—but he took them to a more extreme conclusion. Bodoni had a long career and his designs changed and varied, ending with a typeface of a slightly condensed underlying structure with flat, unbracketed serifs, extreme contrast between thick and thin strokes, and an overall geometric construction. 53 | ![ITCBodoni][image-5] 54 | Some digital versions of Bodoni are said to be hard to read due to "dazzle" caused by the alternating thick and thin strokes, particularly as the thin strokes are very thin at small point sizes. This is very common when optical sizes of font intended for use at display sizes are printed at text size, at which point the hairline strokes can recede to being hard to see. Versions of Bodoni that are intended to be used at text size are "Bodoni Old Face", optimized for 9 points; ITC Bodoni 12 (for 12 points); and ITC Bodoni 6 (for 6 points). 55 | ![Bodoni vita nuova facsimile sepia][image-6] 56 | Massimo Vignelli stated that "Bodoni is one of the most elegant typefaces ever designed." In the English-speaking world, "modern" serif designs like Bodoni are most commonly used in headings and display uses and in upmarket magazine printing, which is often done on high-gloss paper that retains and sets off the crisp detail of the fine strokes. In Europe, they are more often used in body text. 57 | 58 | ## Foundry type revivals and variants 59 | There have been many revivals of the Bodoni typeface; ATF Bodoni and Bauer Bodoni are two of the more successful. 60 | * **ATF's** Bodoni series created in 1909, was the first American release to be a direct revival of Bodoni's work. All variants were designed by Morris Fuller Benton who captured the flavour of Bodoni's original while emphasizing legibility rather than trying to push against the limits of printing technology. This revival is regarded as "the first accurate revival of a historical face for general printing and design applications". However, some details were less based on Bodoni than on the work of his French contemporary Firmin Didot, for example a 't' with a flat rather than slanted top. 61 | * _Bodoni_ (1909) 62 | * _Bodoni Italic_ (1910) 63 | * _Bodoni Book_ (1910) 64 | * _Bodoni Book Italic_ (1911) 65 | * _Bodoni Bold + Italic_ (1911) 66 | * _Bodoni Bold Shaded_ (1912) 67 | * _Bodoni Shaded Initials_ (1914) 68 | * _Card Bodoni_ (1915) 69 | * _Card Bodoni Bold_ (1917) 70 | * _Bodoni Open_ (1918) 71 | * _Bodoni Book Expanded_ (1924) 72 | * _Ultra Bodoni + italic_ (1928) 73 | * _Bodoni Bold Condensed_ (1933) 74 | * _Ultra Bodoni Condensed + extra condensed_ (1933) 75 | * _Engravers Bodoni_ (1933), designed in 1926. 76 | * **Monotype**: 77 | * _Bodoni #175 + italic_ (1911) 78 | * _Bodoni #375 + italic_ (1930), based on the Benton version. 79 | * _Recut Bodoni Bold + italic_ 80 | * _Bodoni Bold Condensed_ (Sol Hess, 1934) 81 | * **Ludlow**: 82 | * _Bodoni Light + italic_ (Robert Wiebking, 1923) 83 | * _True-Cut Bodoni + italic_ (Wiebking, 1923), based on actual specimens at the Newberry Library. 84 | * _Bodoni Bold + italic_ (Wiebking, 1930) 85 | * _Bodoni Modern + italic_ (R. Hunter Middleton, 1936), probably the most faithful recutting. 86 | * **Damon Type Foundry** offered a Bodoni under the name _Bartlet_. 87 | * **Linotype** and **Intertype** also produced matrices for machine composition that were somewhat narrower than the foundry type versions. 88 | * **Haas Type Foundry** produced a version which was then licensed to D. Stempel AG, Amsterdam Type Foundry, and Berthold.[26]() 89 | * The **Bauer Type Foundry** version was drawn by Heinrich Jost in 1926. The Bauer version emphasizes the extreme contrast between hairline and main stroke. The series included the following weights: 90 | * _Bodoni Roman_ 91 | * _Bodoni Title_ 92 | * _Bodoni Bold_ 93 | * _Bodoni Italic_ 94 | * _Bodoni Italic Bold_ 95 | 96 | 97 | 98 | [image-1]: https://upload.wikimedia.org/wikipedia/commons/thumb/c/ce/Parma-pjt7.jpg/1920px-Parma-pjt7.jpg 99 | [image-2]: https://upload.wikimedia.org/wikipedia/commons/thumb/d/d0/09_Parma_night%2C_Italy_-_%E3%82%A4%E3%82%BF%E3%83%AA%E3%82%A2%E3%81%AE%E3%82%AB%E3%83%95%E3%82%A7.jpg/764px-09_Parma_night%2C_Italy_-_%E3%82%A4%E3%82%BF%E3%83%AA%E3%82%A2%E3%81%AE%E3%82%AB%E3%83%95%E3%82%A7.jpg 100 | [image-3]: https://upload.wikimedia.org/wikipedia/commons/5/55/Giambattista_Bodoni_by_Giuseppe_Lucatelli.jpg 101 | [image-4]: https://upload.wikimedia.org/wikipedia/commons/thumb/4/4f/Quosque_tandem.jpg/800px-Quosque_tandem.jpg 102 | [image-5]: https://upload.wikimedia.org/wikipedia/commons/a/a0/ITCBodoni.png 103 | [image-6]: https://upload.wikimedia.org/wikipedia/en/thumb/2/2b/Bodoni_vita_nuova_facsimile_sepia.png/1920px-Bodoni_vita_nuova_facsimile_sepia.png 104 | -------------------------------------------------------------------------------- /Sample/iOS/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UIApplicationSceneManifest 24 | 25 | UIApplicationSupportsMultipleScenes 26 | 27 | 28 | UIApplicationSupportsIndirectInputEvents 29 | 30 | UILaunchScreen 31 | 32 | UIRequiredDeviceCapabilities 33 | 34 | armv7 35 | 36 | UISupportedInterfaceOrientations 37 | 38 | UIInterfaceOrientationPortrait 39 | UIInterfaceOrientationLandscapeLeft 40 | UIInterfaceOrientationLandscapeRight 41 | 42 | UISupportedInterfaceOrientations~ipad 43 | 44 | UIInterfaceOrientationPortrait 45 | UIInterfaceOrientationPortraitUpsideDown 46 | UIInterfaceOrientationLandscapeLeft 47 | UIInterfaceOrientationLandscapeRight 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /Sample/macOS/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleVersion 22 | 1 23 | LSMinimumSystemVersion 24 | $(MACOSX_DEPLOYMENT_TARGET) 25 | 26 | 27 | -------------------------------------------------------------------------------- /Sample/macOS/macOS.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.files.user-selected.read-only 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Sources/Parma/Composer/CodeElementComposer.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CodeElementComposer.swift 3 | // Parma 4 | // 5 | // Created by leonard on 8/15/20. 6 | // 7 | // Copyright (c) 2020 Leonard Chan 8 | // 9 | // MIT license, see LICENSE file for details 10 | 11 | import SwiftUI 12 | 13 | struct CodeElementComposer: InlineElementComposer { 14 | func text(in context: ComposingContext, render: ParmaRenderable) -> Text { 15 | render.code(context.foundCharacters) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Sources/Parma/Composer/Composer.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Composer.swift 3 | // Parma 4 | // 5 | // Created by leonard on 8/15/20. 6 | // 7 | // Copyright (c) 2020 Leonard Chan 8 | // 9 | // MIT license, see LICENSE file for details 10 | 11 | import Foundation 12 | 13 | @available(iOS 13.0, macOS 10.15, *) 14 | protocol Composer { 15 | /// This method will be called right after entering the element. Context is updated to this element. Store everything needed in this delegate method. 16 | /// - Parameter context: The context needed to compose a view. 17 | func willStart(in context: ComposingContext) 18 | 19 | /// This method will be called right before leaving the element. Context is unpredictable here, it might be empty or ready for composing the next element, so do not access or modify it if there's no special purpose. Recommend to clear things for composer itself in this method. 20 | /// - Parameter context: The context for composing views. 21 | func willStop(in context: ComposingContext) 22 | } 23 | 24 | extension Composer { 25 | func willStart(in context: ComposingContext) { } 26 | 27 | func willStop(in context: ComposingContext) { } 28 | } 29 | -------------------------------------------------------------------------------- /Sources/Parma/Composer/ComposingContext.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ComposingContext.swift 3 | // Parma 4 | // 5 | // Created by leonard on 8/15/20. 6 | // 7 | // Copyright (c) 2020 Leonard Chan 8 | // 9 | // MIT license, see LICENSE file for details 10 | 11 | import SwiftUI 12 | 13 | @available(iOS 13.0, macOS 10.15, *) 14 | class ComposingContext { 15 | /// Element stack. 16 | var stack = [Element]() 17 | 18 | /// Characters found in xml parser delegate. 19 | var foundCharacters: String = "" 20 | 21 | /// A set of `Text` for composing inline or block element which has the ability to compose `Text`. 22 | var texts = [Text]() 23 | 24 | /// A set of `AnyView` for composing block element. 25 | var views = [AnyView]() 26 | 27 | /// The element attributes. 28 | var attributes = [String : String]() 29 | 30 | /// Attributes required to display list elements 31 | var listAttributesStack: [ListAttributes] = [] 32 | 33 | /// Return the element which wrapped the current element if possible. 34 | var superElement: Element? { 35 | let count = stack.count - 2 36 | if count >= 0 && !stack.isEmpty { 37 | return stack[count] 38 | } else { 39 | return nil 40 | } 41 | } 42 | 43 | /// The current processing element. 44 | var currentElement: Element? { 45 | return stack.last 46 | } 47 | 48 | /// If the xml parser found new characters. 49 | var didFindCharacters: Bool { 50 | return foundCharacters != "" 51 | } 52 | 53 | /// Combine all `Text` in the context into one `Text` component. 54 | var concatenatedText: Text { 55 | return texts.reduce(Text(""), +) 56 | } 57 | 58 | /// Push a new element to the element stack. 59 | func enter(in element: Element) { 60 | stack.append(element) 61 | } 62 | 63 | /// Pop the last element in the element stack. 64 | func leaveElement() { 65 | stack = stack.dropLast() 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /Sources/Parma/Composer/ElementComposer.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ElementComposer.swift 3 | // Parma 4 | // 5 | // Created by leonard on 8/15/20. 6 | // 7 | // Copyright (c) 2020 Leonard Chan 8 | // 9 | // MIT license, see LICENSE file for details 10 | 11 | import SwiftUI 12 | 13 | @available(iOS 13.0, macOS 10.15, *) 14 | protocol InlineElementComposer: Composer { 15 | /// Provide relevant information to the render to generate `Text` component. 16 | /// - Parameters: 17 | /// - context: The composing context inside the element. 18 | /// - render: A set of delegate methods for generating `View`s. 19 | func text(in context: ComposingContext, render: ParmaRenderable) -> Text 20 | } 21 | 22 | @available(iOS 13.0, macOS 10.15, *) 23 | protocol BlockElementComposer: Composer { 24 | /// Provide relevant information to the render to generate `Text` component, if the element has the ability. 25 | /// - Parameters: 26 | /// - context: The composing context inside the element. 27 | /// - render: A set of delegate methods for generating `View`s. 28 | func text(in context: ComposingContext, render: ParmaRenderable) -> Text? 29 | 30 | /// Provide relevant information to the render to generate `View` component. 31 | /// - Parameters: 32 | /// - context: The composing context inside the element. 33 | /// - render: A set of delegate methods for generating `View`s. 34 | func view(in context: ComposingContext, render: ParmaRenderable) -> AnyView 35 | } 36 | 37 | extension BlockElementComposer { 38 | func text(in context: ComposingContext, render: ParmaRenderable) -> Text? { 39 | return nil 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Sources/Parma/Composer/EmphasisElementComposer.swift: -------------------------------------------------------------------------------- 1 | // 2 | // EmphasisElementComposer.swift 3 | // Parma 4 | // 5 | // Created by leonard on 8/15/20. 6 | // 7 | // Copyright (c) 2020 Leonard Chan 8 | // 9 | // MIT license, see LICENSE file for details 10 | 11 | import SwiftUI 12 | 13 | struct EmphasisElementComposer: InlineElementComposer { 14 | func text(in context: ComposingContext, render: ParmaRenderable) -> Text { 15 | render.emphasis(textView: context.concatenatedText) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Sources/Parma/Composer/HeadingElementComposer.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HeadingElementComposer.swift 3 | // Parma 4 | // 5 | // Created by leonard on 8/15/20. 6 | // 7 | // Copyright (c) 2020 Leonard Chan 8 | // 9 | // MIT license, see LICENSE file for details 10 | 11 | import SwiftUI 12 | 13 | class HeadingElementComposer: BlockElementComposer { 14 | private var headingLevel: HeadingLevel? 15 | private var count = 1 16 | 17 | func willStart(in context: ComposingContext) { 18 | headingLevel = HeadingLevel.level(context.attributes["level"] ?? "6") 19 | // print("\(count) Heading level set to: " + "\(String(describing: headingLevel))") 20 | count += 1 21 | } 22 | 23 | func willStop(in context: ComposingContext) { 24 | headingLevel = nil 25 | } 26 | 27 | func text(in context: ComposingContext, render: ParmaRenderable) -> Text? { 28 | render.heading(level: headingLevel, textView: context.concatenatedText) 29 | } 30 | 31 | func view(in context: ComposingContext, render: ParmaRenderable) -> AnyView { 32 | guard let view = context.views.last else { return AnyView(EmptyView()) } 33 | return render.headingBlock(level: headingLevel, view: view) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Sources/Parma/Composer/ImageElementComposer.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ImageElementComposer.swift 3 | // Parma 4 | // 5 | // Created by leonard on 8/15/20. 6 | // 7 | // Copyright (c) 2020 Leonard Chan 8 | // 9 | // MIT license, see LICENSE file for details 10 | 11 | import SwiftUI 12 | 13 | class ImageElementComposer: BlockElementComposer { 14 | private var startIndex: Int = 0 15 | private var destination = "" 16 | 17 | func willStart(in context: ComposingContext) { 18 | startIndex = context.views.count 19 | destination = context.attributes["destination"] ?? "" 20 | } 21 | 22 | func willStop(in context: ComposingContext) { 23 | destination = "" 24 | startIndex = 0 25 | } 26 | 27 | func view(in context: ComposingContext, render: ParmaRenderable) -> AnyView { 28 | if startIndex == context.views.count { 29 | // No alt text 30 | return render.imageView(with: destination, altTextView: nil) 31 | } else { 32 | // Has alt text 33 | let altTextView = context.views.last 34 | context.views = context.views.dropLast() 35 | return render.imageView(with: destination, altTextView: altTextView) 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Sources/Parma/Composer/LinkElementComposer.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LinkElementComposer.swift 3 | // Parma 4 | // 5 | // Created by leonard on 8/15/20. 6 | // 7 | // Copyright (c) 2020 Leonard Chan 8 | // 9 | // MIT license, see LICENSE file for details 10 | 11 | import SwiftUI 12 | 13 | class LinkElementComposer: InlineElementComposer { 14 | var destination: String? 15 | 16 | func willStart(in context: ComposingContext) { 17 | destination = context.attributes["destination"] 18 | } 19 | 20 | func willStop(in context: ComposingContext) { 21 | destination = nil 22 | } 23 | 24 | func text(in context: ComposingContext, render: ParmaRenderable) -> Text { 25 | return render.link(textView: context.concatenatedText, destination: destination) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Sources/Parma/Composer/ListElementComposer.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ListElementComposer.swift 3 | // Parma 4 | // 5 | // Created by leonard on 8/15/20. 6 | // 7 | // Copyright (c) 2020 Leonard Chan 8 | // 9 | // MIT license, see LICENSE file for details 10 | 11 | import SwiftUI 12 | 13 | class ListElementComposer: BlockElementComposer { 14 | private var index = [Int]() 15 | 16 | func willStart(in context: ComposingContext) { 17 | var attributes = ListAttributes.defaultAttributes 18 | 19 | if let typeAttribute = context.attributes["type"], let listType = ListType(rawValue: typeAttribute) { 20 | attributes.type = listType 21 | } 22 | 23 | if let typeAttribute = context.attributes["delim"], let listDelimiter = ListDelimiter(rawValue: typeAttribute) { 24 | attributes.delimiter = listDelimiter 25 | } 26 | 27 | context.listAttributesStack.append(attributes) 28 | 29 | index.append(context.views.count) 30 | } 31 | 32 | func willStop(in context: ComposingContext) { 33 | index = index.dropLast() 34 | context.listAttributesStack.removeLast() 35 | } 36 | 37 | func view(in context: ComposingContext, render: ParmaRenderable) -> AnyView { 38 | let maxIndex = context.views.count 39 | let minIndex = index.last! 40 | 41 | // Get every view inside this element scope 42 | let views = Array(context.views[minIndex.. 1 { 50 | let count = views.count 51 | return AnyView( 52 | VStack(alignment: .leading, spacing: 0) { 53 | ForEach(0.. 8 | // 9 | // MIT license, see LICENSE file for details 10 | 11 | import SwiftUI 12 | 13 | class ListItemElementComposer: BlockElementComposer { 14 | private var index = [Int]() 15 | 16 | func willStart(in context: ComposingContext) { 17 | index.append(context.views.count) 18 | } 19 | 20 | func willStop(in context: ComposingContext) { 21 | index = index.dropLast() 22 | } 23 | 24 | func view(in context: ComposingContext, render: ParmaRenderable) -> AnyView { 25 | let maxIndex = context.views.count 26 | let minIndex = index.last! 27 | let attributes = context.listAttributesStack.last ?? ListAttributes.defaultAttributes 28 | let normalizedIndexes: [Int] = index.enumerated() 29 | .map({ (elementIndex, element) in 30 | var correctedElement = element 31 | if elementIndex > 0 { 32 | correctedElement = element - (index[elementIndex - 1] + 1) 33 | } 34 | return correctedElement + 1 35 | }) 36 | 37 | // Get every view inside this element scope 38 | let views = Array(context.views[minIndex.. 1 { 46 | let count = views.count 47 | return render.listItem(attributes: attributes, index: normalizedIndexes, view: AnyView( 48 | VStack(alignment: .leading, spacing: 0) { 49 | ForEach(0.. 8 | // 9 | // MIT license, see LICENSE file for details 10 | 11 | import SwiftUI 12 | 13 | class ParagraphElementComposer: BlockElementComposer { 14 | private var index = [Int]() 15 | 16 | func willStart(in context: ComposingContext) { 17 | index.append(context.views.count) 18 | } 19 | 20 | func willStop(in context: ComposingContext) { 21 | index = index.dropLast() 22 | } 23 | 24 | func view(in context: ComposingContext, render: ParmaRenderable) -> AnyView { 25 | let maxIndex = context.views.count 26 | let minIndex = index.last! 27 | 28 | // Get every view inside this element scope 29 | let views = Array(context.views[minIndex.. 1 { 37 | let count = views.count 38 | return render.paragraphBlock(view: AnyView( 39 | VStack(alignment: .leading) { 40 | ForEach(0.. 8 | // 9 | // MIT license, see LICENSE file for details 10 | 11 | import SwiftUI 12 | 13 | struct PlainTextComposer: InlineElementComposer { 14 | func text(in context: ComposingContext, render: ParmaRenderable) -> Text { 15 | render.plainText(context.foundCharacters) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Sources/Parma/Composer/StrongElementComposer.swift: -------------------------------------------------------------------------------- 1 | // 2 | // StrongElementComposer.swift 3 | // Parma 4 | // 5 | // Created by leonard on 8/15/20. 6 | // 7 | // Copyright (c) 2020 Leonard Chan 8 | // 9 | // MIT license, see LICENSE file for details 10 | 11 | import SwiftUI 12 | 13 | struct StrongElementComposer: InlineElementComposer { 14 | func text(in context: ComposingContext, render: ParmaRenderable) -> Text { 15 | render.strong(textView: context.concatenatedText) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Sources/Parma/Composer/UnknownElementComposer.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UnknownElementComposer.swift 3 | // Parma 4 | // 5 | // Created by leonard on 8/15/20. 6 | // 7 | // Copyright (c) 2020 Leonard Chan 8 | // 9 | // MIT license, see LICENSE file for details 10 | 11 | import SwiftUI 12 | 13 | struct UnknownElementComposer: BlockElementComposer { 14 | func text(in context: ComposingContext, render: ParmaRenderable) -> Text? { 15 | guard !context.foundCharacters.isEmpty else { return nil } 16 | return render.plainText(context.foundCharacters) 17 | } 18 | 19 | func view(in context: ComposingContext, render: ParmaRenderable) -> AnyView { 20 | guard let view = context.views.last else { return AnyView(EmptyView()) } 21 | context.views = context.views.dropLast() 22 | return render.paragraphBlock(view: view) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Sources/Parma/Element/Element.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Element.swift 3 | // Parma 4 | // 5 | // Created by leonard on 8/15/20. 6 | // 7 | // Copyright (c) 2020 Leonard Chan 8 | // 9 | // MIT license, see LICENSE file for details 10 | 11 | import Foundation 12 | 13 | /// Markdown elements. 14 | enum Element: Hashable { 15 | case text, heading, paragraph, list, item, image, strong, emphasis, link, code, unknown, codeBlock, blockQuote 16 | 17 | /// If the specific element works as inline. 18 | var isInline: Bool { 19 | switch self { 20 | case .text, .strong, .emphasis, .link, .code: 21 | return true 22 | default: 23 | return false 24 | } 25 | } 26 | 27 | /// Get `Element` by string. For example, input "strong" will return `Element.strong`. 28 | static func element(_ elementText: String) -> Element { 29 | switch elementText { 30 | case "text": 31 | return Self.text 32 | case "strong": 33 | return Self.strong 34 | case "emph": 35 | return Self.emphasis 36 | case "link": 37 | return Self.link 38 | case "code": 39 | return Self.code 40 | case "heading": 41 | return Self.heading 42 | case "paragraph": 43 | return Self.paragraph 44 | case "list": 45 | return Self.list 46 | case "item": 47 | return Self.item 48 | case "image": 49 | return Self.image 50 | // case "code_block": 51 | // return Self.codeBlock 52 | // case "block_quote": 53 | // return Self.blockQuote 54 | default: 55 | return Self.unknown 56 | } 57 | } 58 | 59 | /// The readable name for the element. 60 | func name() -> String { 61 | switch self { 62 | case .heading: 63 | return "heading" 64 | case .paragraph: 65 | return "paragraph" 66 | case .list: 67 | return "list" 68 | case .item: 69 | return "item" 70 | case .image: 71 | return "image" 72 | case .text: 73 | return "text" 74 | case .strong: 75 | return "strong" 76 | case .emphasis: 77 | return "emph" 78 | case .code: 79 | return "code" 80 | case .link: 81 | return "link" 82 | // case .codeBlock: 83 | // return "code_block" 84 | // case .blockQuote: 85 | // return "block_quote" 86 | default: 87 | return "unknown" 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /Sources/Parma/Element/HeadingLevel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HeadingLevel.swift 3 | // Parma 4 | // 5 | // Created by leonard on 8/15/20. 6 | // 7 | // Copyright (c) 2020 Leonard Chan 8 | // 9 | // MIT license, see LICENSE file for details 10 | 11 | import Foundation 12 | 13 | /// The markdown heading levels. 14 | public enum HeadingLevel: String { 15 | case one = "1" 16 | case two = "2" 17 | case three = "3" 18 | case four = "4" 19 | case five = "5" 20 | case six = "6" 21 | 22 | /// Get `HeadingLevel` by string. For example, input "1" will return `HeadingLevel.one`. 23 | static func level(_ text: String) -> HeadingLevel { 24 | switch text { 25 | case "1": 26 | return Self.one 27 | case "2": 28 | return Self.two 29 | case "3": 30 | return Self.three 31 | case "4": 32 | return Self.four 33 | case "5": 34 | return Self.five 35 | case "6": 36 | return Self.six 37 | default: 38 | fatalError("Invalid heading level.") 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Sources/Parma/Element/ListAttributes.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ListAttributes.swift 3 | // Parma 4 | // 5 | // Created by Antoine Lamy on 5/13/21. 6 | // 7 | // Copyright (c) 2020 Leonard Chan 8 | // 9 | // MIT license, see LICENSE file for details 10 | 11 | import Foundation 12 | 13 | /// Attributes used to display a list element. 14 | public struct ListAttributes { 15 | /// Type of the list, can either be ordered or non-ordered (bullet) 16 | public internal(set) var type: ListType 17 | 18 | /** 19 | Type of delimiter to use in the case of an ordered list. 20 | 21 | A dot list delimiter should produce a list like: 22 | ~~~ 23 | 1. Item 1 24 | 2. Item 2 25 | 3. Item 3 26 | ~~~ 27 | 28 | While a parenthesis list delimiter should produce a list like: 29 | ~~~ 30 | 1) Item 1 31 | 2) Item 2 32 | 3) Item 3 33 | ~~~ 34 | */ 35 | public internal(set) var delimiter: ListDelimiter 36 | 37 | static var defaultAttributes: ListAttributes { 38 | ListAttributes(type: .bullet, delimiter: .period) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Sources/Parma/Element/ListDelimiter.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ListDelimiter.swift 3 | // Parma 4 | // 5 | // Created by Antoine Lamy on 5/13/21. 6 | // 7 | // Copyright (c) 2020 Leonard Chan 8 | // 9 | // MIT license, see LICENSE file for details 10 | 11 | import Foundation 12 | 13 | /// The types for markdown ordered list delimiters. 14 | public enum ListDelimiter: String { 15 | case period = "period" 16 | case parenthesis = "paren" 17 | } 18 | -------------------------------------------------------------------------------- /Sources/Parma/Element/ListType.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ListType.swift 3 | // Parma 4 | // 5 | // Created by leonard on 8/15/20. 6 | // 7 | // Copyright (c) 2020 Leonard Chan 8 | // 9 | // MIT license, see LICENSE file for details 10 | 11 | import Foundation 12 | 13 | /// The types for markdown list. 14 | public enum ListType: String { 15 | case ordered, bullet 16 | } 17 | -------------------------------------------------------------------------------- /Sources/Parma/Parma.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Parma.swift 3 | // Parma 4 | // 5 | // Created by leonard on 8/15/20. 6 | // 7 | // Copyright (c) 2020 Leonard Chan 8 | // 9 | // MIT license, see LICENSE file for details 10 | 11 | import SwiftUI 12 | 13 | public struct Parma: View { 14 | // MARK: - Property 15 | private var core: ParmaCore? 16 | private var errorView: AnyView? 17 | private var content: AnyView? 18 | private var alignment: HorizontalAlignment = .leading 19 | 20 | // MARK: - Public property 21 | public var body: some View { 22 | content != nil ? AnyView(VStack(alignment: alignment) { content }) : errorView 23 | } 24 | 25 | // MARK: - Initialization 26 | 27 | /// Create a Parma view with markdown string. 28 | /// - Parameters: 29 | /// - markdown: The markdown string for generating Parma view. 30 | /// - alignment: The guide for aligning the subviews in this stack. It has the same horizontal screen coordinate for all children. Default is leading alignment. 31 | /// - render: Specify a custom render to give the view different appearance. Default is nil, will use `ParmaRender`. 32 | /// - errorContent: The content view to display if some error occurred while parsing markdown. 33 | public init(_ markdown: String, alignment: HorizontalAlignment = .leading, render: ParmaRenderable? = nil, errorContent: ((Error) -> AnyView)? = nil) { 34 | core = nil 35 | errorView = nil 36 | content = nil 37 | self.alignment = alignment 38 | 39 | do { 40 | core = try ParmaCore(markdown) 41 | if let render = render { 42 | core?.render = render 43 | } 44 | core?.start() 45 | content = core?.composedView 46 | } catch { 47 | errorView = errorContent?(error) 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /Sources/Parma/ParmaCore.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ParmaCore.swift 3 | // Parma 4 | // 5 | // Created by leonard on 8/16/20. 6 | // 7 | // Copyright (c) 2020 Leonard Chan 8 | // 9 | // MIT license, see LICENSE file for details 10 | 11 | import SwiftUI 12 | import Down 13 | 14 | public typealias Text = SwiftUI.Text 15 | 16 | @available(iOS 13.0, macOS 10.15, *) 17 | /// The main logic of Parma. 18 | class ParmaCore: NSObject { 19 | // MARK: - Class property 20 | 21 | // Composer collections 22 | private var inlineComposers: [Element : InlineElementComposer] = [:] 23 | private var blockComposers: [Element : BlockElementComposer] = [:] 24 | 25 | // Composers 26 | private let plaintTextComposer = PlainTextComposer() 27 | private let strongElementComposer = StrongElementComposer() 28 | private let emphasisElementComposer = EmphasisElementComposer() 29 | private let linkElementComposer = LinkElementComposer() 30 | private let codeElementComposer = CodeElementComposer() 31 | private let headingElementComposer = HeadingElementComposer() 32 | private let paragraphElementComposer = ParagraphElementComposer() 33 | private let imageElementComposer = ImageElementComposer() 34 | private let listElementComposer = ListElementComposer() 35 | private let listItemElementComposer = ListItemElementComposer() 36 | private let unknownElementComposer = UnknownElementComposer() 37 | 38 | private let parser: XMLParser 39 | 40 | // Generated views 41 | private var views: Array = [] 42 | 43 | // Temporary storage 44 | private var texts: Array = [] 45 | private var foundCharacters = "" 46 | private var concatenatedText: Text { 47 | return texts.reduce(Text(""), +) 48 | } 49 | 50 | // MARK: - Public property 51 | var composedView: AnyView { 52 | AnyView( 53 | ForEach(0..` from causing problems 108 | private func escapeContent(_ rawContent: String) -> String { 109 | 110 | enum EscapedCharacters: String, CaseIterable { 111 | 112 | case leftAngleBracket = "<", 113 | rightAngleBracket = ">" 114 | 115 | func replacement() -> String { 116 | switch self { 117 | case .leftAngleBracket: 118 | return "<" 119 | case .rightAngleBracket: 120 | return ">" 121 | } 122 | } 123 | 124 | static func escapeString(_ string: String) -> String { 125 | var escapedValue = string 126 | 127 | self.allCases.forEach { 128 | escapedValue = escapedValue.replacingOccurrences(of: $0.rawValue, with: $0.replacement()) 129 | } 130 | 131 | return escapedValue 132 | } 133 | } 134 | 135 | return EscapedCharacters.escapeString(rawContent) 136 | } 137 | 138 | // MARK: - XML parsing logic 139 | extension ParmaCore: XMLParserDelegate { 140 | func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String] = [:]) { 141 | // Start new element 142 | let element = Element.element(elementName) 143 | 144 | if element != .unknown { 145 | context.enter(in: element) 146 | } 147 | 148 | context.attributes = attributeDict 149 | 150 | if element.isInline { 151 | inlineComposers[element]?.willStart(in: context) 152 | } else { 153 | blockComposers[element]?.willStart(in: context) 154 | } 155 | } 156 | 157 | func parser(_ parser: XMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) { 158 | let element = Element.element(elementName) 159 | 160 | if element.isInline { 161 | if let text = inlineComposers[element]?.text(in: context, render: render) { 162 | if let superEl = context.superElement, superEl.isInline { 163 | context.texts = [] 164 | context.texts.append(text) 165 | } else { 166 | context.texts = [] 167 | texts.append(text) 168 | context.texts = texts 169 | } 170 | } 171 | 172 | inlineComposers[element]?.willStop(in: context) 173 | } else { 174 | if let text = blockComposers[element]?.text(in: context, render: render) { 175 | context.views.append(AnyView(text)) 176 | } else { 177 | if texts.count != 0 { 178 | context.views.append(AnyView(concatenatedText)) 179 | } 180 | } 181 | 182 | texts = [] 183 | context.texts = [] 184 | 185 | if let view = blockComposers[element]?.view(in: context, render: render) { 186 | if context.stack.count > 1 { 187 | context.views.append(view) 188 | } else { 189 | context.views = [] 190 | views.append(view) 191 | } 192 | } 193 | 194 | blockComposers[element]?.willStop(in: context) 195 | } 196 | 197 | context.foundCharacters = "" 198 | 199 | if element != .unknown { 200 | context.leaveElement() 201 | } 202 | } 203 | 204 | func parser(_ parser: XMLParser, foundCharacters string: String) { 205 | guard string.trimmingCharacters(in: .whitespacesAndNewlines) != "" else { return } 206 | context.foundCharacters += string.trimmingCharacters(in: .newlines) 207 | } 208 | } 209 | -------------------------------------------------------------------------------- /Sources/Parma/Render/ParmaRender.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ParmaRender.swift 3 | // Parma 4 | // 5 | // Created by leonard on 8/15/20. 6 | // 7 | // Copyright (c) 2020 Leonard Chan 8 | // 9 | // MIT license, see LICENSE file for details 10 | 11 | import Foundation 12 | 13 | /// The concrete class of the default render style. Create a new render if custom styles are needed. 14 | final public class ParmaRender: ParmaRenderable { } 15 | -------------------------------------------------------------------------------- /Sources/Parma/Render/ParmaRenderable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ParmaRenderable.swift 3 | // Parma 4 | // 5 | // Created by leonard on 8/15/20. 6 | // 7 | // Copyright (c) 2020 Leonard Chan 8 | // 9 | // MIT license, see LICENSE file for details 10 | 11 | import SwiftUI 12 | 13 | /// The appearance of each element. Create a custom render then conform to this protocol. 14 | public protocol ParmaRenderable { 15 | /// Define the heading text style. 16 | /// - Parameters: 17 | /// - level: The level of heading. 18 | /// - textView: The textView generated from captured heading string. 19 | func heading(level: HeadingLevel?, textView: Text) -> Text 20 | 21 | /// Define the paragraph text style. 22 | /// - Parameter text: The text string captured from paragraph. 23 | func paragraph(text: String) -> Text 24 | 25 | /// Define the text style for plain text. Do NOT recommend to alter this if there's no special purpose. 26 | /// - Parameter text: The text string captured from markdown. 27 | func plainText(_ text: String) -> Text 28 | 29 | /// Define the strong text style. 30 | /// - Parameter textView: The textView generated from captured strong string. 31 | func strong(textView: Text) -> Text 32 | 33 | /// Define the emphasis text style. 34 | /// - Parameter textView: The textView generated from captured emphasis string. 35 | func emphasis(textView: Text) -> Text 36 | 37 | /// Define the link text style. 38 | /// - Parameters: 39 | /// - textView: The textView generated from captured link string. 40 | /// - destination: The destination of the link. 41 | func link(textView: Text, destination: String?) -> Text 42 | 43 | /// Define the code text style. 44 | /// - Parameter text: The text string captured from code. 45 | func code(_ text: String) -> Text 46 | 47 | /// Define the style of heading view. 48 | /// - Parameters: 49 | /// - level: The level of heading. 50 | /// - view: The view contains heading text. 51 | func headingBlock(level: HeadingLevel?, view: AnyView) -> AnyView 52 | 53 | /// Define the style of paragraph view. 54 | /// - Parameter view: The view contains view(s) which belong(s) to this paragraph. 55 | func paragraphBlock(view: AnyView) -> AnyView 56 | 57 | /// Define the style of list item. 58 | /// - Parameter attributes: Attributes of the list containing the item. Those must be considered for proper item rendering. 59 | /// - Parameter index: Normalized index of the list item. For exemple, the index of the third item of a one level list would be `[2]` and the second item of a sublist appearing fourth in it's parent list would be `[3, 1]`. 60 | /// - Parameter view: The view contains view(s) which belong(s) to this item. 61 | func listItem(attributes: ListAttributes, index: [Int], view: AnyView) -> AnyView 62 | 63 | /// Define the style of image view. 64 | /// - Parameter urlString: The url string for this image view. 65 | /// - Parameter altTextView: The view contains alt text. 66 | func imageView(with urlString: String, altTextView: AnyView?) -> AnyView 67 | } 68 | 69 | // MARK: - Default render style 70 | extension ParmaRenderable { 71 | public func plainText(_ text: String) -> Text { 72 | Text(text) 73 | } 74 | 75 | public func strong(textView: Text) -> Text { 76 | textView.bold() 77 | } 78 | 79 | public func emphasis(textView: Text) -> Text { 80 | textView.italic() 81 | } 82 | 83 | public func link(textView: Text, destination: String?) -> Text { 84 | return textView 85 | } 86 | 87 | public func code(_ text: String) -> Text { 88 | Text(text).font(.system(.body, design: .monospaced)) 89 | } 90 | 91 | public func heading(level: HeadingLevel?, textView: Text) -> Text { 92 | switch level { 93 | case .one: 94 | return textView.font(.largeTitle) 95 | case .two: 96 | return textView.font(.title) 97 | default: 98 | return textView.font(.title) 99 | } 100 | } 101 | 102 | public func paragraph(text: String) -> Text { 103 | Text(text).font(.body) 104 | } 105 | 106 | public func headingBlock(level: HeadingLevel?, view: AnyView) -> AnyView { 107 | AnyView(view.padding(.bottom, 12)) 108 | } 109 | 110 | public func paragraphBlock(view: AnyView) -> AnyView { 111 | AnyView(view.fixedSize(horizontal: false, vertical: true).padding(.bottom, 8)) 112 | } 113 | 114 | public func listItem(attributes: ListAttributes, index: [Int], view: AnyView) -> AnyView { 115 | let delimiter: String 116 | switch attributes.delimiter { 117 | case .period: 118 | delimiter = "." 119 | case .parenthesis: 120 | delimiter = ")" 121 | } 122 | 123 | let separator: String 124 | switch attributes.type { 125 | case .bullet: 126 | separator = index.count % 2 == 1 ? "•" : "◦" 127 | case .ordered: 128 | separator = index 129 | .map({ String($0) }) 130 | .joined(separator: ".") 131 | .appending(delimiter) 132 | } 133 | 134 | return AnyView( 135 | HStack(alignment: .top, spacing: 4) { 136 | Text(separator) 137 | view 138 | } 139 | ) 140 | } 141 | 142 | public func imageView(with urlString: String, altTextView: AnyView?) -> AnyView { 143 | if urlString.isEmpty { 144 | return altTextView ?? AnyView(EmptyView()) 145 | } else { 146 | return AnyView(Text(urlString)) 147 | } 148 | } 149 | } 150 | -------------------------------------------------------------------------------- /Tests/LinuxMain.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | 3 | import ParmaTests 4 | 5 | var tests = [XCTestCaseEntry]() 6 | tests += ParmaTests.allTests() 7 | XCTMain(tests) 8 | -------------------------------------------------------------------------------- /Tests/ParmaTests/ParmaTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | //@testable import Parma 3 | 4 | final class ParmaTests: XCTestCase { 5 | func testExample() { 6 | // This is an example of a functional test case. 7 | // Use XCTAssert and related functions to verify your tests produce the correct 8 | // results. 9 | // XCTAssertEqual(Parma().text, "Hello, World!") 10 | } 11 | 12 | static var allTests = [ 13 | ("testExample", testExample), 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /Tests/ParmaTests/XCTestManifests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | 3 | #if !canImport(ObjectiveC) 4 | public func allTests() -> [XCTestCaseEntry] { 5 | return [ 6 | testCase(ParmaTests.allTests), 7 | ] 8 | } 9 | #endif 10 | --------------------------------------------------------------------------------