Compare commits

...

97 Commits

Author SHA1 Message Date
Sven e754ab1c80 Provide access to the list delimiter (#275)
* Provide access to the list delimiter

* Fix test
2021-10-18 13:22:18 +02:00
Sergey Pimenov 3b07bb52cf [Fix] DownTextView: Trigger re-render on styler change (#271)
Co-authored-by: John Nguyen <polyxo@protonmail.com>
2021-08-21 09:27:29 +02:00
John Nguyen 055f818ed7 Add codecov threshold (#272) 2021-08-21 09:07:28 +02:00
Oliver Fox 9997dc00cb RTL support in lists (#261)
- Added text alignment option to lists

Co-authored-by: John Nguyen <polyxo@protonmail.com>
2021-08-21 08:13:29 +02:00
Erik Kerber e2b597d469 [Chore] Add arm64 to simulator supported archs (#265) 2021-07-28 18:06:09 +02:00
John Nguyen bf24fcbb2d [Changes] v0.11.0 2021-05-04 21:56:02 +02:00
John Nguyen f34b166be1 [Pod] Bump to v0.11.0 2021-05-04 21:40:58 +02:00
Loïc Dardant 0586cec03b [Feature] Custom list prefixes for AttributedStringVisitor (#255)
* [Feature] Custom list prefixes for AttributedStringVisitor

* [Feature] Custom list prefixes for AttributedStringVisitor -- code review

Co-authored-by: Loïc DARDANT <loicdardant@MacBook-Pro-de-Loic.local>
2021-04-28 08:45:44 +02:00
John Nguyen 2524b62470 [Chore] Add SwiftLint (#252)
* Add swiftlint

* Fix trailing whitespace

* Fix vertical whitespace

* Fix trailing newline

* Fix opening brace

* Fix trailing comma

* Fix colon

* Fix comma

* Fix control statement

* Fix orphaned doc comment

* Fix void return

* Fix legacy constructor

* Fix unused closure parameter

* Fix type name

* Fix identifier name

* Configure large tuple

* Configure cyclomatic complexity

* Fix force try

* Fix xctfail message

* Fix force cast

* Fix test compilation

* Use snapshots for binding tests

* Fix line length

* Add swiftlint github action

* Clean up
2021-03-21 10:03:26 +01:00
John Nguyen f83e9a2566 [Chore] Fix codecov report (#251)
* Move snapshot tests to main scheme

* Update config files

* Fix conditions

* Bump test deployment version

* Fix ignored paths

* Fix ignored paths... again

* Try uploading coverage after each test
2021-03-19 22:07:04 +01:00
John Nguyen 3ac921e3a9 Update README.md 2021-02-28 15:30:47 +01:00
John Nguyen d127a624d3 [Changes] v0.10.0 2021-02-28 15:12:09 +01:00
John Nguyen 0bcd20dc56 [Pod] Bump to v0.10.0 2021-02-28 14:49:53 +01:00
John Nguyen 4fb13c2fac [Chore] Reorganize project structure for SPM (#248)
* Adjust folder structure to match Swift package structure

* Update package manifest

* Add bundle helper

# Conflicts:
#	Sources/Down/Views/DownView.swift

* Add bundle helper to xcode proj

* Update codecov config

* Update build phase script

* Update podspec

* Try to fix podspec

* Try to fix podspec again
2021-02-28 14:26:02 +01:00
Michael Knoch 4c1c888152 [Chore] Add arm64 as valid arch when building for simulator on M1 macs (#249)
Co-authored-by: micha <micha@m1-ci.flowkeyvpn>
2021-02-27 20:49:16 +01:00
Maxim V. Potapov 5abcbcca06 [Improvement] Expose DownTextView's designated initializer (#250) 2021-02-27 14:41:01 +01:00
John Nguyen 69c7029e1f [Chore] Use SPM to manage snapshot testing dependency (#247)
* Use SPM to manage snapshot testing

* Re-record snapshots

* Update travis config for Xcode 12

* Fix travis config

* Fix travis config again
2021-02-21 21:50:02 +01:00
John Nguyen 21d522d876 [Changes] v0.9.5 2021-02-12 21:16:01 +01:00
John Nguyen f2e4658f79 [Pod] Bump to v0.9.5 2021-02-12 20:53:49 +01:00
claurel 277507d0af [Fix] Compilation failure with Xcode 12.5 and SPM(#245) 2021-02-12 20:34:56 +01:00
John Nguyen cbe21adfdc [Chore] Update readme (#237) 2020-12-05 17:59:00 +01:00
Rob Phillips 5a0b527000 Changelog for v0.9.4 2020-10-21 10:49:19 -04:00
Rob Phillips 731f6bbab2 [Pod] Bump to v0.9.4 2020-10-21 10:39:58 -04:00
John Nguyen 8f380a5558 [Fix] DownTextView renders incorrect link color (#233) 2020-10-21 10:35:18 -04:00
Sven 6689a8fb6b Create custom sequence to access child nodes (#228)
* Create sequence type for child nodes.

* Directly convert DownRenderable to Document

* Remove childSequence requirement from Node protocol. Add to the extension instead.

* Remove toDocument requirement from the DownASTRenderable protocol.

* Make documentation for DownASTRenderable.toDocument more clear

Co-authored-by: Rob Phillips <rob@getkeepsafe.com>
2020-10-09 14:03:52 -04:00
Ken Morse 968ef0d4ba Added instructions for using the Swift Package Manager (#230) 2020-10-08 19:14:01 -04:00
Sven fdfa661aa7 Use case let as instead of case is and force casting later. (#227) 2020-10-05 14:03:54 -04:00
Jasmin Lapalme ff68cfec88 Add macOS arm64 platform (#224) 2020-08-22 11:34:46 -04:00
rob phillips 296ad5409a Correct Swift versions in readme 2020-06-13 09:12:01 -06:00
Rob Phillips a23efb1527 v0.9.3 changes 2020-06-12 09:37:55 -06:00
Rob Phillips 427aec0a0a Bump to v0.9.3 2020-06-12 09:33:29 -06:00
John Nguyen 6638a36b26 Add tightness property to List node (#215)
* Add tightness property to List node

* Fix comment

* Update test

Co-authored-by: rob phillips <rob@robphillips.me>
2020-06-12 05:29:36 -10:00
John Nguyen c389ca6624 [Chore] Bump swift snapshot testing to 1.7.2 (#216)
* Bump swift snapshot testing to 1.7.2

* Fix snapshot sizes

* Update snapshots with bullet points

* Bump to Xcode 11.5

* Use Xcode 11.4 on Travis

* Revert "Update snapshots with bullet points"

This reverts commit e02f098756.
2020-06-12 08:30:21 -06:00
Brunno Braga dd2a448eb4 [DownView] Add parameter so bundle is writable (#200)
* adding parameter for bundle to be writable

* unit test for user writable bundle

* simulator do not enforce app sandbox so no need to copy

Co-authored-by: Brunno Braga <brunno.w.braga@exxonmobil.com>
2020-04-24 14:11:49 -10:00
Max Bothe de6c58760f Add styling options for level 4 to 6 headings (#207)
* Add styling options for level 4 to 6 headings

* Adjust colors
2020-03-19 11:08:08 -10:00
Rob Phillips 2aada56e6a [Down] Bump to 0.9.2 2020-03-03 10:07:01 -10:00
Steve Baranski 69a006cd1b Swift 5.1 Support (#204)
* Updated project for Swift 5.1 support

* Updated xcconfig files & removed superfluous project overrides

* [Example] Update example app settings

Co-authored-by: rob phillips <rob@robphillips.me>
2020-03-03 10:05:14 -10:00
Rob Phillips 79c3d29f13 [Down] Bump to v0.9.1 2020-02-27 19:24:52 -10:00
Steve Baranski 907d67cb59 Resolves Swift Package Manager issue related to swift-snapshot-testing (#203)
* Tidied up some formatting inconsistencies in Package.swift

* Modified SwiftPM testTarget specification to exclude DownSnapshotTests

* Applied some final clarifying changes to Package.swift
2020-02-27 19:19:17 -10:00
Mathew cd1a3f6565 Improve configurability of DownStyler (#188)
* Make styling option initializers public

* Add public memberwise initializer

* Make ParagraphStyleCollection a protocol

Make ParagraphStyleCollection a protocol and add StaticParagraphStyleCollection struct conforming to protocol.

* Make relevant properties and methods public

* Fix paragraph style instantiation
2019-11-12 09:28:58 -05:00
John Nguyen b99cbca24f Make color & font collection initializers public (#184) 2019-10-22 10:17:15 -04:00
rob phillips 0095468027 Add support for Linux 2019-10-08 22:45:37 -04:00
Vlad Gorlov c20e8e2d4c Added Linux support. (#172)
* Added check for os(Linux)

* Sources adopted to Swift Linux Compiler v5.0

* Added Docker configuration to be used for Linux builds.

* Renamed Script.

* Docker configuration update.

* Fixes Linux compile errors.

* Nicification.
2019-10-08 22:43:35 -04:00
Rob Phillips 5aa5a55193 [Changes] v0.9.0 w/ breaking change 2019-10-06 21:11:44 -04:00
Rob Phillips 940b173fc1 [Pod] Bump to v0.9.0 with breaking change 2019-10-06 18:46:57 -04:00
John Nguyen 02d90cc5ff [Feature] Create default Styler for attributed string rendering (#177)
* Add stubs

* Add some helper methods

* Add very basic styling

* Add custom dynamic type for code

* Clean up

* Allow DebugVisitor methods to be overridden

* Add method to calculate list depth

* Pass the list nest depth to the styler

* Move nest depth property to base node

* Add helper to get parent

* Add property to check for top level paragraphs

* Add test

* Pass top level flag to paragraph styler

* Only add pargraph style for top level paragraphs

* Create ListItemPrefixGenerator

* Use list item prefix generator

* Fix debug description

* WIP: list item styling

* Add tests

* Tidy up

* Use paragraph separator code point

* Add list markers

* Add todo

* Add tests

* Tidy up

* Calculate ranges of paragraphs excluding lists

* Add item styling stubs

* Format indentation of nested liists

* Refactor item styling

* Return self if prefix length exceeds bounds

* Add spacing after heading

* Tidy up

* Add todo

* Organize tests

* Rename method

* Add test stubs

* Add tests

* Reorganize files

* Add tests

* Loosen coupling between List and ListItemPrefixGenerator

* Add snapshot testing framework

* Bump minimum deployment to iOS 10 for test target

* Refactor FontBook into FontCollection

* Inject fonts into DefaultStyler

* Create ParagraphStyleCollection & inject into DefaultStyler

* Tidy up

* Create ColorCollection & inject into Default Styler

* Style block quote

* Style code blocks

* Add colors to headings, text and inline code

* Move AttributeCollection into new file

* Organize file structure

* Rename item paragraph styler

* Style list item prefix in the styler

* Make ListItemParagraphStyler configurable

* Add base test suite for styler

* Tidy up

* Add test stubs for list items

* Fix prefix indentation

* Add item prefix tests

* Allow styler properties to be externally configured

* Refactor styler test suite

* Make ListItemParargraphStyler a class

* Clean up

* Add new item styling tests

* Ignore some test stubs

* Use snapshots for visitor tests

* Add snapshots for strong, emphasized, code and html styles

* Clean up

* Explicitly set point size after adding font trait

* Add monospace trait to font extension

* Allow monospace font in headings

* Use heading level when styling

* Make test properties private

* Add heading style tests

* Add todos

* Use line separators in code blocks

* Add code paragraph style

* Add support for custom thematic break attribute

* Add DownTextView

* Add thematic break to color collection

* Add test for thematic break style

* Append newline instead of line separator after thematic break

* Add support for custom quote stripe attribute

* Translate thematic break rect to container origin

* Translate stripe by container origin

* Clean up

* Remove insets property & use origin parameter

* Clean up

* Add quote stripe options

* Move list item options to new file

* Add quote styling tests

* Allow thematic break to be configured

* Test thematic break preservation in block quote

* Add todos

* Add some more extension methods

* Add support for rendering quotes in a list

* Incrementally indent list items

* Fix quote indentation in list item

* Rename methods

* Clean up

* Add test

* Fix line break after code blocks

* Add code block style tests

* Add assert helper

* Clean up tests

* Set text container inset before fitting size to content

* Extract DownDebugLayoutManager and DownDebugTextView

* Allow snapshots to show line fragments

* Add color to links

* Add link style tests

* Clean up file structure

* Remove redundant imports

* Clean up file structure

* Fix DownTextView init

* Draw line fragments in DownDebugLayoutManager

* Add debug style tests

* Clean up file structure

* Remove isTopLevel from Paragraph

* Remove nestDepth from list item

* Remove unused extension method

* Remove unused attribute keys

* Provide public init for ThematicBreakOptions

* Move max prefix width calculation to ListItemParagraphStyler

* Rename DefaultStyler to DownStyler

* Extract styles into a configuration struct

* Clean up

* Clean up

* Remove AttributeCollection

* Remove color from QuoteStripeOptions

* Clean up

* Remove defaults from custom attributes

* Render markdown within DownTextView

* Fix quote stripe rendering

* Revert "Fix quote stripe rendering"

This reverts commit 72f7783d51.

* Tidy up

* Enrich code blocks with background color

* Remove redundant initializers

* Add CodeBlockOptions

* Clean up

* Make extension local and private

* Remove some duplication

* Rename method

* Move non private extensions into new files

* Remove duplication

* Clean up

* Add tests

* Rename method

* Add tests

* Fix prefix  generation

* Add tests

* File organization

* Add tests

* Clean up

* Remove duplicate comment

* Flatten code & html block descriptions into single line

* Add tests

* Clean up

* Remove dynamic fonts

* Initial steps to support macOS & tvOS

* Rename font traits

* Further support for macOS

* Clean up

* Use iPhone Xs simulator when testings on Travis

* Clean up old todos

* Add Styler documentation

* Add documentation

* Make setter private

* Remove duplication

* Fix typo

* Name magic numbers

* Make FontCollection and ColorCollection protocols

* Return self instead of nil

* Mark feature unavailable for watchOS

* Update to snapshot testing 1.6

* Check in snapshot testing framework for iOS

* Re-record list item snapshots

* Remove old TODO

* Fix compiler error for macOS

* Compile snapshot tests for iOS only

* Specify Xcode 11 for CI

* Move snapshot tests into separate test target

* Revert "Compile snapshot tests for iOS only"

This reverts commit 95b2bf1205.

* Run snapshot tests on CI

* Fix travis config

* Fix travis config again

* Fix missing file error

* Re-record snapshots on iPhone 11

* Update travis config

* slather DownShapshotTests

* Provide explicit types in styler configuration

* [Copyright] Update org name and years

* [CI] Try using Codecov for merged reports

* [Travis] Try doing Codecov after each slather

* [Xcode] Share DownSnapshotTests scheme w/ code coverage

* [CI] Use separate codecov report dirs

* [CI] Don't slather, just use codecov
2019-10-06 08:52:00 +02:00
Phuah Yee Keat 3f5dfe3ed8 Resolve xcode11beta4 issue. (#170) 2019-08-19 06:17:02 -04:00
Adrian Schoenig cea0e2df5a Minor documentation fix (#169) 2019-07-28 19:18:10 -04:00
Rob Phillips 4c72856a5c [Changes] v0.8.6 2019-07-11 11:18:42 -04:00
Rob Phillips 2e2a8f2f0c [Pod] Bump to v0.8.6 2019-07-11 11:16:56 -04:00
Herb Bowie 7c5d45ac9e Updates for unsafe option (#160)
Updating README and DownOptions to show that safe mode is now the default, and to indicate that unsafe must be specified to allow HTML rendering.
2019-07-11 11:07:37 -04:00
Matt Diephouse dcf86dcce5 Fix permissions error on Catalina beta 2 (#156) 2019-06-24 21:11:46 -04:00
Rob Phillips 805e537949 [Changes] v0.8.5 2019-06-12 22:20:53 -04:00
Rob Phillips 0e383bc1bb [Pod] Bump to v0.8.5 2019-06-12 22:12:19 -04:00
Aasim Kandrikar 4e4ddcef85 [SwiftPM] Adds cmark directory to header search path (#154) 2019-06-12 22:05:21 -04:00
Michael Collins 5f54bc0168 Create Public Initializer for DebugVisitor (#153)
I updated DebugVisitor. I added a public initializer to allow
DebugVisitor to be used by applications that consume the Down framework
for generating debug output from Markdown ASTs.
2019-06-12 17:41:22 -04:00
rob phillips 6d63c13cc1 Update README.md 2019-06-04 12:23:13 -04:00
Rob Phillips 589545794f [Changelog] v0.8.4 2019-06-04 12:20:14 -04:00
Rob Phillips 0afc8c18d9 [Pod] Bump to v0.8.4 2019-06-04 12:14:20 -04:00
Aasim Kandrikar d94b270cff Add Swift Package Manager support (#150)
* Add Swift Package Manager support

* Added test cases to Package.swift

* Update Down.podspec to reflect change to modulemap

* Updated module map location in Xcode project file
2019-06-04 12:12:53 -04:00
Filip Gulan 80d8b2d50d [AST] Replace line separator with paragraph separator. (#149)
* Replace line separator with paragraph separator.

* Fix Attributed String Visitor test.
2019-06-03 12:15:26 -04:00
Rob Phillips 5396a85265 [Changelog] v0.8.3 2019-05-15 11:09:05 -04:00
Rob Phillips 2b25ee0a0c [DownView] Whitespace nit 2019-05-15 11:06:19 -04:00
Rob Phillips 7b25a10457 [Down] Bump to v0.8.3 2019-05-15 11:03:44 -04:00
Rob Phillips f7dacd7d2c [DownView] Clean up nitpicks, add docs 2019-05-15 11:03:02 -04:00
Ladislas de Toldi 2d64aae0d0 [DownView] Pass DownOptions to init and update (#148)
* add DownOptions to init and update methods - closes #147

* add test for DownOptions init and update
2019-05-15 10:34:25 -04:00
Rob Phillips cb9ee72196 [Changelog] v0.8.2 2019-05-10 12:12:11 -04:00
Rob Phillips 4a1ad245e0 [Tests] Fix tvOS warning in test target compilation 2019-05-10 11:56:25 -04:00
Rob Phillips ae031a3668 [Down] Bump to v0.8.2 2019-05-10 11:49:43 -04:00
Rob Phillips d32bc14333 [DownView] Remove warning in openURL 2019-05-10 11:49:05 -04:00
Samuel Goodwin f82b61ff8e Mark as safe for app extension use. (#146)
This framework doesn't do anything you need an "app" for, so it's fine
to allow it to be used in extensions without warnings.
2019-05-10 11:46:35 -04:00
Rob Phillips 606c1e14dd [Changelog] v0.8.1 2019-04-26 19:28:42 -04:00
rob phillips 49b3ebae4d [Swift] Update to Swift 5.0 (#145)
* [Swift] Update to Swift 5.0

* [Swift] Update README

* [CI] Update travis to Xcode 10.2
2019-04-26 19:15:48 -04:00
Rob Phillips c0660dcda8 [Changelog] v0.8.0 (cmark v0.29.0) 2019-04-24 19:15:34 -04:00
Rob Phillips a0535b7222 [Pods] Bump to v0.8.0, for cmark v0.29.0 release 2019-04-24 19:10:23 -04:00
rob phillips 17a5842293 [Down] Add new unsafe option (#143)
`safe` is now the default, so all raw HTML will be scrubbed
2019-04-24 19:09:08 -04:00
larryonoff 25fde3d7c8 [cmark] Update source to v0.29.0 (#142)
Changelog: https://github.com/commonmark/cmark/releases/tag/0.29.0
* Bump cmark to 0.29.0
* Fix testXMLBindingsWork
2019-04-24 18:52:35 -04:00
larryonoff 3d044c766b Set Swift version 4.0 in podspec (#140) 2019-04-23 23:11:26 -04:00
Rob Phillips 4c35c7b0c5 [Changes] Changelog for v0.7.0 2019-04-21 21:33:30 -04:00
Rob Phillips 410e45c77b [Pod] Bump to v0.7.0 2019-04-21 21:25:41 -04:00
rob phillips bc65c735bc [Cleanup] Comment docs, example apps, and whitespace (#136)
* [Examples] Clean up example code

* [Code] fileprivate --> private

* [Nits] Modernize code doc formats
2019-04-21 19:35:12 -04:00
rob phillips 8c96f29e91 Add John to README contributors 2019-04-21 18:31:56 -04:00
John Nguyen c70d824918 [Feature] Create API for parsing to AST and NSAttributedString (#132)
* Create Node wrapper

* Categorize nodes into classes

* Add debug descriptions

* Define Visitor

* Add simple test for demonstration purposes

* Move nodes into separate files

* Move visitors into separate files

* Tidy up

* Expose Visitor protocol

* Add accept method to Document

* Update various nodes

* WIP: AttributedStringVisitor

* Fill out remaining visit methods

* Move Styler protocol into its own file

* Append blank line only for nodes with successors

* Add prefixes to list items

* Style list prefixes

* Rename isLast

* Adjust accept signature

* Adjust Image and Link nodes

* Pass url to styler methods

* Provide API to render to an attributed string via the AST

* Fix Link & Image properties

* Pass fenceInfo to styler method

* Slight refactoring of nodes

* Improve DebugVisitor to print tree depth

* Tidy up

* More tidy up

* Add some descriptions

* Tidy up

* Add documentation

* Make nodes public

* Tidy up

* More documentation

* Add visitor test

* Fix compile error for Xcode 10.1

* Remove unnecessary line breaks from blocks

* Test AttributedStringVisitor

* Make lazy var private(set)

* Clean up TODO

* Make all cmarkNode reference immutable

* Don’t fatalError on list type

* Don’t fatalError when wrapping child nodes

* Tidy up

* Don’t fatalError when visiting children

* Tidy up doc comments

* Improve documentation

* Refactor Node initialization

* Expose wrap() method

* Tidy up

* Fix warnings

* Lazily compute children

* Fix typo
2019-04-21 18:24:01 -04:00
Rob Phillips 6e566e2d45 Changelog for 0.6.6 2019-04-11 07:38:17 -04:00
Rob Phillips 54664f90be [Pod] Bump to 0.6.6 2019-04-11 07:34:06 -04:00
Nate Heagy 07a117ef4a Wrap openURL for app extensions (#133)
- DownView couldn’t compile in app extensions because of the use of UIApplication.shared.openURL
- With this change, an empty wrapper is used to allow DownView to compile and be usable in app extensions, with the downside that links cannot be opened
2019-04-11 07:33:13 -04:00
Rob Phillips a146258961 [Changes] v0.6.5 2019-04-01 20:33:14 -04:00
Rob Phillips 1685184749 [Pods] Bump to 0.6.5 2019-04-01 20:29:25 -04:00
Matt Diephouse 1fecb4b3a4 Fix Xcode 10.2 warnings (#130)
* Remove redundant 'public' modifiers

'public' modifier is redundant for instance method declared in a public extension

* Xcode 10.2 recommended settings

* Clear the Swift migration check
2019-04-01 20:27:43 -04:00
Rob Phillips 8b1f549ace Changelog for v0.6.4 2019-03-30 18:34:20 -04:00
Rob Phillips 421a92f5df [Pod] Bump to v0.6.4 2019-03-30 18:29:35 -04:00
Zsolt Váradi bdd5215c9a Remove references to memory.h (#125) 2019-03-30 18:27:31 -04:00
Rob Phillips 23e7744b67 [Changes] Update changelog 2019-03-26 21:07:42 -04:00
Rob Phillips 3e1e986138 [Pod] Bump to 0.6.3 2019-03-26 21:00:19 -04:00
phoney 4d947996fc Fix crash from missing parser.h include (#129)
Fix crash from missing parser.h include
2019-03-26 20:57:29 -04:00
phoney 8d0dcae7c1 Make the DownView reflow text on device rotation (#127)
Setting the meta viewport tag to width=device-width reflows the text to match the frame width of the DownView.
2019-03-22 23:50:00 -04:00
Rob Phillips 8db18023dd [Changes] Update changelog 2018-11-28 22:49:03 +01:00
267 changed files with 17567 additions and 28115 deletions
+17
View File
@@ -0,0 +1,17 @@
name: SwiftLint
on:
pull_request:
paths:
- '.github/workflows/swiftlint.yml'
- '.swiftlint.yml'
- '**/*.swift'
jobs:
SwiftLint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: GitHub Action for SwiftLint
uses: norio-nomura/action-swiftlint@3.2.1
+1 -1
View File
@@ -1,9 +1,9 @@
Pods/
.build/
.DS_Store
xcuserdata
# additional ignores that will save us time
build/
*.pbxuser
!default.pbxuser
*.mode1v3
-5
View File
@@ -1,5 +0,0 @@
coverage_service: coveralls
xcodeproj: Down.xcodeproj
source_directory: Source
ignore:
- Source/cmark/*
-1
View File
@@ -1 +0,0 @@
4.0
+10
View File
@@ -0,0 +1,10 @@
included:
- Sources/Down
- Tests
large_tuple:
warning: 3
error: 4
cyclomatic_complexity:
ignores_case_statements: true
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:">
</FileRef>
</Workspace>
+8 -8
View File
@@ -1,12 +1,12 @@
osx_image: xcode10.1
osx_image: xcode12.2
language: objective-c
before_install:
- set -o pipefail
- gem install xcpretty slather -N
- xcrun simctl boot "iPhone 7" || echo "(Pre)Launched the simulator."
- xcrun simctl boot "iPhone 12" || echo "(Pre)Launched the simulator."
script:
- travis_retry xcodebuild -project Down.xcodeproj -scheme "Down" -destination "platform=iOS Simulator,name=iPhone 7" -enableCodeCoverage YES ONLY_ACTIVE_ARCH=YES test | xcpretty -c
- travis_retry xcodebuild -project Down.xcodeproj -scheme "Down" -sdk macosx -destination 'platform=OS X,arch=x86_64' -enableCodeCoverage YES test | xcpretty -c
- travis_retry xcodebuild -project Down.xcodeproj -scheme "Down" -sdk appletvsimulator -destination 'platform=tvOS Simulator,name=Apple TV' -enableCodeCoverage YES test | xcpretty -c
after_success:
- slather coverage --ignore "../**/*/Xcode*" --ignore "Source/cmark/*" --scheme "Down" Down.xcodeproj
- travis_retry xcodebuild -project Down.xcodeproj -scheme "Down" -sdk iphonesimulator -destination "platform=iOS Simulator,OS=14.2,name=iPhone 12" -enableCodeCoverage YES ONLY_ACTIVE_ARCH=YES -quiet test
- bash <(curl -s https://codecov.io/bash)
- travis_retry xcodebuild -project Down.xcodeproj -scheme "Down" -sdk macosx -destination 'platform=OS X,arch=x86_64' -enableCodeCoverage YES -quiet test
- bash <(curl -s https://codecov.io/bash)
- travis_retry xcodebuild -project Down.xcodeproj -scheme "Down" -sdk appletvsimulator -destination 'platform=tvOS Simulator,name=Apple TV' -enableCodeCoverage YES -quiet test
- bash <(curl -s https://codecov.io/bash)
+521 -173
View File
@@ -1,263 +1,611 @@
# Change Log
# Changelog
## [v0.6.1](https://github.com/iwasrobbed/Down/tree/v0.6.1) (2018-11-23)
[Full Changelog](https://github.com/iwasrobbed/Down/compare/v0.6.0...v0.6.1)
## [v0.11.0](https://github.com/johnxnguyen/Down/tree/v0.11.0) (2021-05-04)
**Closed issues:**
- 2 Swift Compiler Errors when installing Down on iOS [\#117](https://github.com/iwasrobbed/Down/issues/117)
- How to update to the latest version of the cmark library [\#115](https://github.com/iwasrobbed/Down/issues/115)
**Merged pull requests:**
- \[travis\] Update to retry [\#114](https://github.com/iwasrobbed/Down/pull/114) ([iwasrobbed](https://github.com/iwasrobbed))
- Fix macOS Platform, Custom URL Scheme Handler, Polish Demos. [\#110](https://github.com/iwasrobbed/Down/pull/110) ([chriszielinski](https://github.com/chriszielinski))
## [v0.6.0](https://github.com/iwasrobbed/Down/tree/v0.6.0) (2018-11-10)
[Full Changelog](https://github.com/iwasrobbed/Down/compare/v0.5.3...v0.6.0)
[Full Changelog](https://github.com/johnxnguyen/Down/compare/v0.10.0...v0.11.0)
**Implemented enhancements:**
- \[iOS 10+\] Warnings for WebKit signal service and latex.c [\#94](https://github.com/iwasrobbed/Down/issues/94)
- Update cmark version to latest stable release [\#84](https://github.com/iwasrobbed/Down/issues/84)
- \[CodeCoverage\] Improve accuracy for combined code coverage reporting [\#205](https://github.com/johnxnguyen/Down/issues/205)
**Closed issues:**
- HTML to Markdowndow? [\#107](https://github.com/iwasrobbed/Down/issues/107)
- Blockquote does not work in NSAttributedString [\#106](https://github.com/iwasrobbed/Down/issues/106)
- Support for Dynamic Type [\#90](https://github.com/iwasrobbed/Down/issues/90)
- DownStyler not included when installed via CocoaPods [\#254](https://github.com/johnxnguyen/Down/issues/254)
- \[Commonmark\] Strikethrough not working / not supported [\#253](https://github.com/johnxnguyen/Down/issues/253)
- \[Attributed Strings\] Unordered list items with a single line appear further indented than those with multiple lines when using a custom font [\#246](https://github.com/johnxnguyen/Down/issues/246)
**Merged pull requests:**
- \[Down\] Bump to v0.6.0 [\#113](https://github.com/iwasrobbed/Down/pull/113) ([iwasrobbed](https://github.com/iwasrobbed))
- \[cmark\] Update lib to v0.28.3 [\#112](https://github.com/iwasrobbed/Down/pull/112) ([phoney](https://github.com/phoney))
- Update project to Xcode 10 [\#109](https://github.com/iwasrobbed/Down/pull/109) ([funkyboy](https://github.com/funkyboy))
- \[Feature\] Custom list prefixes for AttributedStringVisitor [\#255](https://github.com/johnxnguyen/Down/pull/255) ([dloic](https://github.com/dloic))
- \[Chore\] Add SwiftLint [\#252](https://github.com/johnxnguyen/Down/pull/252) ([johnxnguyen](https://github.com/johnxnguyen))
- \[Chore\] Fix codecov report [\#251](https://github.com/johnxnguyen/Down/pull/251) ([johnxnguyen](https://github.com/johnxnguyen))
## [v0.5.3](https://github.com/iwasrobbed/Down/tree/v0.5.3) (2018-09-19)
[Full Changelog](https://github.com/iwasrobbed/Down/compare/v0.5.2...v0.5.3)
## [v0.10.0](https://github.com/johnxnguyen/Down/tree/v0.10.0) (2021-02-28)
[Full Changelog](https://github.com/johnxnguyen/Down/compare/v0.9.5...v0.10.0)
**Closed issues:**
- Does not build in 12.5 [\#244](https://github.com/johnxnguyen/Down/issues/244)
- \[Crash\] Missing resource bundle when using SPM [\#243](https://github.com/johnxnguyen/Down/issues/243)
**Merged pull requests:**
- \[Improvement\] Expose DownTextView's designated initializer [\#250](https://github.com/johnxnguyen/Down/pull/250) ([max-potapov](https://github.com/max-potapov))
- \[Chore\] Add arm64 as valid arch when building for simulator on M1 macs [\#249](https://github.com/johnxnguyen/Down/pull/249) ([michaelknoch](https://github.com/michaelknoch))
- \[Chore\] Reorganize project structure for SPM [\#248](https://github.com/johnxnguyen/Down/pull/248) ([johnxnguyen](https://github.com/johnxnguyen))
- \[Chore\] Use SPM to manage snapshot testing dependency [\#247](https://github.com/johnxnguyen/Down/pull/247) ([johnxnguyen](https://github.com/johnxnguyen))
## [v0.9.5](https://github.com/johnxnguyen/Down/tree/v0.9.5) (2021-02-12)
[Full Changelog](https://github.com/johnxnguyen/Down/compare/v0.9.4...v0.9.5)
**Closed issues:**
- Namespacing issues with Down "Node" type [\#242](https://github.com/johnxnguyen/Down/issues/242)
- GitHub actions build failure: `small method list` [\#238](https://github.com/johnxnguyen/Down/issues/238)
**Merged pull requests:**
- \[Fix\] Compilation failure with Xcode 12.5 and SPM [\#245](https://github.com/johnxnguyen/Down/pull/245) ([claurel](https://github.com/claurel))
- \[Chore\] Update readme [\#237](https://github.com/johnxnguyen/Down/pull/237) ([johnxnguyen](https://github.com/johnxnguyen))
## [v0.9.4](https://github.com/johnxnguyen/Down/tree/v0.9.4) (2020-10-21)
[Full Changelog](https://github.com/johnxnguyen/Down/compare/v0.9.3...v0.9.4)
**Implemented enhancements:**
- &rdquo; not being rendered [\#95](https://github.com/iwasrobbed/Down/issues/95)
- Update issue templates [\#101](https://github.com/iwasrobbed/Down/pull/101) ([iwasrobbed](https://github.com/iwasrobbed))
- Create custom sequence to access child nodes [\#228](https://github.com/johnxnguyen/Down/pull/228) ([5sw](https://github.com/5sw))
**Closed issues:**
- DownStylerConfiguration Link Color Not Working [\#232](https://github.com/johnxnguyen/Down/issues/232)
- SwiftUI support [\#231](https://github.com/johnxnguyen/Down/issues/231)
- How to pre-calculate height needed for attributed string when using DownLayoutManager [\#226](https://github.com/johnxnguyen/Down/issues/226)
- How i can render both markdown and Latex ? [\#221](https://github.com/johnxnguyen/Down/issues/221)
- Emphasis + Strong [\#220](https://github.com/johnxnguyen/Down/issues/220)
- \[StackOverflow\] Creating a new Visitor leads to wrapping value error [\#218](https://github.com/johnxnguyen/Down/issues/218)
- 0.9.0/0.9.1 don't build with Swift 5.0.x [\#217](https://github.com/johnxnguyen/Down/issues/217)
- Unable to build Swift package in Xcode 11.4.1 [\#209](https://github.com/johnxnguyen/Down/issues/209)
- \[Feature\] Add support for Mac Catalyst [\#208](https://github.com/johnxnguyen/Down/issues/208)
**Merged pull requests:**
- \[Fix\] DownTextView renders incorrect link color [\#233](https://github.com/johnxnguyen/Down/pull/233) ([johnxnguyen](https://github.com/johnxnguyen))
- Added instructions for using the Swift Package Manager [\#230](https://github.com/johnxnguyen/Down/pull/230) ([klm1](https://github.com/klm1))
- Use case let as instead of case is and force casting later. [\#227](https://github.com/johnxnguyen/Down/pull/227) ([5sw](https://github.com/5sw))
- Add macOS arm64 platform [\#224](https://github.com/johnxnguyen/Down/pull/224) ([jasminlapalme](https://github.com/jasminlapalme))
## [v0.9.3](https://github.com/johnxnguyen/Down/tree/v0.9.3) (2020-06-12)
[Full Changelog](https://github.com/johnxnguyen/Down/compare/v0.9.2...v0.9.3)
**Closed issues:**
- Line breaks between list items are not parsed correctly [\#214](https://github.com/johnxnguyen/Down/issues/214)
- Can't build with copied sources [\#211](https://github.com/johnxnguyen/Down/issues/211)
- hard blank line insertion after list [\#210](https://github.com/johnxnguyen/Down/issues/210)
- Cocoapod version 0.9.2 not available. [\#206](https://github.com/johnxnguyen/Down/issues/206)
- \[Feature\] Local images not accessible from WKWebView [\#198](https://github.com/johnxnguyen/Down/issues/198)
**Merged pull requests:**
- \[Chore\] Bump swift snapshot testing to 1.7.2 [\#216](https://github.com/johnxnguyen/Down/pull/216) ([johnxnguyen](https://github.com/johnxnguyen))
- Add tightness property to List node [\#215](https://github.com/johnxnguyen/Down/pull/215) ([johnxnguyen](https://github.com/johnxnguyen))
- Add styling options for level 4 to 6 headings [\#207](https://github.com/johnxnguyen/Down/pull/207) ([mathebox](https://github.com/mathebox))
- \[DownView\] Add parameter so bundle is writable [\#200](https://github.com/johnxnguyen/Down/pull/200) ([brunnobga](https://github.com/brunnobga))
## [v0.9.2](https://github.com/johnxnguyen/Down/tree/v0.9.2) (2020-03-03)
[Full Changelog](https://github.com/johnxnguyen/Down/compare/v0.9.1...v0.9.2)
**Closed issues:**
- Update Framework with Swift 5.1 [\#178](https://github.com/johnxnguyen/Down/issues/178)
**Merged pull requests:**
- Swift 5.1 Support [\#204](https://github.com/johnxnguyen/Down/pull/204) ([ghost](https://github.com/ghost))
- Resolves Swift Package Manager issue related to swift-snapshot-testing [\#203](https://github.com/johnxnguyen/Down/pull/203) ([ghost](https://github.com/ghost))
## [v0.9.1](https://github.com/johnxnguyen/Down/tree/v0.9.1) (2020-02-28)
[Full Changelog](https://github.com/johnxnguyen/Down/compare/v0.9.0...v0.9.1)
**Implemented enhancements:**
- Added Linux support. [\#172](https://github.com/johnxnguyen/Down/pull/172) ([vgorloff](https://github.com/vgorloff))
**Closed issues:**
- SwiftPM : Resolve apparent version incompatibility with swift-snapshot-testing [\#202](https://github.com/johnxnguyen/Down/issues/202)
- Release fixes made after 0.9.0 [\#201](https://github.com/johnxnguyen/Down/issues/201)
- Swift UI Support [\#199](https://github.com/johnxnguyen/Down/issues/199)
- 'BaseNode' initializer is inaccessible due to 'internal' protection level [\#196](https://github.com/johnxnguyen/Down/issues/196)
- Any emoji support? [\#195](https://github.com/johnxnguyen/Down/issues/195)
- Swift Packege maneger? [\#194](https://github.com/johnxnguyen/Down/issues/194)
- Regression: single newline syntax not working \(any variety\) [\#191](https://github.com/johnxnguyen/Down/issues/191)
- Down cannot convert this markdown string to html [\#190](https://github.com/johnxnguyen/Down/issues/190)
- App using xcframework with Down pod dependency causes crash [\#187](https://github.com/johnxnguyen/Down/issues/187)
- Is the text supposed to be rendering this large? [\#186](https://github.com/johnxnguyen/Down/issues/186)
- Issue with markdown render/convert to attribute string on macOS latest version [\#185](https://github.com/johnxnguyen/Down/issues/185)
- Table are not render [\#183](https://github.com/johnxnguyen/Down/issues/183)
- How to change text color? [\#182](https://github.com/johnxnguyen/Down/issues/182)
- incorrect parse for string that is a mixture of markdown and html [\#180](https://github.com/johnxnguyen/Down/issues/180)
**Merged pull requests:**
- Improve configurability of DownStyler [\#188](https://github.com/johnxnguyen/Down/pull/188) ([mgacy](https://github.com/mgacy))
- Make color & font collection initializers public [\#184](https://github.com/johnxnguyen/Down/pull/184) ([johnxnguyen](https://github.com/johnxnguyen))
## [v0.9.0](https://github.com/johnxnguyen/Down/tree/v0.9.0) (2019-10-06)
[Full Changelog](https://github.com/johnxnguyen/Down/compare/v0.8.6...v0.9.0)
**Closed issues:**
- Please add Styler example in the documentation [\#179](https://github.com/johnxnguyen/Down/issues/179)
- \[Attributed Strings\] Can the `Styler` know which list item marker was parsed? [\#176](https://github.com/johnxnguyen/Down/issues/176)
- Error: 'cmark\_export.h' file not found with \<angled\> include; use "quotes" instead [\#175](https://github.com/johnxnguyen/Down/issues/175)
- GIFF Support [\#174](https://github.com/johnxnguyen/Down/issues/174)
- Help: Set Default Font [\#168](https://github.com/johnxnguyen/Down/issues/168)
- \[Testing\] Adding a snapshot testing framework [\#165](https://github.com/johnxnguyen/Down/issues/165)
- Adding a snapshot test framework [\#164](https://github.com/johnxnguyen/Down/issues/164)
- XCode Beta 4 Build Error [\#162](https://github.com/johnxnguyen/Down/issues/162)
- \[Attributed Strings\] Create default `Styler` for attributed string rendering [\#138](https://github.com/johnxnguyen/Down/issues/138)
- \[Help out\] Collaborators wanted! Help us improve Down [\#105](https://github.com/johnxnguyen/Down/issues/105)
- \[DownView\] Support for internal links? [\#93](https://github.com/johnxnguyen/Down/issues/93)
**Merged pull requests:**
- \[Feature\] Create default `Styler` for attributed string rendering [\#177](https://github.com/johnxnguyen/Down/pull/177) ([johnxnguyen](https://github.com/johnxnguyen))
- Resolve xcode11beta4 issue. [\#170](https://github.com/johnxnguyen/Down/pull/170) ([ykphuah](https://github.com/ykphuah))
- Minor documentation fix [\#169](https://github.com/johnxnguyen/Down/pull/169) ([nighthawk](https://github.com/nighthawk))
## [v0.8.6](https://github.com/johnxnguyen/Down/tree/v0.8.6) (2019-07-11)
[Full Changelog](https://github.com/johnxnguyen/Down/compare/v0.8.5...v0.8.6)
**Closed issues:**
- Update Options to support Unsafe Rendering [\#159](https://github.com/johnxnguyen/Down/issues/159)
- .toAttributedString stylesheet parameter [\#158](https://github.com/johnxnguyen/Down/issues/158)
**Merged pull requests:**
- Updates for unsafe option [\#160](https://github.com/johnxnguyen/Down/pull/160) ([hbowie](https://github.com/hbowie))
- Fix permissions error on Catalina beta 2 [\#156](https://github.com/johnxnguyen/Down/pull/156) ([mdiep](https://github.com/mdiep))
## [v0.8.5](https://github.com/johnxnguyen/Down/tree/v0.8.5) (2019-06-13)
[Full Changelog](https://github.com/johnxnguyen/Down/compare/v0.8.4...v0.8.5)
**Closed issues:**
- DebugVisitor is missing a public initializer [\#152](https://github.com/johnxnguyen/Down/issues/152)
- Can't build with Swift 5.1 with SwiftPM [\#151](https://github.com/johnxnguyen/Down/issues/151)
**Merged pull requests:**
- \[SPM\] Fixes error with missing headers [\#154](https://github.com/johnxnguyen/Down/pull/154) ([aasimk2000](https://github.com/aasimk2000))
- Create Public Initializer for DebugVisitor [\#153](https://github.com/johnxnguyen/Down/pull/153) ([mfcollins3](https://github.com/mfcollins3))
## [v0.8.4](https://github.com/johnxnguyen/Down/tree/v0.8.4) (2019-06-04)
[Full Changelog](https://github.com/johnxnguyen/Down/compare/v0.8.3...v0.8.4)
**Closed issues:**
- \[Carthage\] Missing required module 'libcmark' [\#120](https://github.com/johnxnguyen/Down/issues/120)
**Merged pull requests:**
- Add Swift Package Manager support [\#150](https://github.com/johnxnguyen/Down/pull/150) ([aasimk2000](https://github.com/aasimk2000))
- \[AST\] Replace line separator with paragraph separator. [\#149](https://github.com/johnxnguyen/Down/pull/149) ([fgulan](https://github.com/fgulan))
## [v0.8.3](https://github.com/johnxnguyen/Down/tree/v0.8.3) (2019-05-15)
[Full Changelog](https://github.com/johnxnguyen/Down/compare/v0.8.2...v0.8.3)
**Closed issues:**
- Pass DownOptions to DownView [\#147](https://github.com/johnxnguyen/Down/issues/147)
**Merged pull requests:**
- Feature - pass DownOptions to init and update [\#148](https://github.com/johnxnguyen/Down/pull/148) ([ladislas](https://github.com/ladislas))
## [v0.8.2](https://github.com/johnxnguyen/Down/tree/v0.8.2) (2019-05-10)
[Full Changelog](https://github.com/johnxnguyen/Down/compare/v0.8.1...v0.8.2)
**Merged pull requests:**
- Mark as safe for app extension use. [\#146](https://github.com/johnxnguyen/Down/pull/146) ([sgoodwin](https://github.com/sgoodwin))
## [v0.8.1](https://github.com/johnxnguyen/Down/tree/v0.8.1) (2019-04-26)
[Full Changelog](https://github.com/johnxnguyen/Down/compare/v0.8.0...v0.8.1)
**Merged pull requests:**
- \[Swift\] Update to Swift 5.0 [\#145](https://github.com/johnxnguyen/Down/pull/145) ([iwasrobbed](https://github.com/iwasrobbed))
## [v0.8.0](https://github.com/johnxnguyen/Down/tree/v0.8.0) (2019-04-24)
[Full Changelog](https://github.com/johnxnguyen/Down/compare/v0.7.0...v0.8.0)
**Closed issues:**
- 0.7.0 problems with NSAttributedString.Key [\#139](https://github.com/johnxnguyen/Down/issues/139)
**Merged pull requests:**
- \[Down\] Add new `unsafe` option [\#143](https://github.com/johnxnguyen/Down/pull/143) ([iwasrobbed](https://github.com/iwasrobbed))
- Bump cmark to 0.29.0 [\#142](https://github.com/johnxnguyen/Down/pull/142) ([larryonoff](https://github.com/larryonoff))
## [v0.7.0](https://github.com/johnxnguyen/Down/tree/v0.7.0) (2019-04-24)
[Full Changelog](https://github.com/johnxnguyen/Down/compare/v0.6.6...v0.7.0)
**Implemented enhancements:**
- \[Documentation\] AST API [\#134](https://github.com/johnxnguyen/Down/issues/134)
- \[Attributed Strings\] Line spacing more than expected [\#121](https://github.com/johnxnguyen/Down/issues/121)
- \[Down\] Rendering to attributed string is really slow, requires main thread [\#100](https://github.com/johnxnguyen/Down/issues/100)
**Merged pull requests:**
- Set Swift version 4.0 in podspec [\#140](https://github.com/johnxnguyen/Down/pull/140) ([larryonoff](https://github.com/larryonoff))
- \[Cleanup\] Comment docs, example apps, and whitespace [\#136](https://github.com/johnxnguyen/Down/pull/136) ([iwasrobbed](https://github.com/iwasrobbed))
- \[Feature\] Create API for parsing to AST and NSAttributedString [\#132](https://github.com/johnxnguyen/Down/pull/132) ([johnxnguyen](https://github.com/johnxnguyen))
## [v0.6.6](https://github.com/johnxnguyen/Down/tree/v0.6.6) (2019-04-11)
[Full Changelog](https://github.com/johnxnguyen/Down/compare/v0.6.5...v0.6.6)
**Closed issues:**
- Swift 4/5 compatibility [\#131](https://github.com/johnxnguyen/Down/issues/131)
**Merged pull requests:**
- Wrap openURL so that Down compiles in app extensions [\#133](https://github.com/johnxnguyen/Down/pull/133) ([nheagy](https://github.com/nheagy))
## [v0.6.5](https://github.com/johnxnguyen/Down/tree/v0.6.5) (2019-04-02)
[Full Changelog](https://github.com/johnxnguyen/Down/compare/v0.6.4...v0.6.5)
**Merged pull requests:**
- Fix Xcode 10.2 warnings [\#130](https://github.com/johnxnguyen/Down/pull/130) ([mdiep](https://github.com/mdiep))
## [v0.6.4](https://github.com/johnxnguyen/Down/tree/v0.6.4) (2019-03-30)
[Full Changelog](https://github.com/johnxnguyen/Down/compare/v0.6.3...v0.6.4)
**Closed issues:**
- Support SwiftPM [\#128](https://github.com/johnxnguyen/Down/issues/128)
- \[DownView\] Load multiple .md files \(link support\) [\#68](https://github.com/johnxnguyen/Down/issues/68)
**Merged pull requests:**
- Fix Swift module errors when used alongside Firestore [\#125](https://github.com/johnxnguyen/Down/pull/125) ([vzsg](https://github.com/vzsg))
## [v0.6.3](https://github.com/johnxnguyen/Down/tree/v0.6.3) (2019-03-27)
[Full Changelog](https://github.com/johnxnguyen/Down/compare/v0.6.2...v0.6.3)
**Implemented enhancements:**
- \[DownView\] Doesn't reflow text on orientation change [\#111](https://github.com/johnxnguyen/Down/issues/111)
**Fixed bugs:**
- \[Xcode 10\] Crash in XCBuildService; need to use old build system [\#91](https://github.com/iwasrobbed/Down/issues/91)
- Crash rendering markdown [\#126](https://github.com/johnxnguyen/Down/issues/126)
**Closed issues:**
- DownView font size on iPad is huge [\#102](https://github.com/iwasrobbed/Down/issues/102)
- Is there a way to convert NSAttributedString back to markdown? [\#98](https://github.com/iwasrobbed/Down/issues/98)
- Back Gesture [\#96](https://github.com/iwasrobbed/Down/issues/96)
- Access for [\#92](https://github.com/iwasrobbed/Down/issues/92)
- Image size NSAttributedString [\#89](https://github.com/iwasrobbed/Down/issues/89)
- Dependency analysis warnings with Cocoapods [\#88](https://github.com/iwasrobbed/Down/issues/88)
- WatchKit Support [\#71](https://github.com/iwasrobbed/Down/issues/71)
- Installation via Swift Package Manager [\#61](https://github.com/iwasrobbed/Down/issues/61)
- Cocoapods: libcmark [\#124](https://github.com/johnxnguyen/Down/issues/124)
- Use with storyboards [\#123](https://github.com/johnxnguyen/Down/issues/123)
- support for audio markdown? [\#122](https://github.com/johnxnguyen/Down/issues/122)
- \[Down\] Can't render toAttributedString while app is in background [\#116](https://github.com/johnxnguyen/Down/issues/116)
**Merged pull requests:**
- \[Xcode 10\]\[Carthage\] Use new build system [\#104](https://github.com/iwasrobbed/Down/pull/104) ([torokzsolt](https://github.com/torokzsolt))
- Updates the project settings to use the Legacy Build System. [\#97](https://github.com/iwasrobbed/Down/pull/97) ([pieromattos](https://github.com/pieromattos))
- \[Release\] v0.5.2 [\#87](https://github.com/iwasrobbed/Down/pull/87) ([iwasrobbed](https://github.com/iwasrobbed))
- Fix crash from missing parser.h include [\#129](https://github.com/johnxnguyen/Down/pull/129) ([phoney](https://github.com/phoney))
- Make the DownView reflow text on device rotation [\#127](https://github.com/johnxnguyen/Down/pull/127) ([phoney](https://github.com/phoney))
## [v0.5.2](https://github.com/iwasrobbed/Down/tree/v0.5.2) (2018-05-05)
[Full Changelog](https://github.com/iwasrobbed/Down/compare/v0.5.1...v0.5.2)
## [v0.6.2](https://github.com/johnxnguyen/Down/tree/v0.6.2) (2018-11-28)
**Merged pull requests:**
- \[Pods\] Only include files in source\_files that can be compiled [\#86](https://github.com/iwasrobbed/Down/pull/86) ([njdehoog](https://github.com/njdehoog))
## [v0.5.1](https://github.com/iwasrobbed/Down/tree/v0.5.1) (2018-03-03)
[Full Changelog](https://github.com/iwasrobbed/Down/compare/v0.5.0...v0.5.1)
**Closed issues:**
- `DocumentReadingOptionKey` Error via pod [\#80](https://github.com/iwasrobbed/Down/issues/80)
**Merged pull requests:**
- Add optional stylesheet argument for NSAttributedString renderer [\#79](https://github.com/iwasrobbed/Down/pull/79) ([kengruven](https://github.com/kengruven))
- Roll up cmark's COPYING sections into the top-level LICENSE file [\#78](https://github.com/iwasrobbed/Down/pull/78) ([kengruven](https://github.com/kengruven))
- Update supported versions in README [\#77](https://github.com/iwasrobbed/Down/pull/77) ([kengruven](https://github.com/kengruven))
## [v0.5.0](https://github.com/iwasrobbed/Down/tree/v0.5.0) (2018-02-24)
[Full Changelog](https://github.com/iwasrobbed/Down/compare/v0.4.2...v0.5.0)
[Full Changelog](https://github.com/johnxnguyen/Down/compare/v0.6.1...v0.6.2)
**Implemented enhancements:**
- Fix/update example app [\#58](https://github.com/iwasrobbed/Down/pull/58) ([iwasrobbed](https://github.com/iwasrobbed))
- \[cmark\] Some characters are escaped twice [\#99](https://github.com/johnxnguyen/Down/issues/99)
**Merged pull requests:**
- Add compiler flag to suppress implicit conversion warnings [\#118](https://github.com/johnxnguyen/Down/pull/118) ([phoney](https://github.com/phoney))
## [v0.6.1](https://github.com/johnxnguyen/Down/tree/v0.6.1) (2018-11-23)
[Full Changelog](https://github.com/johnxnguyen/Down/compare/v0.6.0...v0.6.1)
**Closed issues:**
- 2 Swift Compiler Errors when installing Down on iOS [\#117](https://github.com/johnxnguyen/Down/issues/117)
- How to update to the latest version of the cmark library [\#115](https://github.com/johnxnguyen/Down/issues/115)
**Merged pull requests:**
- \[travis\] Update to retry [\#114](https://github.com/johnxnguyen/Down/pull/114) ([iwasrobbed](https://github.com/iwasrobbed))
- Fix macOS Platform, Custom URL Scheme Handler, Polish Demos. [\#110](https://github.com/johnxnguyen/Down/pull/110) ([chriszielinski](https://github.com/chriszielinski))
## [v0.6.0](https://github.com/johnxnguyen/Down/tree/v0.6.0) (2018-11-10)
[Full Changelog](https://github.com/johnxnguyen/Down/compare/v0.5.3...v0.6.0)
**Implemented enhancements:**
- \[iOS 10+\] Warnings for WebKit signal service and latex.c [\#94](https://github.com/johnxnguyen/Down/issues/94)
- Update cmark version to latest stable release [\#84](https://github.com/johnxnguyen/Down/issues/84)
**Closed issues:**
- HTML to Markdowndow? [\#107](https://github.com/johnxnguyen/Down/issues/107)
- Blockquote does not work in NSAttributedString [\#106](https://github.com/johnxnguyen/Down/issues/106)
- Support for Dynamic Type [\#90](https://github.com/johnxnguyen/Down/issues/90)
**Merged pull requests:**
- \[Down\] Bump to v0.6.0 [\#113](https://github.com/johnxnguyen/Down/pull/113) ([iwasrobbed](https://github.com/iwasrobbed))
- \[cmark\] Update lib to v0.28.3 [\#112](https://github.com/johnxnguyen/Down/pull/112) ([phoney](https://github.com/phoney))
- Update project to Xcode 10 [\#109](https://github.com/johnxnguyen/Down/pull/109) ([funkyboy](https://github.com/funkyboy))
## [v0.5.3](https://github.com/johnxnguyen/Down/tree/v0.5.3) (2018-09-19)
[Full Changelog](https://github.com/johnxnguyen/Down/compare/v0.5.2...v0.5.3)
**Implemented enhancements:**
- &rdquo; not being rendered [\#95](https://github.com/johnxnguyen/Down/issues/95)
- Update issue templates [\#101](https://github.com/johnxnguyen/Down/pull/101) ([iwasrobbed](https://github.com/iwasrobbed))
**Fixed bugs:**
- Building for tvOS fails [\#49](https://github.com/iwasrobbed/Down/issues/49)
- Fix Carthage builds [\#72](https://github.com/iwasrobbed/Down/pull/72) ([tonyarnold](https://github.com/tonyarnold))
- Fix/update example app [\#58](https://github.com/iwasrobbed/Down/pull/58) ([iwasrobbed](https://github.com/iwasrobbed))
- \[Xcode 10\] Crash in XCBuildService; need to use old build system [\#91](https://github.com/johnxnguyen/Down/issues/91)
**Closed issues:**
- Swift 3+ convention for capitalization [\#74](https://github.com/iwasrobbed/Down/issues/74)
- macOS 10.11 support? [\#73](https://github.com/iwasrobbed/Down/issues/73)
- Installing with Carthage for Mac fails [\#70](https://github.com/iwasrobbed/Down/issues/70)
- Error building/installing Down [\#69](https://github.com/iwasrobbed/Down/issues/69)
- get heigth when add downview to other view? [\#67](https://github.com/iwasrobbed/Down/issues/67)
- iOS8 crash [\#66](https://github.com/iwasrobbed/Down/issues/66)
- Image caching [\#65](https://github.com/iwasrobbed/Down/issues/65)
- Some warnings to fix [\#64](https://github.com/iwasrobbed/Down/issues/64)
- build error [\#63](https://github.com/iwasrobbed/Down/issues/63)
- Lists and paragraph spacing [\#62](https://github.com/iwasrobbed/Down/issues/62)
- Converting Markdown string to HTML with emojis [\#60](https://github.com/iwasrobbed/Down/issues/60)
- Syntax highlighting themes [\#59](https://github.com/iwasrobbed/Down/issues/59)
- Compiling error on example project [\#57](https://github.com/iwasrobbed/Down/issues/57)
- Compilation error using Carthage [\#54](https://github.com/iwasrobbed/Down/issues/54)
- DownView font size on iPad is huge [\#102](https://github.com/johnxnguyen/Down/issues/102)
- Is there a way to convert NSAttributedString back to markdown? [\#98](https://github.com/johnxnguyen/Down/issues/98)
- Back Gesture [\#96](https://github.com/johnxnguyen/Down/issues/96)
- Access for [\#92](https://github.com/johnxnguyen/Down/issues/92)
- Image size NSAttributedString [\#89](https://github.com/johnxnguyen/Down/issues/89)
- Dependency analysis warnings with Cocoapods [\#88](https://github.com/johnxnguyen/Down/issues/88)
- WatchKit Support [\#71](https://github.com/johnxnguyen/Down/issues/71)
- Installation via Swift Package Manager [\#61](https://github.com/johnxnguyen/Down/issues/61)
**Merged pull requests:**
- Use lower-case Swift 3 convention for DownOptions [\#76](https://github.com/iwasrobbed/Down/pull/76) ([kengruven](https://github.com/kengruven))
- Lower MACOSX\_DEPLOYMENT\_TARGET to include El Capitan [\#75](https://github.com/iwasrobbed/Down/pull/75) ([kengruven](https://github.com/kengruven))
- WebKit not available on watchOS. [\#56](https://github.com/iwasrobbed/Down/pull/56) ([128keaton](https://github.com/128keaton))
- Update README.md [\#55](https://github.com/iwasrobbed/Down/pull/55) ([128keaton](https://github.com/128keaton))
- Updated Copyright year in ReadMe file [\#53](https://github.com/iwasrobbed/Down/pull/53) ([jobinsjohn](https://github.com/jobinsjohn))
- \[Xcode 10\]\[Carthage\] Use new build system [\#104](https://github.com/johnxnguyen/Down/pull/104) ([torokzsolt](https://github.com/torokzsolt))
- Updates the project settings to use the Legacy Build System. [\#97](https://github.com/johnxnguyen/Down/pull/97) ([pieromattos](https://github.com/pieromattos))
- \[Release\] v0.5.2 [\#87](https://github.com/johnxnguyen/Down/pull/87) ([iwasrobbed](https://github.com/iwasrobbed))
## [v0.4.2](https://github.com/iwasrobbed/Down/tree/v0.4.2) (2017-10-21)
[Full Changelog](https://github.com/iwasrobbed/Down/compare/v0.4.1...v0.4.2)
## [v0.5.2](https://github.com/johnxnguyen/Down/tree/v0.5.2) (2018-05-05)
[Full Changelog](https://github.com/johnxnguyen/Down/compare/v0.5.1...v0.5.2)
**Merged pull requests:**
- \[Pods\] Only include files in source\_files that can be compiled [\#86](https://github.com/johnxnguyen/Down/pull/86) ([njdehoog](https://github.com/njdehoog))
## [v0.5.1](https://github.com/johnxnguyen/Down/tree/v0.5.1) (2018-03-03)
[Full Changelog](https://github.com/johnxnguyen/Down/compare/v0.5.0...v0.5.1)
**Closed issues:**
- Push v0.4.1 to cocoapods [\#51](https://github.com/iwasrobbed/Down/issues/51)
- `DocumentReadingOptionKey` Error via pod [\#80](https://github.com/johnxnguyen/Down/issues/80)
**Merged pull requests:**
- \[tvOS\] Conditionally compile DownView [\#52](https://github.com/iwasrobbed/Down/pull/52) ([iwasrobbed](https://github.com/iwasrobbed))
- Add optional stylesheet argument for NSAttributedString renderer [\#79](https://github.com/johnxnguyen/Down/pull/79) ([kengruven](https://github.com/kengruven))
- Roll up cmark's COPYING sections into the top-level LICENSE file [\#78](https://github.com/johnxnguyen/Down/pull/78) ([kengruven](https://github.com/kengruven))
- Update supported versions in README [\#77](https://github.com/johnxnguyen/Down/pull/77) ([kengruven](https://github.com/kengruven))
## [v0.4.1](https://github.com/iwasrobbed/Down/tree/v0.4.1) (2017-10-04)
[Full Changelog](https://github.com/iwasrobbed/Down/compare/v0.4.0...v0.4.1)
## [v0.5.0](https://github.com/johnxnguyen/Down/tree/v0.5.0) (2018-02-24)
[Full Changelog](https://github.com/johnxnguyen/Down/compare/v0.4.2...v0.5.0)
**Implemented enhancements:**
- Fix/update example app [\#58](https://github.com/johnxnguyen/Down/pull/58) ([iwasrobbed](https://github.com/iwasrobbed))
**Fixed bugs:**
- Building for tvOS fails [\#49](https://github.com/johnxnguyen/Down/issues/49)
- Fix Carthage builds [\#72](https://github.com/johnxnguyen/Down/pull/72) ([tonyarnold](https://github.com/tonyarnold))
**Closed issues:**
- Carthage install fails: no such module 'libcmark' [\#43](https://github.com/iwasrobbed/Down/issues/43)
- Xcode 8.3 warnings [\#26](https://github.com/iwasrobbed/Down/issues/26)
- Swift 3+ convention for capitalization [\#74](https://github.com/johnxnguyen/Down/issues/74)
- macOS 10.11 support? [\#73](https://github.com/johnxnguyen/Down/issues/73)
- Installing with Carthage for Mac fails [\#70](https://github.com/johnxnguyen/Down/issues/70)
- Error building/installing Down [\#69](https://github.com/johnxnguyen/Down/issues/69)
- get heigth when add downview to other view? [\#67](https://github.com/johnxnguyen/Down/issues/67)
- iOS8 crash [\#66](https://github.com/johnxnguyen/Down/issues/66)
- Image caching [\#65](https://github.com/johnxnguyen/Down/issues/65)
- Some warnings to fix [\#64](https://github.com/johnxnguyen/Down/issues/64)
- build error [\#63](https://github.com/johnxnguyen/Down/issues/63)
- Lists and paragraph spacing [\#62](https://github.com/johnxnguyen/Down/issues/62)
- Converting Markdown string to HTML with emojis [\#60](https://github.com/johnxnguyen/Down/issues/60)
- Syntax highlighting themes [\#59](https://github.com/johnxnguyen/Down/issues/59)
- Compiling error on example project [\#57](https://github.com/johnxnguyen/Down/issues/57)
- Compilation error using Carthage [\#54](https://github.com/johnxnguyen/Down/issues/54)
**Merged pull requests:**
- Adds filters to remove Xcode-specific warnings [\#48](https://github.com/iwasrobbed/Down/pull/48) ([128keaton](https://github.com/128keaton))
- Fixes issue \#43 [\#47](https://github.com/iwasrobbed/Down/pull/47) ([128keaton](https://github.com/128keaton))
- Update to Swift 4 [\#46](https://github.com/iwasrobbed/Down/pull/46) ([iwasrobbed](https://github.com/iwasrobbed))
- Fixed error with accessing shared workspace. [\#44](https://github.com/iwasrobbed/Down/pull/44) ([mjzac](https://github.com/mjzac))
- Use lower-case Swift 3 convention for DownOptions [\#76](https://github.com/johnxnguyen/Down/pull/76) ([kengruven](https://github.com/kengruven))
- Lower MACOSX\_DEPLOYMENT\_TARGET to include El Capitan [\#75](https://github.com/johnxnguyen/Down/pull/75) ([kengruven](https://github.com/kengruven))
- WebKit not available on watchOS. [\#56](https://github.com/johnxnguyen/Down/pull/56) ([128keaton](https://github.com/128keaton))
- Update README.md [\#55](https://github.com/johnxnguyen/Down/pull/55) ([128keaton](https://github.com/128keaton))
- Updated Copyright year in ReadMe file [\#53](https://github.com/johnxnguyen/Down/pull/53) ([jobinsjohn](https://github.com/jobinsjohn))
## [v0.4.0](https://github.com/iwasrobbed/Down/tree/v0.4.0) (2017-08-31)
[Full Changelog](https://github.com/iwasrobbed/Down/compare/v0.3.5...v0.4.0)
## [v0.4.2](https://github.com/johnxnguyen/Down/tree/v0.4.2) (2017-10-21)
**Implemented enhancements:**
- Example project [\#37](https://github.com/iwasrobbed/Down/issues/37)
- Markdown tables support [\#36](https://github.com/iwasrobbed/Down/issues/36)
[Full Changelog](https://github.com/johnxnguyen/Down/compare/v0.4.1...v0.4.2)
**Closed issues:**
- Unable to build with Xcode 9 [\#41](https://github.com/iwasrobbed/Down/issues/41)
- Can not load local image and link to local .md file [\#40](https://github.com/iwasrobbed/Down/issues/40)
- Fenced code syntax highlighting [\#35](https://github.com/iwasrobbed/Down/issues/35)
- down.toAttributedString\(\) custom text font and image size [\#33](https://github.com/iwasrobbed/Down/issues/33)
- Push v0.4.1 to cocoapods [\#51](https://github.com/johnxnguyen/Down/issues/51)
**Merged pull requests:**
- Closes “Example” Issue [\#38](https://github.com/iwasrobbed/Down/pull/38) ([128keaton](https://github.com/128keaton))
- Prevent zoom documentation [\#34](https://github.com/iwasrobbed/Down/pull/34) ([Kumuluzz](https://github.com/Kumuluzz))
- \[tvOS\] Conditionally compile DownView [\#52](https://github.com/johnxnguyen/Down/pull/52) ([iwasrobbed](https://github.com/iwasrobbed))
## [v0.3.5](https://github.com/iwasrobbed/Down/tree/v0.3.5) (2017-05-25)
[Full Changelog](https://github.com/iwasrobbed/Down/compare/v0.3.4...v0.3.5)
## [v0.4.1](https://github.com/johnxnguyen/Down/tree/v0.4.1) (2017-10-04)
**Implemented enhancements:**
- Disable analysis of cmark source code [\#31](https://github.com/iwasrobbed/Down/pull/31) ([tonyarnold](https://github.com/tonyarnold))
## [v0.3.4](https://github.com/iwasrobbed/Down/tree/v0.3.4) (2017-05-13)
[Full Changelog](https://github.com/iwasrobbed/Down/compare/v0.3.3...v0.3.4)
**Merged pull requests:**
- Suggested project fixes/changes [\#28](https://github.com/iwasrobbed/Down/pull/28) ([tonyarnold](https://github.com/tonyarnold))
- Add the ability to initialise a DownView using a custom template bundle [\#27](https://github.com/iwasrobbed/Down/pull/27) ([tonyarnold](https://github.com/tonyarnold))
## [v0.3.3](https://github.com/iwasrobbed/Down/tree/v0.3.3) (2017-03-09)
[Full Changelog](https://github.com/iwasrobbed/Down/compare/v0.3.2...v0.3.3)
**Implemented enhancements:**
- Add OS X support [\#6](https://github.com/iwasrobbed/Down/issues/6)
**Merged pull requests:**
- \#6 macOS Support [\#25](https://github.com/iwasrobbed/Down/pull/25) ([128keaton](https://github.com/128keaton))
## [v0.3.2](https://github.com/iwasrobbed/Down/tree/v0.3.2) (2017-02-26)
[Full Changelog](https://github.com/iwasrobbed/Down/compare/v0.3.1...v0.3.2)
**Implemented enhancements:**
- Create changelog [\#20](https://github.com/iwasrobbed/Down/issues/20)
[Full Changelog](https://github.com/johnxnguyen/Down/compare/v0.4.0...v0.4.1)
**Closed issues:**
- A faster substitute to NSHTMLTextDocumentType? [\#23](https://github.com/iwasrobbed/Down/issues/23)
- How to update DownView content and keep the style? [\#19](https://github.com/iwasrobbed/Down/issues/19)
- Carthage install fails: no such module 'libcmark' [\#43](https://github.com/johnxnguyen/Down/issues/43)
- Xcode 8.3 warnings [\#26](https://github.com/johnxnguyen/Down/issues/26)
**Merged pull requests:**
- Add tvOS support [\#24](https://github.com/iwasrobbed/Down/pull/24) ([invliD](https://github.com/invliD))
- v0.3.1: Add the ability to update DownView content [\#22](https://github.com/iwasrobbed/Down/pull/22) ([iwasrobbed](https://github.com/iwasrobbed))
- Adds filters to remove Xcode-specific warnings [\#48](https://github.com/johnxnguyen/Down/pull/48) ([128keaton](https://github.com/128keaton))
- Fixes issue \#43 [\#47](https://github.com/johnxnguyen/Down/pull/47) ([128keaton](https://github.com/128keaton))
- Update to Swift 4 [\#46](https://github.com/johnxnguyen/Down/pull/46) ([iwasrobbed](https://github.com/iwasrobbed))
## [v0.3.1](https://github.com/iwasrobbed/Down/tree/v0.3.1) (2017-02-09)
[Full Changelog](https://github.com/iwasrobbed/Down/compare/v0.3...v0.3.1)
## [v0.4.0](https://github.com/johnxnguyen/Down/tree/v0.4.0) (2017-08-31)
**Closed issues:**
- How to keep UITextView font style [\#21](https://github.com/iwasrobbed/Down/issues/21)
- Define custom fonts [\#18](https://github.com/iwasrobbed/Down/issues/18)
- Render progress [\#17](https://github.com/iwasrobbed/Down/issues/17)
- Disable zoom WebView [\#16](https://github.com/iwasrobbed/Down/issues/16)
- Text Size of DownView too small [\#15](https://github.com/iwasrobbed/Down/issues/15)
- How to customize the Font? [\#14](https://github.com/iwasrobbed/Down/issues/14)
- Support Images [\#13](https://github.com/iwasrobbed/Down/issues/13)
- How to manually install \(w/o Carthage or CocoaPods\) [\#12](https://github.com/iwasrobbed/Down/issues/12)
- Add support for Carthage [\#8](https://github.com/iwasrobbed/Down/issues/8)
## [v0.3](https://github.com/iwasrobbed/Down/tree/v0.3) (2016-10-12)
[Full Changelog](https://github.com/iwasrobbed/Down/compare/v0.2...v0.3)
[Full Changelog](https://github.com/johnxnguyen/Down/compare/v0.3.5...v0.4.0)
**Implemented enhancements:**
- Swift 3.0 support [\#10](https://github.com/iwasrobbed/Down/issues/10)
- Add web view for rendering output [\#3](https://github.com/iwasrobbed/Down/issues/3)
- Example project [\#37](https://github.com/johnxnguyen/Down/issues/37)
- Markdown tables support [\#36](https://github.com/johnxnguyen/Down/issues/36)
**Closed issues:**
- Can you give an example how to custom the parser? [\#9](https://github.com/iwasrobbed/Down/issues/9)
- Unable to build with Xcode 9 [\#41](https://github.com/johnxnguyen/Down/issues/41)
- Can not load local image and link to local .md file [\#40](https://github.com/johnxnguyen/Down/issues/40)
- Fenced code syntax highlighting [\#35](https://github.com/johnxnguyen/Down/issues/35)
- down.toAttributedString\(\) custom text font and image size [\#33](https://github.com/johnxnguyen/Down/issues/33)
**Merged pull requests:**
- Swift 3 [\#11](https://github.com/iwasrobbed/Down/pull/11) ([azeff](https://github.com/azeff))
- Adds a few extra tests where possible [\#7](https://github.com/iwasrobbed/Down/pull/7) ([iwasrobbed](https://github.com/iwasrobbed))
- DownView rendering to close \#3 [\#5](https://github.com/iwasrobbed/Down/pull/5) ([iwasrobbed](https://github.com/iwasrobbed))
- Closes “Example” Issue [\#38](https://github.com/johnxnguyen/Down/pull/38) ([128keaton](https://github.com/128keaton))
- Prevent zoom documentation [\#34](https://github.com/johnxnguyen/Down/pull/34) ([Kumuluzz](https://github.com/Kumuluzz))
## [v0.2](https://github.com/iwasrobbed/Down/tree/v0.2) (2016-06-02)
[Full Changelog](https://github.com/iwasrobbed/Down/compare/v0.1.1...v0.2)
## [v0.3.5](https://github.com/johnxnguyen/Down/tree/v0.3.5) (2017-05-25)
[Full Changelog](https://github.com/johnxnguyen/Down/compare/v0.3.4...v0.3.5)
**Implemented enhancements:**
- Add attributed string support [\#2](https://github.com/iwasrobbed/Down/issues/2)
- Adds attributed string rendering [\#4](https://github.com/iwasrobbed/Down/pull/4) ([iwasrobbed](https://github.com/iwasrobbed))
- Disable analysis of cmark source code [\#31](https://github.com/johnxnguyen/Down/pull/31) ([tonyarnold](https://github.com/tonyarnold))
## [v0.1.1](https://github.com/iwasrobbed/Down/tree/v0.1.1) (2016-06-01)
[Full Changelog](https://github.com/iwasrobbed/Down/compare/v0.1...v0.1.1)
## [v0.3.4](https://github.com/johnxnguyen/Down/tree/v0.3.4) (2017-05-13)
[Full Changelog](https://github.com/johnxnguyen/Down/compare/v0.3.3...v0.3.4)
**Merged pull requests:**
- Suggested project fixes/changes [\#28](https://github.com/johnxnguyen/Down/pull/28) ([tonyarnold](https://github.com/tonyarnold))
- Add the ability to initialise a DownView using a custom template bundle [\#27](https://github.com/johnxnguyen/Down/pull/27) ([tonyarnold](https://github.com/tonyarnold))
## [v0.3.3](https://github.com/johnxnguyen/Down/tree/v0.3.3) (2017-03-09)
[Full Changelog](https://github.com/johnxnguyen/Down/compare/v0.3.2...v0.3.3)
**Implemented enhancements:**
- Add CocoaPods support & cmark license [\#1](https://github.com/iwasrobbed/Down/pull/1) ([iwasrobbed](https://github.com/iwasrobbed))
- Add OS X support [\#6](https://github.com/johnxnguyen/Down/issues/6)
## [v0.1](https://github.com/iwasrobbed/Down/tree/v0.1) (2016-06-01)
**Merged pull requests:**
- \#6 macOS Support [\#25](https://github.com/johnxnguyen/Down/pull/25) ([128keaton](https://github.com/128keaton))
## [v0.3.2](https://github.com/johnxnguyen/Down/tree/v0.3.2) (2017-02-26)
[Full Changelog](https://github.com/johnxnguyen/Down/compare/v0.3.1...v0.3.2)
**Implemented enhancements:**
- Create changelog [\#20](https://github.com/johnxnguyen/Down/issues/20)
**Closed issues:**
- A faster substitute to NSHTMLTextDocumentType? [\#23](https://github.com/johnxnguyen/Down/issues/23)
- How to update DownView content and keep the style? [\#19](https://github.com/johnxnguyen/Down/issues/19)
**Merged pull requests:**
- Add tvOS support [\#24](https://github.com/johnxnguyen/Down/pull/24) ([invliD](https://github.com/invliD))
- v0.3.1: Add the ability to update DownView content [\#22](https://github.com/johnxnguyen/Down/pull/22) ([iwasrobbed](https://github.com/iwasrobbed))
## [v0.3.1](https://github.com/johnxnguyen/Down/tree/v0.3.1) (2017-02-09)
[Full Changelog](https://github.com/johnxnguyen/Down/compare/v0.3...v0.3.1)
**Closed issues:**
- How to keep UITextView font style [\#21](https://github.com/johnxnguyen/Down/issues/21)
- Define custom fonts [\#18](https://github.com/johnxnguyen/Down/issues/18)
- Render progress [\#17](https://github.com/johnxnguyen/Down/issues/17)
- Disable zoom WebView [\#16](https://github.com/johnxnguyen/Down/issues/16)
- Text Size of DownView too small [\#15](https://github.com/johnxnguyen/Down/issues/15)
- How to customize the Font? [\#14](https://github.com/johnxnguyen/Down/issues/14)
- Support Images [\#13](https://github.com/johnxnguyen/Down/issues/13)
- How to manually install \(w/o Carthage or CocoaPods\) [\#12](https://github.com/johnxnguyen/Down/issues/12)
- Add support for Carthage [\#8](https://github.com/johnxnguyen/Down/issues/8)
## [v0.3](https://github.com/johnxnguyen/Down/tree/v0.3) (2016-10-12)
[Full Changelog](https://github.com/johnxnguyen/Down/compare/v0.2...v0.3)
**Implemented enhancements:**
- Swift 3.0 support [\#10](https://github.com/johnxnguyen/Down/issues/10)
- Add web view for rendering output [\#3](https://github.com/johnxnguyen/Down/issues/3)
**Closed issues:**
- Can you give an example how to custom the parser? [\#9](https://github.com/johnxnguyen/Down/issues/9)
**Merged pull requests:**
- Swift 3 [\#11](https://github.com/johnxnguyen/Down/pull/11) ([azeff](https://github.com/azeff))
- Adds a few extra tests where possible [\#7](https://github.com/johnxnguyen/Down/pull/7) ([iwasrobbed](https://github.com/iwasrobbed))
- DownView rendering to close \#3 [\#5](https://github.com/johnxnguyen/Down/pull/5) ([iwasrobbed](https://github.com/iwasrobbed))
## [v0.2](https://github.com/johnxnguyen/Down/tree/v0.2) (2016-06-02)
[Full Changelog](https://github.com/johnxnguyen/Down/compare/v0.1.1...v0.2)
**Implemented enhancements:**
- Add attributed string support [\#2](https://github.com/johnxnguyen/Down/issues/2)
- Adds attributed string rendering [\#4](https://github.com/johnxnguyen/Down/pull/4) ([iwasrobbed](https://github.com/iwasrobbed))
## [v0.1.1](https://github.com/johnxnguyen/Down/tree/v0.1.1) (2016-06-01)
[Full Changelog](https://github.com/johnxnguyen/Down/compare/v0.1...v0.1.1)
**Implemented enhancements:**
- Add CocoaPods support & cmark license [\#1](https://github.com/johnxnguyen/Down/pull/1) ([iwasrobbed](https://github.com/iwasrobbed))
## [v0.1](https://github.com/johnxnguyen/Down/tree/v0.1) (2016-06-01)
[Full Changelog](https://github.com/johnxnguyen/Down/compare/69fba2a97e45a07360054a811cac018bec10e17d...v0.1)
\* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)*
\* *This Changelog was automatically generated by [github_changelog_generator](https://github.com/github-changelog-generator/github-changelog-generator)*
@@ -11,28 +11,28 @@
14090A4E2185411800503C06 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 14090A4D2185411800503C06 /* ViewController.swift */; };
14090A502185411A00503C06 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 14090A4F2185411A00503C06 /* Assets.xcassets */; };
14090A532185411A00503C06 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 14090A512185411A00503C06 /* Main.storyboard */; };
14090A592185414B00503C06 /* Down.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D49980B51FA560F8004EE42E /* Down.framework */; };
14090A5A2185414B00503C06 /* Down.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = D49980B51FA560F8004EE42E /* Down.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
1466417E218D2A18009627F9 /* Down.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D49980B51FA560F8004EE42E /* Down.framework */; };
1466417F218D2A18009627F9 /* Down.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = D49980B51FA560F8004EE42E /* Down.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
14954EA521A7DCB9001933C4 /* README-11:2:18.md in Resources */ = {isa = PBXBuildFile; fileRef = 14954EA421A7DCA3001933C4 /* README-11:2:18.md */; };
14954EA621A7DCBA001933C4 /* README-11:2:18.md in Resources */ = {isa = PBXBuildFile; fileRef = 14954EA421A7DCA3001933C4 /* README-11:2:18.md */; };
14954EA521A7DCB9001933C4 /* README-sample.md in Resources */ = {isa = PBXBuildFile; fileRef = 14954EA421A7DCA3001933C4 /* README-sample.md */; };
14954EA621A7DCBA001933C4 /* README-sample.md in Resources */ = {isa = PBXBuildFile; fileRef = 14954EA421A7DCA3001933C4 /* README-sample.md */; };
8A07D7D31F085EC6004D7141 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A07D7D21F085EC6004D7141 /* AppDelegate.swift */; };
8A07D7D51F085EC6004D7141 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A07D7D41F085EC6004D7141 /* ViewController.swift */; };
8A07D7D81F085EC6004D7141 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8A07D7D61F085EC6004D7141 /* Main.storyboard */; };
8A07D7DA1F085EC6004D7141 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 8A07D7D91F085EC6004D7141 /* Assets.xcassets */; };
8A07D7DD1F085EC6004D7141 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8A07D7DB1F085EC6004D7141 /* LaunchScreen.storyboard */; };
D4591E9C226D293F00EBD476 /* Down.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D49980B51FA560F8004EE42E /* Down.framework */; };
D4591E9D226D293F00EBD476 /* Down.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = D49980B51FA560F8004EE42E /* Down.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
14090A5B2185414B00503C06 /* PBXContainerItemProxy */ = {
14664180218D2A18009627F9 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = D49980AF1FA560F8004EE42E /* Down.xcodeproj */;
proxyType = 1;
remoteGlobalIDString = 8A569F3F1E6B3E50008BE2AC;
remoteInfo = Down;
};
14664180218D2A18009627F9 /* PBXContainerItemProxy */ = {
D4591E9E226D293F00EBD476 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = D49980AF1FA560F8004EE42E /* Down.xcodeproj */;
proxyType = 1;
@@ -53,20 +53,16 @@
remoteGlobalIDString = 8AFAEAFB1E6E32E900E09B68;
remoteInfo = DownTests;
};
D4C77E06240EEB64004675B3 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = D49980AF1FA560F8004EE42E /* Down.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = EEBA153A2344845500B54ECB;
remoteInfo = DownSnapshotTests;
};
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
14090A5D2185414B00503C06 /* Embed Frameworks */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 10;
files = (
14090A5A2185414B00503C06 /* Down.framework in Embed Frameworks */,
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
};
14664182218D2A18009627F9 /* Embed Frameworks */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
@@ -78,6 +74,17 @@
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
};
D4591EA0226D293F00EBD476 /* Embed Frameworks */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 10;
files = (
D4591E9D226D293F00EBD476 /* Down.framework in Embed Frameworks */,
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
@@ -88,7 +95,7 @@
14090A522185411A00503C06 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
14090A542185411A00503C06 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
14090A5E2185443800503C06 /* macOS Demo.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "macOS Demo.entitlements"; sourceTree = "<group>"; };
14954EA421A7DCA3001933C4 /* README-11:2:18.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = "README-11:2:18.md"; sourceTree = "<group>"; };
14954EA421A7DCA3001933C4 /* README-sample.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = "README-sample.md"; sourceTree = "<group>"; };
8A07D7CF1F085EC6004D7141 /* Down-Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Down-Example.app"; sourceTree = BUILT_PRODUCTS_DIR; };
8A07D7D21F085EC6004D7141 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
8A07D7D41F085EC6004D7141 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
@@ -104,7 +111,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
14090A592185414B00503C06 /* Down.framework in Frameworks */,
D4591E9C226D293F00EBD476 /* Down.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -142,7 +149,7 @@
14954EA321A7DCA3001933C4 /* Shared */ = {
isa = PBXGroup;
children = (
14954EA421A7DCA3001933C4 /* README-11:2:18.md */,
14954EA421A7DCA3001933C4 /* README-sample.md */,
);
path = Shared;
sourceTree = "<group>";
@@ -186,6 +193,7 @@
children = (
D49980B51FA560F8004EE42E /* Down.framework */,
D49980B71FA560F8004EE42E /* DownTests.xctest */,
D4C77E07240EEB64004675B3 /* DownSnapshotTests.xctest */,
);
name = Products;
sourceTree = "<group>";
@@ -200,12 +208,12 @@
14090A452185411800503C06 /* Sources */,
14090A462185411800503C06 /* Frameworks */,
14090A472185411800503C06 /* Resources */,
14090A5D2185414B00503C06 /* Embed Frameworks */,
D4591EA0226D293F00EBD476 /* Embed Frameworks */,
);
buildRules = (
);
dependencies = (
14090A5C2185414B00503C06 /* PBXTargetDependency */,
D4591E9F226D293F00EBD476 /* PBXTargetDependency */,
);
name = "macOS Demo";
productName = "macOS Demo";
@@ -238,11 +246,13 @@
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 1000;
LastUpgradeCheck = 1000;
ORGANIZATIONNAME = down;
LastUpgradeCheck = 1130;
ORGANIZATIONNAME = Down;
TargetAttributes = {
14090A482185411800503C06 = {
CreatedOnToolsVersion = 10.0;
DevelopmentTeam = 7V68668DJN;
LastSwiftMigration = 1020;
ProvisioningStyle = Automatic;
SystemCapabilities = {
com.apple.Sandbox = {
@@ -252,13 +262,13 @@
};
8A07D7CE1F085EC6004D7141 = {
CreatedOnToolsVersion = 8.3.3;
LastSwiftMigration = 0900;
LastSwiftMigration = 1020;
};
};
};
buildConfigurationList = 8A07D7CA1F085EC6004D7141 /* Build configuration list for PBXProject "Down-Example" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
@@ -296,6 +306,13 @@
remoteRef = D49980B61FA560F8004EE42E /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
D4C77E07240EEB64004675B3 /* DownSnapshotTests.xctest */ = {
isa = PBXReferenceProxy;
fileType = wrapper.cfbundle;
path = DownSnapshotTests.xctest;
remoteRef = D4C77E06240EEB64004675B3 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
/* End PBXReferenceProxy section */
/* Begin PBXResourcesBuildPhase section */
@@ -305,7 +322,7 @@
files = (
14090A502185411A00503C06 /* Assets.xcassets in Resources */,
14090A532185411A00503C06 /* Main.storyboard in Resources */,
14954EA521A7DCB9001933C4 /* README-11:2:18.md in Resources */,
14954EA521A7DCB9001933C4 /* README-sample.md in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -313,7 +330,7 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
14954EA621A7DCBA001933C4 /* README-11:2:18.md in Resources */,
14954EA621A7DCBA001933C4 /* README-sample.md in Resources */,
8A07D7DD1F085EC6004D7141 /* LaunchScreen.storyboard in Resources */,
8A07D7DA1F085EC6004D7141 /* Assets.xcassets in Resources */,
8A07D7D81F085EC6004D7141 /* Main.storyboard in Resources */,
@@ -344,16 +361,16 @@
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
14090A5C2185414B00503C06 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
name = Down;
targetProxy = 14090A5B2185414B00503C06 /* PBXContainerItemProxy */;
};
14664181218D2A18009627F9 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
name = Down;
targetProxy = 14664180218D2A18009627F9 /* PBXContainerItemProxy */;
};
D4591E9F226D293F00EBD476 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
name = Down;
targetProxy = D4591E9E226D293F00EBD476 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */
@@ -396,17 +413,18 @@
CODE_SIGN_IDENTITY = "Mac Developer";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
DEVELOPMENT_TEAM = "";
DEVELOPMENT_TEAM = 7V68668DJN;
ENABLE_HARDENED_RUNTIME = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
INFOPLIST_FILE = "macOS Demo/Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
MACOSX_DEPLOYMENT_TARGET = 10.11;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = "com.glazeddonut.macOS-Demo";
PRODUCT_BUNDLE_IDENTIFIER = "com.downMarkdown.macOS-Demo";
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = macosx;
SWIFT_VERSION = 4.2;
SWIFT_VERSION = 5.0;
};
name = Debug;
};
@@ -422,16 +440,17 @@
CODE_SIGN_IDENTITY = "Mac Developer";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
DEVELOPMENT_TEAM = "";
DEVELOPMENT_TEAM = 7V68668DJN;
ENABLE_HARDENED_RUNTIME = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
INFOPLIST_FILE = "macOS Demo/Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
MACOSX_DEPLOYMENT_TARGET = 10.11;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = "com.glazeddonut.macOS-Demo";
PRODUCT_BUNDLE_IDENTIFIER = "com.downMarkdown.macOS-Demo";
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = macosx;
SWIFT_VERSION = 4.2;
SWIFT_VERSION = 5.0;
};
name = Release;
};
@@ -439,6 +458,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
@@ -499,6 +519,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
@@ -561,11 +582,10 @@
INFOPLIST_FILE = "Down-Example/Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 10.2;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "com.glazeddonut.Down-Example";
PRODUCT_BUNDLE_IDENTIFIER = "com.downMarkdown.Down-Example";
PRODUCT_NAME = "$(TARGET_NAME)";
SUPPORTED_PLATFORMS = "iphonesimulator iphoneos";
SWIFT_SWIFT3_OBJC_INFERENCE = Off;
SWIFT_VERSION = 4.0;
SWIFT_VERSION = 5.0;
};
name = Debug;
};
@@ -582,11 +602,10 @@
INFOPLIST_FILE = "Down-Example/Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 10.2;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "com.glazeddonut.Down-Example";
PRODUCT_BUNDLE_IDENTIFIER = "com.downMarkdown.Down-Example";
PRODUCT_NAME = "$(TARGET_NAME)";
SUPPORTED_PLATFORMS = "iphonesimulator iphoneos";
SWIFT_SWIFT3_OBJC_INFERENCE = Off;
SWIFT_VERSION = 4.0;
SWIFT_VERSION = 5.0;
};
name = Release;
};
@@ -0,0 +1,16 @@
{
"object": {
"pins": [
{
"package": "SnapshotTesting",
"repositoryURL": "https://github.com/pointfreeco/swift-snapshot-testing.git",
"state": {
"branch": null,
"revision": "c466812aa2e22898f27557e2e780d3aad7a27203",
"version": "1.8.2"
}
}
]
},
"version": 1
}
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1010"
LastUpgradeVersion = "1130"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@@ -27,8 +27,6 @@
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
@@ -38,8 +36,8 @@
ReferencedContainer = "container:Down-Example.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
<Testables>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
@@ -61,8 +59,6 @@
ReferencedContainer = "container:Down-Example.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1010"
LastUpgradeVersion = "1130"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@@ -27,8 +27,6 @@
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
@@ -38,8 +36,8 @@
ReferencedContainer = "container:Down-Example.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
<Testables>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
@@ -61,8 +59,6 @@
ReferencedContainer = "container:Down-Example.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>
+1 -9
View File
@@ -3,21 +3,13 @@
// Down-Example
//
// Created by Keaton Burleson on 7/1/17.
// Copyright © 2017 down. All rights reserved.
// Copyright © 2016-2019 Down. All rights reserved.
//
import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
return true
}
}
+2
View File
@@ -35,6 +35,8 @@
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
+44 -28
View File
@@ -3,51 +3,67 @@
// Down-Example
//
// Created by Keaton Burleson on 7/1/17.
// Copyright © 2017 down. All rights reserved.
// Copyright © 2016-2019 Down. All rights reserved.
//
import UIKit
import Down
class ViewController: UIViewController {
var downView: DownView!
final class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let readMeURL = Bundle.main.url(forResource: nil, withExtension: "md")!
let readMeContents = try! String(contentsOf: readMeURL)
renderDownInWebView()
}
}
private extension ViewController {
func renderDownInWebView() {
guard let readMeURL = Bundle.main.url(forResource: nil, withExtension: "md"),
let readMeContents = try? String(contentsOf: readMeURL)
else {
showError(message: "Could not load readme contents.")
return
}
do {
downView = try DownView(frame: view.bounds, markdownString: readMeContents, didLoadSuccessfully: {
let downView = try DownView(frame: view.bounds, markdownString: readMeContents, didLoadSuccessfully: {
print("Markdown was rendered.")
})
downView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(downView)
constrain(subview: downView)
createStatusBarBackgrounds(above: downView)
} catch {
let alertController = UIAlertController(title: "DownView Render Error",
message: error.localizedDescription,
preferredStyle: .alert)
self.present(alertController, animated: true, completion: nil)
showError(message: error.localizedDescription)
}
view.addSubview(downView)
createStatusBarBackgrounds()
}
func createStatusBarBackgrounds() {
func createStatusBarBackgrounds(above subview: UIView) {
let blurEffect = UIBlurEffect(style: .prominent)
let blurEffectView = UIVisualEffectView(effect: blurEffect)
blurEffectView.translatesAutoresizingMaskIntoConstraints = false
view.insertSubview(blurEffectView, aboveSubview: downView)
NSLayoutConstraint.activate([
blurEffectView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
blurEffectView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
blurEffectView.topAnchor.constraint(equalTo: topLayoutGuide.topAnchor),
blurEffectView.bottomAnchor.constraint(equalTo: topLayoutGuide.bottomAnchor)
])
view.insertSubview(blurEffectView, aboveSubview: subview)
constrain(subview: blurEffectView, bottomAnchor: topLayoutGuide.bottomAnchor)
}
func constrain(subview: UIView, bottomAnchor: NSLayoutYAxisAnchor? = nil) {
NSLayoutConstraint.activate([
subview.leadingAnchor.constraint(equalTo: view.leadingAnchor),
subview.trailingAnchor.constraint(equalTo: view.trailingAnchor),
subview.topAnchor.constraint(equalTo: topLayoutGuide.topAnchor),
subview.bottomAnchor.constraint(equalTo: bottomAnchor ?? bottomLayoutGuide.bottomAnchor)
])
}
func showError(message: String) {
let alertController = UIAlertController(title: "DownView Render Error",
message: message,
preferredStyle: .alert)
self.present(alertController, animated: true, completion: nil)
}
}
@@ -8,23 +8,26 @@
[![tvOS](https://img.shields.io/badge/OS-tvOS-orange.svg)](https://developer.apple.com/tvos/)
[![Coverage Status](https://coveralls.io/repos/github/iwasrobbed/Down/badge.svg?branch=master)](https://coveralls.io/github/iwasrobbed/Down?branch=master)
Blazing fast Markdown (CommonMark) rendering in Swift, built upon [cmark](https://github.com/jgm/cmark).
Blazing fast Markdown (CommonMark) rendering in Swift, built upon [cmark v0.28.3](https://github.com/commonmark/cmark).
Is your app using it? [Let us know!](mailto:rob@robphillips.me)
#### Maintainers
- [Rob Phillips](https://github.com/iwasrobbed)
- [John Nguyen](https://github.com/johnxnguyen)
- [Keaton Burleson](https://github.com/128keaton)
- [phoney](https://github.com/phoney)
- [Tony Arnold](https://github.com/tonyarnold)
- [Ken Harris](https://github.com/kengruven)
- [Other contributors](https://github.com/iwasrobbed/Down/graphs/contributors) 🙌
- [Chris Zielinski](https://github.com/chriszielinski)
- [Other contributors](https://github.com/iwasrobbed/Down/graphs/contributors) 🙌
### Installation
Note: Swift 4 support is now on the `master` branch and any tag >= 0.4.x (Swift 3 is 0.3.x)
Quickly install using [CocoaPods](https://cocoapods.org):
Quickly install using [CocoaPods](https://cocoapods.org):
```ruby
pod 'Down'
@@ -35,7 +38,7 @@ Or [Carthage](https://github.com/Carthage/Carthage):
```
github "iwasrobbed/Down"
```
Due to limitations in Carthage regarding platform specification, you need to define the platform with Carthage.
Due to limitations in Carthage regarding platform specification, you need to define the platform with Carthage.
e.g.
@@ -51,7 +54,7 @@ Or manually install:
### Robust Performance
>[cmark](https://github.com/jgm/cmark) can render a Markdown version of War and Peace in the blink of an eye (127 milliseconds on a ten year old laptop, vs. 100-400 milliseconds for an eye blink). In our [benchmarks](https://github.com/jgm/cmark/blob/master/benchmarks.md), cmark is 10,000 times faster than the original Markdown.pl, and on par with the very fastest available Markdown processors.
>[cmark](https://github.com/commonmark/cmark) can render a Markdown version of War and Peace in the blink of an eye (127 milliseconds on a ten year old laptop, vs. 100-400 milliseconds for an eye blink). In our [benchmarks](https://github.com/commonmark/cmark/blob/master/benchmarks.md), cmark is 10,000 times faster than the original Markdown.pl, and on par with the very fastest available Markdown processors.
> The library has been extensively fuzz-tested using [american fuzzy lop](http://lcamtuf.coredump.cx/afl). The test suite includes pathological cases that bring many other Markdown parsers to a crawl (for example, thousands-deep nested bracketed text or block quotes).
@@ -71,25 +74,22 @@ The `DownView` class offers a very simple way to parse a UTF-8 encoded string wi
```swift
let downView = try? DownView(frame: self.view.bounds, markdownString: "**Oh Hai**") {
// Optional callback for loading finished
// Optional callback for loading finished
}
// Now add to view or constrain w/ Autolayout
// Or you could optionally update the contents at some point:
try? downView?.update(markdownString: "## [Google](https://google.com)") {
// Optional callback for loading finished
// Optional callback for loading finished
}
```
Meta example of rendering this README:
![Example gif](https://raw.githubusercontent.com/iwasrobbed/Down/master/Images/ohhai.gif)
##### Prevent zoom
The default implementation of the `DownView` allows for zooming in the rendered content. If you want to disable this, then youll need to instantiate the `DownView` with a custom bundle where the `viewport` in `index.html` has been assigned `user-scalable=no`. More info can be found [here](https://github.com/iwasrobbed/Down/pull/30).
![Example gif](Images/ohhai.gif)
### Parsing API
The `Down` struct has everything you need if you just want out-of-the-box setup for parsing and conversion.
The `Down` struct has everything you need if you just want out-of-the-box setup for parsing and conversion.
```swift
let down = Down(markdownString: "## [Down](https://github.com/iwasrobbed/Down)")
@@ -142,71 +142,82 @@ Example:
```swift
public struct MarkdownToHTML: DownHTMLRenderable {
/**
A string containing CommonMark Markdown
*/
public var markdownString: String
/**
A string containing CommonMark Markdown
*/
public var markdownString: String
/**
Initializes the container with a CommonMark Markdown string which can then be rendered as HTML using `toHTML()`
/**
Initializes the container with a CommonMark Markdown string which can then be rendered as HTML using `toHTML()`
- parameter markdownString: A string containing CommonMark Markdown
- parameter markdownString: A string containing CommonMark Markdown
- returns: An instance of Self
*/
@warn_unused_result
public init(markdownString: String) {
self.markdownString = markdownString
}
- returns: An instance of Self
*/
@warn_unused_result
public init(markdownString: String) {
self.markdownString = markdownString
}
}
```
### Configuration of `DownView`
`DownView` can be configured with a custom bundle using your own HTML / CSS or to do things like supporting
Dynamic Type or custom fonts, etc. It's completely configurable.
This option can be found in [DownView's instantiation function](https://github.com/iwasrobbed/Down/blob/master/Source/Views/DownView.swift#L26).
##### Prevent zoom
The default implementation of the `DownView` allows for zooming in the rendered content. If you want to disable this, then youll need to instantiate the `DownView` with a custom bundle where the `viewport` in `index.html` has been assigned `user-scalable=no`. More info can be found [here](https://github.com/iwasrobbed/Down/pull/30).
### Options
Each protocol has options that will influence either rendering or parsing:
```swift
/**
Default options
Default options
*/
public static let `default` = DownOptions(rawValue: 0)
// MARK: - Rendering Options
/**
Include a `data-sourcepos` attribute on all block elements
Include a `data-sourcepos` attribute on all block elements
*/
public static let sourcePos = DownOptions(rawValue: 1 << 1)
/**
Render `softbreak` elements as hard line breaks.
Render `softbreak` elements as hard line breaks.
*/
public static let hardBreaks = DownOptions(rawValue: 1 << 2)
/**
Suppress raw HTML and unsafe links (`javascript:`, `vbscript:`,
`file:`, and `data:`, except for `image/png`, `image/gif`,
`image/jpeg`, or `image/webp` mime types). Raw HTML is replaced
by a placeholder HTML comment. Unsafe links are replaced by
empty strings.
Suppress raw HTML and unsafe links (`javascript:`, `vbscript:`,
`file:`, and `data:`, except for `image/png`, `image/gif`,
`image/jpeg`, or `image/webp` mime types). Raw HTML is replaced
by a placeholder HTML comment. Unsafe links are replaced by
empty strings.
*/
public static let safe = DownOptions(rawValue: 1 << 3)
// MARK: - Parsing Options
/**
Normalize tree by consolidating adjacent text nodes.
Normalize tree by consolidating adjacent text nodes.
*/
public static let normalize = DownOptions(rawValue: 1 << 4)
/**
Validate UTF-8 in the input before parsing, replacing illegal
sequences with the replacement character U+FFFD.
Validate UTF-8 in the input before parsing, replacing illegal
sequences with the replacement character U+FFFD.
*/
public static let validateUTF8 = DownOptions(rawValue: 1 << 5)
/**
Convert straight quotes to curly, --- to em dashes, -- to en dashes.
Convert straight quotes to curly, --- to em dashes, -- to en dashes.
*/
public static let smart = DownOptions(rawValue: 1 << 6)
```
@@ -222,6 +233,6 @@ Down is built upon the [CommonMark](http://commonmark.org) specification.
Please feel free to fork and create a pull request for bug fixes or improvements, being sure to maintain the general coding style, adding tests, and adding comments as necessary.
### Credit
This library is a wrapper around [cmark](https://github.com/jgm/cmark), which is built upon the [CommonMark](http://commonmark.org) Markdown specification.
This library is a wrapper around [cmark](https://github.com/commonmark/cmark), which is built upon the [CommonMark](http://commonmark.org) Markdown specification.
[cmark](https://github.com/jgm/cmark) is Copyright (c) 2014 - 2017, John MacFarlane. View [full license](https://github.com/jgm/cmark/blob/master/COPYING).
[cmark](https://github.com/commonmark/cmark) is Copyright (c) 2014 - 2017, John MacFarlane. View [full license](https://github.com/commonmark/cmark/blob/master/COPYING).
+2 -13
View File
@@ -3,22 +3,11 @@
// macOS Demo
//
// Created by Chris Zielinski on 10/27/18.
// Copyright © 2018 down. All rights reserved.
// Copyright © 2016-2019 Down. All rights reserved.
//
import Cocoa
@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
func applicationDidFinishLaunching(_ aNotification: Notification) {
// Insert code here to initialize your application
}
func applicationWillTerminate(_ aNotification: Notification) {
// Insert code here to tear down your application
}
}
class AppDelegate: NSObject, NSApplicationDelegate {}
+1 -1
View File
@@ -23,7 +23,7 @@
<key>LSMinimumSystemVersion</key>
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2018 down. All rights reserved.</string>
<string>Copyright © 2016-2019 Down. All rights reserved.</string>
<key>NSMainStoryboardFile</key>
<string>Main</string>
<key>NSPrincipalClass</key>
+14 -9
View File
@@ -3,32 +3,37 @@
// macOS Demo
//
// Created by Chris Zielinski on 10/27/18.
// Copyright © 2018 down. All rights reserved.
// Copyright © 2016-2019 Down. All rights reserved.
//
import Cocoa
import Down
class ViewController: NSViewController {
var downView: DownView!
final class ViewController: NSViewController {
override func viewDidLoad() {
super.viewDidLoad()
renderDownInWebView()
}
}
private extension ViewController {
func renderDownInWebView() {
let readMeURL = Bundle.main.url(forResource: nil, withExtension: "md")!
let readMeContents = try! String(contentsOf: readMeURL)
do {
downView = try DownView(frame: view.bounds, markdownString: readMeContents, didLoadSuccessfully: {
let downView = try DownView(frame: view.bounds, markdownString: readMeContents, didLoadSuccessfully: {
print("Markdown was rendered.")
})
downView.autoresizingMask = [.width, .height]
view.addSubview(downView, positioned: .below, relativeTo: nil)
} catch {
NSApp.presentError(error)
}
downView.autoresizingMask = [.width, .height]
view.addSubview(downView, positioned: .below, relativeTo: nil)
}
}
+13 -13
View File
@@ -1,23 +1,23 @@
Pod::Spec.new do |spec|
spec.name = "Down"
spec.summary = "Blazing fast Markdown rendering in Swift, built upon cmark."
spec.version = "0.6.2"
spec.homepage = "https://github.com/iwasrobbed/Down"
spec.version = "0.11.0"
spec.homepage = "https://github.com/johnxnguyen/Down"
spec.license = { :type => "MIT", :file => "LICENSE" }
spec.authors = { "Rob Phillips" => "rob@robphillips.me" }
spec.source = { :git => "https://github.com/iwasrobbed/Down.git", :tag => "v" + spec.version.to_s }
spec.source_files = "Source/{cmark,Enums & Options,Extensions,Renderers}/**/*.{h,c,swift}", "Source/*"
spec.ios.source_files = "Source/Views/**"
spec.osx.source_files = "Source/Views/**"
spec.public_header_files = "Source/*.h"
spec.authors = { "John Nguyen" => "polyxo@protonmail.com" }
spec.source = { :git => "https://github.com/johnxnguyen/Down.git", :tag => "v" + spec.version.to_s }
spec.source_files = "Sources/Down/{AST,Enums & Options,Extensions,Renderers}/**/*.swift", "Sources/cmark/*.{h,c}", "Sources/Down/*"
spec.ios.source_files = "Sources/Down/Views/**"
spec.osx.source_files = "Sources/Down/Views/**"
spec.public_header_files = "Sources/Down/*.h"
spec.ios.deployment_target = "9.0"
spec.tvos.deployment_target = "9.0"
spec.osx.deployment_target = "10.11"
spec.requires_arc = true
spec.module_name = "Down"
spec.preserve_paths = "Source/cmark/module.modulemap", "Source/cmark/*.inc", "Source/cmark/COPYING"
spec.pod_target_xcconfig = { 'SWIFT_INCLUDE_PATHS' => '$(SRCROOT)/Down/Source/cmark/**' }
spec.compiler_flags = '-Wno-shorten-64-to-32'
spec.ios.resource = 'Resources/DownView.bundle'
spec.osx.resource = 'Resources/DownView.bundle'
spec.preserve_paths = "Sources/cmark/include/module.modulemap", "Sources/cmark/*.inc", "Sources/cmark/COPYING"
spec.pod_target_xcconfig = { 'SWIFT_INCLUDE_PATHS' => '$(SRCROOT)/Down/Sources/cmark/**' }
spec.ios.resource = 'Sources/Down/Resources/DownView.bundle'
spec.osx.resource = 'Sources/Down/Resources/DownView.bundle'
spec.swift_versions = ['5.0', '5.1']
end
+553 -59
View File
@@ -3,11 +3,12 @@
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objectVersion = 52;
objects = {
/* Begin PBXBuildFile section */
14C5E33521877CE900D5380C /* DownView.bundle in Resources */ = {isa = PBXBuildFile; fileRef = D41689B51CFFE6BB00E5802B /* DownView.bundle */; };
26CABB93252B4D490032183C /* ChildSequence.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26CABB92252B4D490032183C /* ChildSequence.swift */; };
8A569F481E6B3ED2008BE2AC /* DownView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D43AE5D91CFFD0D0006E1522 /* DownView.swift */; };
8A569F491E6B3ED9008BE2AC /* blocks.c in Sources */ = {isa = PBXBuildFile; fileRef = D4201EF71CFA5D63008EEC6E /* blocks.c */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; };
8A569F4A1E6B3ED9008BE2AC /* buffer.c in Sources */ = {isa = PBXBuildFile; fileRef = D4201EF81CFA5D63008EEC6E /* buffer.c */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; };
@@ -21,13 +22,11 @@
8A569F521E6B3ED9008BE2AC /* cmark_version.h in Headers */ = {isa = PBXBuildFile; fileRef = D4201F011CFA5D63008EEC6E /* cmark_version.h */; };
8A569F531E6B3ED9008BE2AC /* commonmark.c in Sources */ = {isa = PBXBuildFile; fileRef = D4201F021CFA5D63008EEC6E /* commonmark.c */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; };
8A569F541E6B3ED9008BE2AC /* config.h in Headers */ = {isa = PBXBuildFile; fileRef = D4201F031CFA5D63008EEC6E /* config.h */; };
8A569F551E6B3ED9008BE2AC /* debug.h in Headers */ = {isa = PBXBuildFile; fileRef = D4201F041CFA5D63008EEC6E /* debug.h */; };
8A569F561E6B3ED9008BE2AC /* houdini.h in Headers */ = {isa = PBXBuildFile; fileRef = D4201F061CFA5D63008EEC6E /* houdini.h */; };
8A569F571E6B3ED9008BE2AC /* houdini_href_e.c in Sources */ = {isa = PBXBuildFile; fileRef = D4201F071CFA5D63008EEC6E /* houdini_href_e.c */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; };
8A569F581E6B3ED9008BE2AC /* houdini_html_e.c in Sources */ = {isa = PBXBuildFile; fileRef = D4201F081CFA5D63008EEC6E /* houdini_html_e.c */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; };
8A569F591E6B3ED9008BE2AC /* houdini_html_u.c in Sources */ = {isa = PBXBuildFile; fileRef = D4201F091CFA5D63008EEC6E /* houdini_html_u.c */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; };
8A569F5A1E6B3ED9008BE2AC /* html.c in Sources */ = {isa = PBXBuildFile; fileRef = D4201F0A1CFA5D63008EEC6E /* html.c */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; };
8A569F5B1E6B3ED9008BE2AC /* html_unescape.h in Headers */ = {isa = PBXBuildFile; fileRef = D4201F0B1CFA5D63008EEC6E /* html_unescape.h */; };
8A569F5C1E6B3ED9008BE2AC /* inlines.c in Sources */ = {isa = PBXBuildFile; fileRef = D4201F0C1CFA5D63008EEC6E /* inlines.c */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; };
8A569F5D1E6B3ED9008BE2AC /* inlines.h in Headers */ = {isa = PBXBuildFile; fileRef = D4201F0D1CFA5D63008EEC6E /* inlines.h */; };
8A569F5E1E6B3ED9008BE2AC /* iterator.c in Sources */ = {isa = PBXBuildFile; fileRef = D4201F0E1CFA5D63008EEC6E /* iterator.c */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; };
@@ -66,6 +65,74 @@
8AFAEB091E6E331700E09B68 /* StringTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D438696B1D00D27700E95A1F /* StringTests.swift */; };
907C64651EC133780095FEE1 /* TestDownView.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 907C64621EC120530095FEE1 /* TestDownView.bundle */; };
90A40A9C1EC03292004F2E91 /* Down.framework in Copy Bundled Frameworks */ = {isa = PBXBuildFile; fileRef = 8A569F401E6B3E50008BE2AC /* Down.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
EE0E54F82300800E0070C83F /* BlockBackgroundColorAttribute.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE0E54F72300800E0070C83F /* BlockBackgroundColorAttribute.swift */; };
EE3E7E38260400E800170A52 /* DownDebugLayoutManagerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE5D2DF822FC9E89009EC13E /* DownDebugLayoutManagerTests.swift */; };
EE3E7E3F260400EE00170A52 /* LinkStyleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE5D2DF522FC99A6009EC13E /* LinkStyleTests.swift */; };
EE3E7E46260400F100170A52 /* CodeBlockStyleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE64722A22F8BB0B00C5F0BA /* CodeBlockStyleTests.swift */; };
EE3E7E4D260400F500170A52 /* BlockQuoteStyleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEA2BDC722F705B900D0C72C /* BlockQuoteStyleTests.swift */; };
EE3E7E54260400F900170A52 /* ThematicBreakSyleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEA5C02A22F58B8000B91D60 /* ThematicBreakSyleTests.swift */; };
EE3E7E5B260400FC00170A52 /* HeadingStyleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE99E3DD22F0C83F00BCE15B /* HeadingStyleTests.swift */; };
EE3E7E622604010000170A52 /* InlineStyleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE9E886222EF76040005948C /* InlineStyleTests.swift */; };
EE3E7E692604010300170A52 /* ListItemStyleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE335C4922EDC85900648842 /* ListItemStyleTests.swift */; };
EE3E7E702604010700170A52 /* StylerTestSuite.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE59C30122ECF0BD006EE8A8 /* StylerTestSuite.swift */; };
EE3E7E812604019300170A52 /* SnapshotTesting in Frameworks */ = {isa = PBXBuildFile; productRef = EE3E7E802604019300170A52 /* SnapshotTesting */; };
EE3E7E88260401F000170A52 /* VisitorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE64FEEF225BEB3900A35B34 /* VisitorTests.swift */; };
EE408A39230338B600E5278A /* CGPointTranslateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE408A38230338B600E5278A /* CGPointTranslateTests.swift */; };
EE408A3B2303399B00E5278A /* CGRectHelpersTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE408A3A2303399B00E5278A /* CGRectHelpersTests.swift */; };
EE408A3D23033B6B00E5278A /* ListItemPrefixGeneratorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE408A3C23033B6B00E5278A /* ListItemPrefixGeneratorTests.swift */; };
EE44848B2301E51C0065C836 /* CodeBlockOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE44848A2301E51C0065C836 /* CodeBlockOptions.swift */; };
EE4484912301F2920065C836 /* CGPoint+Translate.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE4484902301F2920065C836 /* CGPoint+Translate.swift */; };
EE4484932301F2DB0065C836 /* CGRect+Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE4484922301F2DB0065C836 /* CGRect+Helpers.swift */; };
EE469B11226CF3B500C0655D /* BaseNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE469B10226CF3B500C0655D /* BaseNode.swift */; };
EE48C7D922EC9250004815ED /* ParagraphStyleCollection.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE48C7D822EC9250004815ED /* ParagraphStyleCollection.swift */; };
EE48C7DB22EC946F004815ED /* ColorCollection.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE48C7DA22EC946F004815ED /* ColorCollection.swift */; };
EE4F77C322FF3F170026A983 /* DownStylerConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE4F77C222FF3F170026A983 /* DownStylerConfiguration.swift */; };
EE5F2BA42262564A00B7C0F3 /* Styler.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE5F2BA32262564A00B7C0F3 /* Styler.swift */; };
EE8F38CC22BFB2420056270E /* NodeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE8F38CB22BFB2420056270E /* NodeTests.swift */; };
EE8F38CE22BFEDE50056270E /* ListItemPrefixGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE8F38CD22BFEDE50056270E /* ListItemPrefixGenerator.swift */; };
EE97253E22C130D8004D3B3A /* NSMutableAttributedString+AttributesTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE97253D22C130D8004D3B3A /* NSMutableAttributedString+AttributesTests.swift */; };
EE97254322C14B79004D3B3A /* NSAttributedString+HelpersTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE97254222C14B79004D3B3A /* NSAttributedString+HelpersTests.swift */; };
EEA2BDC422F704F200D0C72C /* QuoteStripeOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEA2BDC322F704F200D0C72C /* QuoteStripeOptions.swift */; };
EEA2BDC622F7057600D0C72C /* ListItemOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEA2BDC522F7057600D0C72C /* ListItemOptions.swift */; };
EEA2BDCA22F7152B00D0C72C /* ThematicBreakOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEA2BDC922F7152B00D0C72C /* ThematicBreakOptions.swift */; };
EEA5C02922F58A0900B91D60 /* DownTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEA5C02822F58A0900B91D60 /* DownTextView.swift */; };
EEA5C02D22F5C96B00B91D60 /* QuoteStripeAttribute.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEA5C02C22F5C96B00B91D60 /* QuoteStripeAttribute.swift */; };
EEBE62F025E28F3D005CCAD6 /* BundleHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEBE62EF25E28F3D005CCAD6 /* BundleHelper.swift */; };
EED7FED825E3133C0033E33A /* DownView (macOS).bundle in Resources */ = {isa = PBXBuildFile; fileRef = 14C5E33621877FCD00D5380C /* DownView (macOS).bundle */; };
EED8DA8E22BE404F00E54492 /* DownStyler.swift in Sources */ = {isa = PBXBuildFile; fileRef = EED8DA8D22BE404F00E54492 /* DownStyler.swift */; };
EED8DA9022BECBAE00E54492 /* NSAttributedString+Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = EED8DA8F22BECBAE00E54492 /* NSAttributedString+Helpers.swift */; };
EED8DA9222BECBF200E54492 /* NSMutableAttributedString+Attributes.swift in Sources */ = {isa = PBXBuildFile; fileRef = EED8DA9122BECBF200E54492 /* NSMutableAttributedString+Attributes.swift */; };
EED8DA9422BECC2100E54492 /* UIFont+Traits.swift in Sources */ = {isa = PBXBuildFile; fileRef = EED8DA9322BECC2100E54492 /* UIFont+Traits.swift */; };
EED8DA9722BECD7500E54492 /* FontCollection.swift in Sources */ = {isa = PBXBuildFile; fileRef = EED8DA9622BECD7500E54492 /* FontCollection.swift */; };
EEE2C7F122C2AFEF001B7054 /* ListItemParagraphStyler.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEE2C7F022C2AFEF001B7054 /* ListItemParagraphStyler.swift */; };
EEEBEE47225D298D00AE438D /* Document.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEEBEE46225D298D00AE438D /* Document.swift */; };
EEEBEE49225D29C200AE438D /* BlockQuote.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEEBEE48225D29C200AE438D /* BlockQuote.swift */; };
EEEBEE4B225D29D800AE438D /* List.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEEBEE4A225D29D800AE438D /* List.swift */; };
EEEBEE4D225D2A0200AE438D /* Item.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEEBEE4C225D2A0200AE438D /* Item.swift */; };
EEEBEE4F225D2A1400AE438D /* CodeBlock.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEEBEE4E225D2A1400AE438D /* CodeBlock.swift */; };
EEEBEE51225D2A2900AE438D /* HtmlBlock.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEEBEE50225D2A2900AE438D /* HtmlBlock.swift */; };
EEEBEE53225D2A3C00AE438D /* CustomBlock.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEEBEE52225D2A3C00AE438D /* CustomBlock.swift */; };
EEEBEE55225D2A4E00AE438D /* Paragraph.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEEBEE54225D2A4E00AE438D /* Paragraph.swift */; };
EEEBEE57225D2A6200AE438D /* Heading.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEEBEE56225D2A6200AE438D /* Heading.swift */; };
EEEBEE59225D2A7000AE438D /* ThematicBreak.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEEBEE58225D2A7000AE438D /* ThematicBreak.swift */; };
EEEBEE5B225D2A7E00AE438D /* Text.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEEBEE5A225D2A7E00AE438D /* Text.swift */; };
EEEBEE5D225D2A8F00AE438D /* SoftBreak.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEEBEE5C225D2A8F00AE438D /* SoftBreak.swift */; };
EEEBEE5F225D2AA700AE438D /* LineBreak.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEEBEE5E225D2AA700AE438D /* LineBreak.swift */; };
EEEBEE61225D2AC000AE438D /* Code.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEEBEE60225D2AC000AE438D /* Code.swift */; };
EEEBEE63225D2AD400AE438D /* HtmlInline.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEEBEE62225D2AD400AE438D /* HtmlInline.swift */; };
EEEBEE65225D2AE800AE438D /* CustomInline.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEEBEE64225D2AE800AE438D /* CustomInline.swift */; };
EEEBEE67225D2AF900AE438D /* Emphasis.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEEBEE66225D2AF900AE438D /* Emphasis.swift */; };
EEEBEE69225D2B1200AE438D /* Strong.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEEBEE68225D2B1200AE438D /* Strong.swift */; };
EEEBEE6B225D2B2200AE438D /* Link.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEEBEE6A225D2B2200AE438D /* Link.swift */; };
EEEBEE6D225D2B3200AE438D /* Image.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEEBEE6C225D2B3200AE438D /* Image.swift */; };
EEEBEE70225D2B9D00AE438D /* DebugVisitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEEBEE6F225D2B9D00AE438D /* DebugVisitor.swift */; };
EEEBEE72225D2F9200AE438D /* AttributedStringVisitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEEBEE71225D2F9200AE438D /* AttributedStringVisitor.swift */; };
EEF1376F2259E53400D7DDE0 /* Node.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEF1376E2259E53400D7DDE0 /* Node.swift */; };
EEF137712259E7E700D7DDE0 /* Visitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEF137702259E7E700D7DDE0 /* Visitor.swift */; };
EEF8580F22FA101C0025370B /* DownDebugLayoutManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEF8580E22FA101C0025370B /* DownDebugLayoutManager.swift */; };
EEF8581122FA11690025370B /* DownDebugTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEF8581022FA11690025370B /* DownDebugTextView.swift */; };
EEFFFDDB22F4C36800036FD5 /* ThematicBreakAttribute.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEFFFDDA22F4C36800036FD5 /* ThematicBreakAttribute.swift */; };
EEFFFDDD22F4C8AB00036FD5 /* DownLayoutManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEFFFDDC22F4C8AB00036FD5 /* DownLayoutManager.swift */; };
/* End PBXBuildFile section */
/* Begin PBXBuildRule section */
@@ -74,6 +141,8 @@
compilerSpec = com.apple.compilers.pbxcp;
filePatterns = "*.inc";
fileType = pattern.proxy;
inputFiles = (
);
isEditable = 1;
outputFiles = (
);
@@ -84,6 +153,8 @@
compilerSpec = com.apple.compilers.pbxcp;
filePatterns = "*COPYING";
fileType = pattern.proxy;
inputFiles = (
);
isEditable = 1;
outputFiles = (
);
@@ -94,6 +165,8 @@
compilerSpec = com.apple.compilers.pbxcp;
filePatterns = "*.modulemap";
fileType = pattern.proxy;
inputFiles = (
);
isEditable = 1;
outputFiles = (
);
@@ -127,8 +200,10 @@
/* Begin PBXFileReference section */
14C5E33621877FCD00D5380C /* DownView (macOS).bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = "DownView (macOS).bundle"; sourceTree = "<group>"; };
26CABB92252B4D490032183C /* ChildSequence.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChildSequence.swift; sourceTree = "<group>"; };
8A569F401E6B3E50008BE2AC /* Down.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Down.framework; sourceTree = BUILT_PRODUCTS_DIR; };
8AFAEAFB1E6E32E900E09B68 /* DownTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = DownTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
8C73B9B522A687C400C8E60F /* module.modulemap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = "<group>"; };
907C64621EC120530095FEE1 /* TestDownView.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = TestDownView.bundle; sourceTree = "<group>"; };
90A40A951EC02FF6004F2E91 /* Down-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Down-Info.plist"; sourceTree = "<group>"; };
90A40A961EC02FF6004F2E91 /* DownTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "DownTests-Info.plist"; sourceTree = "<group>"; };
@@ -151,13 +226,11 @@
D4201F011CFA5D63008EEC6E /* cmark_version.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cmark_version.h; sourceTree = "<group>"; };
D4201F021CFA5D63008EEC6E /* commonmark.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = commonmark.c; sourceTree = "<group>"; };
D4201F031CFA5D63008EEC6E /* config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = config.h; sourceTree = "<group>"; };
D4201F041CFA5D63008EEC6E /* debug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug.h; sourceTree = "<group>"; };
D4201F061CFA5D63008EEC6E /* houdini.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = houdini.h; sourceTree = "<group>"; };
D4201F071CFA5D63008EEC6E /* houdini_href_e.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = houdini_href_e.c; sourceTree = "<group>"; };
D4201F081CFA5D63008EEC6E /* houdini_html_e.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = houdini_html_e.c; sourceTree = "<group>"; };
D4201F091CFA5D63008EEC6E /* houdini_html_u.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = houdini_html_u.c; sourceTree = "<group>"; };
D4201F0A1CFA5D63008EEC6E /* html.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = html.c; sourceTree = "<group>"; };
D4201F0B1CFA5D63008EEC6E /* html_unescape.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = html_unescape.h; sourceTree = "<group>"; };
D4201F0C1CFA5D63008EEC6E /* inlines.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = inlines.c; sourceTree = "<group>"; };
D4201F0D1CFA5D63008EEC6E /* inlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = inlines.h; sourceTree = "<group>"; };
D4201F0E1CFA5D63008EEC6E /* iterator.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = iterator.c; sourceTree = "<group>"; };
@@ -176,7 +249,6 @@
D4201F1C1CFA5D63008EEC6E /* utf8.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = utf8.c; sourceTree = "<group>"; };
D4201F1D1CFA5D63008EEC6E /* utf8.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = utf8.h; sourceTree = "<group>"; };
D4201F1E1CFA5D63008EEC6E /* xml.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = xml.c; sourceTree = "<group>"; };
D42869501CFF501200FACB4C /* module.modulemap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = "<group>"; };
D438696B1D00D27700E95A1F /* StringTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StringTests.swift; sourceTree = "<group>"; };
D43AE5C91CFFAE4D006E1522 /* NSAttributedString+HTML.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSAttributedString+HTML.swift"; sourceTree = "<group>"; };
D43AE5D91CFFD0D0006E1522 /* DownView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DownView.swift; sourceTree = "<group>"; };
@@ -193,6 +265,74 @@
D4CF88971CFFAC2C00F07FD1 /* DownAttributedStringRenderable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DownAttributedStringRenderable.swift; sourceTree = "<group>"; };
D4DC91131CFDED4B0091CE09 /* DownCommonMarkRenderable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DownCommonMarkRenderable.swift; sourceTree = "<group>"; };
D4F948DB1D00A4A800C9C0F6 /* NSAttributedStringTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NSAttributedStringTests.swift; sourceTree = "<group>"; };
EE0E54F72300800E0070C83F /* BlockBackgroundColorAttribute.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlockBackgroundColorAttribute.swift; sourceTree = "<group>"; };
EE335C4922EDC85900648842 /* ListItemStyleTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListItemStyleTests.swift; sourceTree = "<group>"; };
EE39B28026063E0D002C4F8D /* .swiftlint.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = .swiftlint.yml; sourceTree = "<group>"; };
EE408A38230338B600E5278A /* CGPointTranslateTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CGPointTranslateTests.swift; sourceTree = "<group>"; };
EE408A3A2303399B00E5278A /* CGRectHelpersTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CGRectHelpersTests.swift; sourceTree = "<group>"; };
EE408A3C23033B6B00E5278A /* ListItemPrefixGeneratorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListItemPrefixGeneratorTests.swift; sourceTree = "<group>"; };
EE44848A2301E51C0065C836 /* CodeBlockOptions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CodeBlockOptions.swift; sourceTree = "<group>"; };
EE4484902301F2920065C836 /* CGPoint+Translate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CGPoint+Translate.swift"; sourceTree = "<group>"; };
EE4484922301F2DB0065C836 /* CGRect+Helpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CGRect+Helpers.swift"; sourceTree = "<group>"; };
EE469B10226CF3B500C0655D /* BaseNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseNode.swift; sourceTree = "<group>"; };
EE48C7D822EC9250004815ED /* ParagraphStyleCollection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParagraphStyleCollection.swift; sourceTree = "<group>"; };
EE48C7DA22EC946F004815ED /* ColorCollection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorCollection.swift; sourceTree = "<group>"; };
EE4F77C222FF3F170026A983 /* DownStylerConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DownStylerConfiguration.swift; sourceTree = "<group>"; };
EE54F96E22EB9CE500628683 /* SnapshotTesting.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SnapshotTesting.framework; path = Carthage/Build/iOS/SnapshotTesting.framework; sourceTree = "<group>"; };
EE59C30122ECF0BD006EE8A8 /* StylerTestSuite.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StylerTestSuite.swift; sourceTree = "<group>"; };
EE5D2DF522FC99A6009EC13E /* LinkStyleTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkStyleTests.swift; sourceTree = "<group>"; };
EE5D2DF822FC9E89009EC13E /* DownDebugLayoutManagerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DownDebugLayoutManagerTests.swift; sourceTree = "<group>"; };
EE5F2BA32262564A00B7C0F3 /* Styler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Styler.swift; sourceTree = "<group>"; };
EE64722A22F8BB0B00C5F0BA /* CodeBlockStyleTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CodeBlockStyleTests.swift; sourceTree = "<group>"; };
EE64FEEF225BEB3900A35B34 /* VisitorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VisitorTests.swift; sourceTree = "<group>"; };
EE8F38CB22BFB2420056270E /* NodeTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NodeTests.swift; sourceTree = "<group>"; };
EE8F38CD22BFEDE50056270E /* ListItemPrefixGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListItemPrefixGenerator.swift; sourceTree = "<group>"; };
EE97253D22C130D8004D3B3A /* NSMutableAttributedString+AttributesTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSMutableAttributedString+AttributesTests.swift"; sourceTree = "<group>"; };
EE97254222C14B79004D3B3A /* NSAttributedString+HelpersTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSAttributedString+HelpersTests.swift"; sourceTree = "<group>"; };
EE99E3DD22F0C83F00BCE15B /* HeadingStyleTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadingStyleTests.swift; sourceTree = "<group>"; };
EE9E886222EF76040005948C /* InlineStyleTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InlineStyleTests.swift; sourceTree = "<group>"; };
EEA2BDC322F704F200D0C72C /* QuoteStripeOptions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuoteStripeOptions.swift; sourceTree = "<group>"; };
EEA2BDC522F7057600D0C72C /* ListItemOptions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListItemOptions.swift; sourceTree = "<group>"; };
EEA2BDC722F705B900D0C72C /* BlockQuoteStyleTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlockQuoteStyleTests.swift; sourceTree = "<group>"; };
EEA2BDC922F7152B00D0C72C /* ThematicBreakOptions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThematicBreakOptions.swift; sourceTree = "<group>"; };
EEA5C02822F58A0900B91D60 /* DownTextView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DownTextView.swift; sourceTree = "<group>"; };
EEA5C02A22F58B8000B91D60 /* ThematicBreakSyleTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThematicBreakSyleTests.swift; sourceTree = "<group>"; };
EEA5C02C22F5C96B00B91D60 /* QuoteStripeAttribute.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuoteStripeAttribute.swift; sourceTree = "<group>"; };
EEBE62EF25E28F3D005CCAD6 /* BundleHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BundleHelper.swift; sourceTree = "<group>"; };
EED8DA8D22BE404F00E54492 /* DownStyler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DownStyler.swift; sourceTree = "<group>"; };
EED8DA8F22BECBAE00E54492 /* NSAttributedString+Helpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSAttributedString+Helpers.swift"; sourceTree = "<group>"; };
EED8DA9122BECBF200E54492 /* NSMutableAttributedString+Attributes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSMutableAttributedString+Attributes.swift"; sourceTree = "<group>"; };
EED8DA9322BECC2100E54492 /* UIFont+Traits.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIFont+Traits.swift"; sourceTree = "<group>"; };
EED8DA9622BECD7500E54492 /* FontCollection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FontCollection.swift; sourceTree = "<group>"; };
EEE2C7F022C2AFEF001B7054 /* ListItemParagraphStyler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListItemParagraphStyler.swift; sourceTree = "<group>"; };
EEEBEE46225D298D00AE438D /* Document.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Document.swift; sourceTree = "<group>"; };
EEEBEE48225D29C200AE438D /* BlockQuote.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlockQuote.swift; sourceTree = "<group>"; };
EEEBEE4A225D29D800AE438D /* List.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = List.swift; sourceTree = "<group>"; };
EEEBEE4C225D2A0200AE438D /* Item.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Item.swift; sourceTree = "<group>"; };
EEEBEE4E225D2A1400AE438D /* CodeBlock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CodeBlock.swift; sourceTree = "<group>"; };
EEEBEE50225D2A2900AE438D /* HtmlBlock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HtmlBlock.swift; sourceTree = "<group>"; };
EEEBEE52225D2A3C00AE438D /* CustomBlock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomBlock.swift; sourceTree = "<group>"; };
EEEBEE54225D2A4E00AE438D /* Paragraph.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Paragraph.swift; sourceTree = "<group>"; };
EEEBEE56225D2A6200AE438D /* Heading.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Heading.swift; sourceTree = "<group>"; };
EEEBEE58225D2A7000AE438D /* ThematicBreak.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThematicBreak.swift; sourceTree = "<group>"; };
EEEBEE5A225D2A7E00AE438D /* Text.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Text.swift; sourceTree = "<group>"; };
EEEBEE5C225D2A8F00AE438D /* SoftBreak.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SoftBreak.swift; sourceTree = "<group>"; };
EEEBEE5E225D2AA700AE438D /* LineBreak.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LineBreak.swift; sourceTree = "<group>"; };
EEEBEE60225D2AC000AE438D /* Code.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Code.swift; sourceTree = "<group>"; };
EEEBEE62225D2AD400AE438D /* HtmlInline.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HtmlInline.swift; sourceTree = "<group>"; };
EEEBEE64225D2AE800AE438D /* CustomInline.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomInline.swift; sourceTree = "<group>"; };
EEEBEE66225D2AF900AE438D /* Emphasis.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Emphasis.swift; sourceTree = "<group>"; };
EEEBEE68225D2B1200AE438D /* Strong.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Strong.swift; sourceTree = "<group>"; };
EEEBEE6A225D2B2200AE438D /* Link.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Link.swift; sourceTree = "<group>"; };
EEEBEE6C225D2B3200AE438D /* Image.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Image.swift; sourceTree = "<group>"; };
EEEBEE6F225D2B9D00AE438D /* DebugVisitor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DebugVisitor.swift; sourceTree = "<group>"; };
EEEBEE71225D2F9200AE438D /* AttributedStringVisitor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttributedStringVisitor.swift; sourceTree = "<group>"; };
EEF1376E2259E53400D7DDE0 /* Node.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Node.swift; sourceTree = "<group>"; };
EEF137702259E7E700D7DDE0 /* Visitor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Visitor.swift; sourceTree = "<group>"; };
EEF8580E22FA101C0025370B /* DownDebugLayoutManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DownDebugLayoutManager.swift; sourceTree = "<group>"; };
EEF8581022FA11690025370B /* DownDebugTextView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DownDebugTextView.swift; sourceTree = "<group>"; };
EEFFFDDA22F4C36800036FD5 /* ThematicBreakAttribute.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThematicBreakAttribute.swift; sourceTree = "<group>"; };
EEFFFDDC22F4C8AB00036FD5 /* DownLayoutManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DownLayoutManager.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -201,12 +341,21 @@
buildActionMask = 2147483647;
files = (
8AFAEB001E6E32E900E09B68 /* Down.framework in Frameworks */,
EE3E7E812604019300170A52 /* SnapshotTesting in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
8C73B9B422A687C400C8E60F /* include */ = {
isa = PBXGroup;
children = (
8C73B9B522A687C400C8E60F /* module.modulemap */,
);
path = include;
sourceTree = "<group>";
};
907C64611EC120530095FEE1 /* Fixtures */ = {
isa = PBXGroup;
children = (
@@ -225,25 +374,25 @@
path = Configurations;
sourceTree = "<group>";
};
D41689B41CFFE6BB00E5802B /* Resources */ = {
D41689B41CFFE6BB00E5802B /* Supporting Files */ = {
isa = PBXGroup;
children = (
90A40A971EC0309A004F2E91 /* Configurations */,
90A40A951EC02FF6004F2E91 /* Down-Info.plist */,
90A40A961EC02FF6004F2E91 /* DownTests-Info.plist */,
D41689B51CFFE6BB00E5802B /* DownView.bundle */,
14C5E33621877FCD00D5380C /* DownView (macOS).bundle */,
);
path = Resources;
path = "Supporting Files";
sourceTree = "<group>";
};
D4201E761CFA5151008EEC6E = {
isa = PBXGroup;
children = (
D4201E9B1CFA59A5008EEC6E /* Source */,
D41689B41CFFE6BB00E5802B /* Resources */,
EE39B28026063E0D002C4F8D /* .swiftlint.yml */,
D4201E9B1CFA59A5008EEC6E /* Sources */,
D41689B41CFFE6BB00E5802B /* Supporting Files */,
D4201EC41CFA59A5008EEC6E /* Tests */,
D4201E811CFA5151008EEC6E /* Products */,
EE54F96D22EB9CE400628683 /* Frameworks */,
);
indentWidth = 4;
sourceTree = "<group>";
@@ -258,28 +407,19 @@
name = Products;
sourceTree = "<group>";
};
D4201E9B1CFA59A5008EEC6E /* Source */ = {
D4201E9B1CFA59A5008EEC6E /* Sources */ = {
isa = PBXGroup;
children = (
D4CF88961CFF94B300F07FD1 /* Down.h */,
D4201EF01CFA59F2008EEC6E /* Down.swift */,
D44875E71CFA6CF30037A624 /* Enums & Options */,
D43AE5C81CFFAE39006E1522 /* Extensions */,
D44875E21CFA6B120037A624 /* Renderers */,
D43AE5CB1CFFD068006E1522 /* Views */,
EED7D92025C6DA4300E52D18 /* Down */,
D4201EF61CFA5D63008EEC6E /* cmark */,
);
path = Source;
path = Sources;
sourceTree = "<group>";
};
D4201EC41CFA59A5008EEC6E /* Tests */ = {
isa = PBXGroup;
children = (
D4201EC51CFA59A5008EEC6E /* BindingTests.swift */,
D41689B21CFFE28200E5802B /* DownViewTests.swift */,
907C64611EC120530095FEE1 /* Fixtures */,
D4F948DB1D00A4A800C9C0F6 /* NSAttributedStringTests.swift */,
D438696B1D00D27700E95A1F /* StringTests.swift */,
EED7D92725C6DB9100E52D18 /* DownTests */,
);
path = Tests;
sourceTree = "<group>";
@@ -287,6 +427,7 @@
D4201EF61CFA5D63008EEC6E /* cmark */ = {
isa = PBXGroup;
children = (
8C73B9B422A687C400C8E60F /* include */,
D4201EF71CFA5D63008EEC6E /* blocks.c */,
D4201EF81CFA5D63008EEC6E /* buffer.c */,
D4201EF91CFA5D63008EEC6E /* buffer.h */,
@@ -299,20 +440,17 @@
D4201F011CFA5D63008EEC6E /* cmark_version.h */,
D4201F021CFA5D63008EEC6E /* commonmark.c */,
D4201F031CFA5D63008EEC6E /* config.h */,
D4201F041CFA5D63008EEC6E /* debug.h */,
D4201F061CFA5D63008EEC6E /* houdini.h */,
D4201F071CFA5D63008EEC6E /* houdini_href_e.c */,
D4201F081CFA5D63008EEC6E /* houdini_html_e.c */,
D4201F091CFA5D63008EEC6E /* houdini_html_u.c */,
D4201F0A1CFA5D63008EEC6E /* html.c */,
D4201F0B1CFA5D63008EEC6E /* html_unescape.h */,
D4201F0C1CFA5D63008EEC6E /* inlines.c */,
D4201F0D1CFA5D63008EEC6E /* inlines.h */,
D4201F0E1CFA5D63008EEC6E /* iterator.c */,
D4201F0F1CFA5D63008EEC6E /* iterator.h */,
D4201F101CFA5D63008EEC6E /* latex.c */,
D4201F111CFA5D63008EEC6E /* man.c */,
D42869501CFF501200FACB4C /* module.modulemap */,
D4201F131CFA5D63008EEC6E /* node.c */,
D4201F141CFA5D63008EEC6E /* node.h */,
D4201F151CFA5D63008EEC6E /* parser.h */,
@@ -342,6 +480,7 @@
isa = PBXGroup;
children = (
D43AE5D91CFFD0D0006E1522 /* DownView.swift */,
EEBE62EF25E28F3D005CCAD6 /* BundleHelper.swift */,
);
path = Views;
sourceTree = "<group>";
@@ -355,8 +494,8 @@
D486E9991CFDE28B0059FD7C /* DownGroffRenderable.swift */,
D44875E51CFA6B660037A624 /* DownHTMLRenderable.swift */,
D486E9971CFDE2730059FD7C /* DownLaTeXRenderable.swift */,
D486E9931CFDD33C0059FD7C /* DownXMLRenderable.swift */,
D44875E31CFA6B200037A624 /* DownRenderable.swift */,
D486E9931CFDD33C0059FD7C /* DownXMLRenderable.swift */,
);
path = Renderers;
sourceTree = "<group>";
@@ -370,6 +509,235 @@
path = "Enums & Options";
sourceTree = "<group>";
};
EE408A3E23033DFE00E5278A /* Helpers */ = {
isa = PBXGroup;
children = (
EE408A3A2303399B00E5278A /* CGRectHelpersTests.swift */,
EE408A38230338B600E5278A /* CGPointTranslateTests.swift */,
EE97254222C14B79004D3B3A /* NSAttributedString+HelpersTests.swift */,
EE97253D22C130D8004D3B3A /* NSMutableAttributedString+AttributesTests.swift */,
);
path = Helpers;
sourceTree = "<group>";
};
EE48C7DE22EC99F3004815ED /* Attribute Collections */ = {
isa = PBXGroup;
children = (
EED8DA9622BECD7500E54492 /* FontCollection.swift */,
EE48C7DA22EC946F004815ED /* ColorCollection.swift */,
EE48C7D822EC9250004815ED /* ParagraphStyleCollection.swift */,
);
path = "Attribute Collections";
sourceTree = "<group>";
};
EE48C7DF22EC9A4D004815ED /* Extensions */ = {
isa = PBXGroup;
children = (
EED8DA9322BECC2100E54492 /* UIFont+Traits.swift */,
EED8DA8F22BECBAE00E54492 /* NSAttributedString+Helpers.swift */,
EED8DA9122BECBF200E54492 /* NSMutableAttributedString+Attributes.swift */,
EE4484902301F2920065C836 /* CGPoint+Translate.swift */,
EE4484922301F2DB0065C836 /* CGRect+Helpers.swift */,
);
path = Extensions;
sourceTree = "<group>";
};
EE54F96D22EB9CE400628683 /* Frameworks */ = {
isa = PBXGroup;
children = (
EE54F96E22EB9CE500628683 /* SnapshotTesting.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
EE59C30022ECF08E006EE8A8 /* Styler */ = {
isa = PBXGroup;
children = (
EE408A3E23033DFE00E5278A /* Helpers */,
EE5D2DF822FC9E89009EC13E /* DownDebugLayoutManagerTests.swift */,
EE5D2DF522FC99A6009EC13E /* LinkStyleTests.swift */,
EE64722A22F8BB0B00C5F0BA /* CodeBlockStyleTests.swift */,
EEA2BDC722F705B900D0C72C /* BlockQuoteStyleTests.swift */,
EEA5C02A22F58B8000B91D60 /* ThematicBreakSyleTests.swift */,
EE99E3DD22F0C83F00BCE15B /* HeadingStyleTests.swift */,
EE9E886222EF76040005948C /* InlineStyleTests.swift */,
EE335C4922EDC85900648842 /* ListItemStyleTests.swift */,
EE59C30122ECF0BD006EE8A8 /* StylerTestSuite.swift */,
);
path = Styler;
sourceTree = "<group>";
};
EE5D2DF722FC9D98009EC13E /* Options */ = {
isa = PBXGroup;
children = (
EEA2BDC922F7152B00D0C72C /* ThematicBreakOptions.swift */,
EEA2BDC322F704F200D0C72C /* QuoteStripeOptions.swift */,
EEA2BDC522F7057600D0C72C /* ListItemOptions.swift */,
EE44848A2301E51C0065C836 /* CodeBlockOptions.swift */,
);
path = Options;
sourceTree = "<group>";
};
EE5D2DFA22FCA92F009EC13E /* Stylers */ = {
isa = PBXGroup;
children = (
EE5F2BA32262564A00B7C0F3 /* Styler.swift */,
EED8DA8D22BE404F00E54492 /* DownStyler.swift */,
EE4F77C222FF3F170026A983 /* DownStylerConfiguration.swift */,
);
path = Stylers;
sourceTree = "<group>";
};
EE5D2DFB22FCA946009EC13E /* Layout Managers */ = {
isa = PBXGroup;
children = (
EEFFFDDC22F4C8AB00036FD5 /* DownLayoutManager.swift */,
EEF8580E22FA101C0025370B /* DownDebugLayoutManager.swift */,
);
path = "Layout Managers";
sourceTree = "<group>";
};
EE5D2DFC22FCA953009EC13E /* Text Views */ = {
isa = PBXGroup;
children = (
EEA5C02822F58A0900B91D60 /* DownTextView.swift */,
EEF8581022FA11690025370B /* DownDebugTextView.swift */,
);
path = "Text Views";
sourceTree = "<group>";
};
EE5F2BA22262562F00B7C0F3 /* Styling */ = {
isa = PBXGroup;
children = (
EE5D2DFA22FCA92F009EC13E /* Stylers */,
EEFFFDD922F4C35000036FD5 /* Custom Attributes */,
EE5D2DFB22FCA946009EC13E /* Layout Managers */,
EE5D2DFC22FCA953009EC13E /* Text Views */,
EE48C7DE22EC99F3004815ED /* Attribute Collections */,
EE5D2DF722FC9D98009EC13E /* Options */,
EED8DA9522BECCF000E54492 /* Helpers */,
);
path = Styling;
sourceTree = "<group>";
};
EEC752BE22C4AE1300EC729C /* AST */ = {
isa = PBXGroup;
children = (
EE8F38CB22BFB2420056270E /* NodeTests.swift */,
EE64FEEF225BEB3900A35B34 /* VisitorTests.swift */,
EE408A3C23033B6B00E5278A /* ListItemPrefixGeneratorTests.swift */,
);
path = AST;
sourceTree = "<group>";
};
EED7D92025C6DA4300E52D18 /* Down */ = {
isa = PBXGroup;
children = (
EED7D94425C6DF2D00E52D18 /* Resources */,
D4CF88961CFF94B300F07FD1 /* Down.h */,
D4201EF01CFA59F2008EEC6E /* Down.swift */,
EEF1376D2259E4BA00D7DDE0 /* AST */,
D44875E71CFA6CF30037A624 /* Enums & Options */,
D43AE5C81CFFAE39006E1522 /* Extensions */,
D44875E21CFA6B120037A624 /* Renderers */,
D43AE5CB1CFFD068006E1522 /* Views */,
);
path = Down;
sourceTree = "<group>";
};
EED7D92725C6DB9100E52D18 /* DownTests */ = {
isa = PBXGroup;
children = (
EE59C30022ECF08E006EE8A8 /* Styler */,
907C64611EC120530095FEE1 /* Fixtures */,
D4201EC51CFA59A5008EEC6E /* BindingTests.swift */,
D41689B21CFFE28200E5802B /* DownViewTests.swift */,
D4F948DB1D00A4A800C9C0F6 /* NSAttributedStringTests.swift */,
D438696B1D00D27700E95A1F /* StringTests.swift */,
EEC752BE22C4AE1300EC729C /* AST */,
);
path = DownTests;
sourceTree = "<group>";
};
EED7D94425C6DF2D00E52D18 /* Resources */ = {
isa = PBXGroup;
children = (
D41689B51CFFE6BB00E5802B /* DownView.bundle */,
14C5E33621877FCD00D5380C /* DownView (macOS).bundle */,
);
path = Resources;
sourceTree = "<group>";
};
EED8DA9522BECCF000E54492 /* Helpers */ = {
isa = PBXGroup;
children = (
EEE2C7F022C2AFEF001B7054 /* ListItemParagraphStyler.swift */,
EE48C7DF22EC9A4D004815ED /* Extensions */,
);
path = Helpers;
sourceTree = "<group>";
};
EEEBEE45225D297700AE438D /* Nodes */ = {
isa = PBXGroup;
children = (
EE469B10226CF3B500C0655D /* BaseNode.swift */,
EEEBEE48225D29C200AE438D /* BlockQuote.swift */,
EEEBEE60225D2AC000AE438D /* Code.swift */,
EEEBEE4E225D2A1400AE438D /* CodeBlock.swift */,
EEEBEE52225D2A3C00AE438D /* CustomBlock.swift */,
EEEBEE64225D2AE800AE438D /* CustomInline.swift */,
EEEBEE46225D298D00AE438D /* Document.swift */,
EEEBEE66225D2AF900AE438D /* Emphasis.swift */,
EEEBEE56225D2A6200AE438D /* Heading.swift */,
EEEBEE50225D2A2900AE438D /* HtmlBlock.swift */,
EEEBEE62225D2AD400AE438D /* HtmlInline.swift */,
EEEBEE6C225D2B3200AE438D /* Image.swift */,
EEEBEE4C225D2A0200AE438D /* Item.swift */,
EEEBEE5E225D2AA700AE438D /* LineBreak.swift */,
EEEBEE6A225D2B2200AE438D /* Link.swift */,
EEEBEE4A225D29D800AE438D /* List.swift */,
EEF1376E2259E53400D7DDE0 /* Node.swift */,
EEEBEE54225D2A4E00AE438D /* Paragraph.swift */,
EEEBEE5C225D2A8F00AE438D /* SoftBreak.swift */,
EEEBEE68225D2B1200AE438D /* Strong.swift */,
EEEBEE5A225D2A7E00AE438D /* Text.swift */,
EEEBEE58225D2A7000AE438D /* ThematicBreak.swift */,
26CABB92252B4D490032183C /* ChildSequence.swift */,
);
path = Nodes;
sourceTree = "<group>";
};
EEEBEE6E225D2B8200AE438D /* Visitors */ = {
isa = PBXGroup;
children = (
EEEBEE71225D2F9200AE438D /* AttributedStringVisitor.swift */,
EE8F38CD22BFEDE50056270E /* ListItemPrefixGenerator.swift */,
EEEBEE6F225D2B9D00AE438D /* DebugVisitor.swift */,
EEF137702259E7E700D7DDE0 /* Visitor.swift */,
);
path = Visitors;
sourceTree = "<group>";
};
EEF1376D2259E4BA00D7DDE0 /* AST */ = {
isa = PBXGroup;
children = (
EEEBEE45225D297700AE438D /* Nodes */,
EEEBEE6E225D2B8200AE438D /* Visitors */,
EE5F2BA22262562F00B7C0F3 /* Styling */,
);
path = AST;
sourceTree = "<group>";
};
EEFFFDD922F4C35000036FD5 /* Custom Attributes */ = {
isa = PBXGroup;
children = (
EEFFFDDA22F4C36800036FD5 /* ThematicBreakAttribute.swift */,
EEA5C02C22F5C96B00B91D60 /* QuoteStripeAttribute.swift */,
EE0E54F72300800E0070C83F /* BlockBackgroundColorAttribute.swift */,
);
path = "Custom Attributes";
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
@@ -377,7 +745,6 @@
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
8A569F551E6B3ED9008BE2AC /* debug.h in Headers */,
8A569F4C1E6B3ED9008BE2AC /* chunk.h in Headers */,
8A569F631E6B3ED9008BE2AC /* node.h in Headers */,
8A569F521E6B3ED9008BE2AC /* cmark_version.h in Headers */,
@@ -394,7 +761,6 @@
8A569F511E6B3ED9008BE2AC /* cmark_export.h in Headers */,
8A569F4E1E6B3ED9008BE2AC /* cmark.h in Headers */,
8A569F501E6B3ED9008BE2AC /* cmark_ctype.h in Headers */,
8A569F5B1E6B3ED9008BE2AC /* html_unescape.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -409,6 +775,7 @@
8A569F3D1E6B3E50008BE2AC /* Headers */,
14C5E33421877CDC00D5380C /* Resources */,
14CEAC38218774BC00039EDF /* Replace Bundle for macOS Platform */,
EED185ED26054F800051E616 /* Swiftlint */,
);
buildRules = (
8AE66BE41F848C3900ED4C98 /* PBXBuildRule */,
@@ -437,6 +804,9 @@
8AFAEB021E6E32E900E09B68 /* PBXTargetDependency */,
);
name = DownTests;
packageProductDependencies = (
EE3E7E802604019300170A52 /* SnapshotTesting */,
);
productName = "DownTests-macOS";
productReference = 8AFAEAFB1E6E32E900E09B68 /* DownTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
@@ -447,30 +817,34 @@
D4201E771CFA5151008EEC6E /* Project object */ = {
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 0820;
LastUpgradeCheck = 1010;
ORGANIZATIONNAME = "Glazed Donut, LLC.";
LastSwiftUpdateCheck = 1100;
LastUpgradeCheck = 1020;
ORGANIZATIONNAME = Down;
TargetAttributes = {
8A569F3F1E6B3E50008BE2AC = {
CreatedOnToolsVersion = 8.2.1;
LastSwiftMigration = 0900;
LastSwiftMigration = 1020;
ProvisioningStyle = Automatic;
};
8AFAEAFA1E6E32E900E09B68 = {
CreatedOnToolsVersion = 8.2.1;
LastSwiftMigration = 0900;
LastSwiftMigration = 1020;
ProvisioningStyle = Automatic;
};
};
};
buildConfigurationList = D4201E7A1CFA5151008EEC6E /* Build configuration list for PBXProject "Down" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = D4201E761CFA5151008EEC6E;
packageReferences = (
EED7FED525E303000033E33A /* XCRemoteSwiftPackageReference "swift-snapshot-testing" */,
);
productRefGroup = D4201E811CFA5151008EEC6E /* Products */;
projectDirPath = "";
projectRoot = "";
@@ -486,6 +860,7 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
EED7FED825E3133C0033E33A /* DownView (macOS).bundle in Resources */,
14C5E33521877CE900D5380C /* DownView.bundle in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -517,9 +892,27 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "# Type a script or drag a script file from your workspace to insert its path.\nRESOURCE_PATH=$SRCROOT/Resources\n\nFILENAME_IN_BUNDLE=DownView.bundle\n\nBUILD_APP_DIR=${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.framework/Resources\n\necho \"$RESOURCE_PATH\"\necho \"$BUILD_APP_DIR\"\n\nif [ \"$PLATFORM_NAME\" == \"macosx\" ]; then\n echo $BUILD_APP_DIR\n rm -r \"$BUILD_APP_DIR/$FILENAME_IN_BUNDLE/\"\n cp -R \"$RESOURCE_PATH/DownView (macOS).bundle\" \"$BUILD_APP_DIR/$FILENAME_IN_BUNDLE/\"\nfi\n";
shellScript = "# Type a script or drag a script file from your workspace to insert its path.\nRESOURCE_PATH=$SRCROOT/Sources/Down/Resources\n\nFILENAME_IN_BUNDLE=DownView.bundle\n\nBUILD_APP_DIR=${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.framework/Resources\n\necho \"$RESOURCE_PATH\"\necho \"$BUILD_APP_DIR\"\n\nif [ \"$PLATFORM_NAME\" == \"macosx\" ]; then\n echo $BUILD_APP_DIR\n rm -r \"$BUILD_APP_DIR/$FILENAME_IN_BUNDLE/\"\n cp -R \"$RESOURCE_PATH/DownView (macOS).bundle\" \"$BUILD_APP_DIR/$FILENAME_IN_BUNDLE/\"\nfi\n";
showEnvVarsInLog = 0;
};
EED185ED26054F800051E616 /* Swiftlint */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
);
name = Swiftlint;
outputFileListPaths = (
);
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "if which swiftlint >/dev/null; then\n swiftlint\nelse\n echo \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi\n";
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
@@ -531,35 +924,86 @@
8A569F761E6B3EE3008BE2AC /* NSAttributedString+HTML.swift in Sources */,
8A569F5A1E6B3ED9008BE2AC /* html.c in Sources */,
8A569F5E1E6B3ED9008BE2AC /* iterator.c in Sources */,
EEEBEE70225D2B9D00AE438D /* DebugVisitor.swift in Sources */,
EEEBEE59225D2A7000AE438D /* ThematicBreak.swift in Sources */,
8A569F481E6B3ED2008BE2AC /* DownView.swift in Sources */,
EE4F77C322FF3F170026A983 /* DownStylerConfiguration.swift in Sources */,
8A569F591E6B3ED9008BE2AC /* houdini_html_u.c in Sources */,
EEEBEE63225D2AD400AE438D /* HtmlInline.swift in Sources */,
8A569F621E6B3ED9008BE2AC /* node.c in Sources */,
EE4484932301F2DB0065C836 /* CGRect+Helpers.swift in Sources */,
26CABB93252B4D490032183C /* ChildSequence.swift in Sources */,
EEEBEE6D225D2B3200AE438D /* Image.swift in Sources */,
EED8DA9722BECD7500E54492 /* FontCollection.swift in Sources */,
EEEBEE4D225D2A0200AE438D /* Item.swift in Sources */,
EEF8580F22FA101C0025370B /* DownDebugLayoutManager.swift in Sources */,
8A569F6F1E6B3EDE008BE2AC /* DownAttributedStringRenderable.swift in Sources */,
EEEBEE55225D2A4E00AE438D /* Paragraph.swift in Sources */,
EEBE62F025E28F3D005CCAD6 /* BundleHelper.swift in Sources */,
8A569F721E6B3EDE008BE2AC /* DownHTMLRenderable.swift in Sources */,
EED8DA9422BECC2100E54492 /* UIFont+Traits.swift in Sources */,
EE44848B2301E51C0065C836 /* CodeBlockOptions.swift in Sources */,
EE4484912301F2920065C836 /* CGPoint+Translate.swift in Sources */,
EEFFFDDB22F4C36800036FD5 /* ThematicBreakAttribute.swift in Sources */,
EEE2C7F122C2AFEF001B7054 /* ListItemParagraphStyler.swift in Sources */,
8A569F581E6B3ED9008BE2AC /* houdini_html_e.c in Sources */,
EEEBEE5D225D2A8F00AE438D /* SoftBreak.swift in Sources */,
EE48C7D922EC9250004815ED /* ParagraphStyleCollection.swift in Sources */,
EEEBEE6B225D2B2200AE438D /* Link.swift in Sources */,
8A569F531E6B3ED9008BE2AC /* commonmark.c in Sources */,
EEA2BDC422F704F200D0C72C /* QuoteStripeOptions.swift in Sources */,
8A569F4A1E6B3ED9008BE2AC /* buffer.c in Sources */,
EED8DA9222BECBF200E54492 /* NSMutableAttributedString+Attributes.swift in Sources */,
EED8DA9022BECBAE00E54492 /* NSAttributedString+Helpers.swift in Sources */,
EEFFFDDD22F4C8AB00036FD5 /* DownLayoutManager.swift in Sources */,
8A569F771E6B3EE3008BE2AC /* String+ToHTML.swift in Sources */,
8A569F751E6B3EDE008BE2AC /* DownRenderable.swift in Sources */,
EEA2BDC622F7057600D0C72C /* ListItemOptions.swift in Sources */,
EE8F38CE22BFEDE50056270E /* ListItemPrefixGenerator.swift in Sources */,
8A569F741E6B3EDE008BE2AC /* DownXMLRenderable.swift in Sources */,
8A569F6B1E6B3ED9008BE2AC /* utf8.c in Sources */,
8A569F791E6B3EE7008BE2AC /* DownOptions.swift in Sources */,
EEEBEE72225D2F9200AE438D /* AttributedStringVisitor.swift in Sources */,
EEEBEE4B225D29D800AE438D /* List.swift in Sources */,
EEEBEE57225D2A6200AE438D /* Heading.swift in Sources */,
8A569F601E6B3ED9008BE2AC /* latex.c in Sources */,
8A569F711E6B3EDE008BE2AC /* DownGroffRenderable.swift in Sources */,
EEEBEE51225D2A2900AE438D /* HtmlBlock.swift in Sources */,
8A569F691E6B3ED9008BE2AC /* scanners.c in Sources */,
8A569F701E6B3EDE008BE2AC /* DownCommonMarkRenderable.swift in Sources */,
8A569F7A1E6B3EEA008BE2AC /* Down.swift in Sources */,
EE5F2BA42262564A00B7C0F3 /* Styler.swift in Sources */,
EEA5C02922F58A0900B91D60 /* DownTextView.swift in Sources */,
8A569F731E6B3EDE008BE2AC /* DownLaTeXRenderable.swift in Sources */,
8A569F781E6B3EE7008BE2AC /* DownErrors.swift in Sources */,
8A569F5C1E6B3ED9008BE2AC /* inlines.c in Sources */,
EE48C7DB22EC946F004815ED /* ColorCollection.swift in Sources */,
EEA5C02D22F5C96B00B91D60 /* QuoteStripeAttribute.swift in Sources */,
8A569F571E6B3ED9008BE2AC /* houdini_href_e.c in Sources */,
8A569F4D1E6B3ED9008BE2AC /* cmark.c in Sources */,
EEEBEE65225D2AE800AE438D /* CustomInline.swift in Sources */,
EE0E54F82300800E0070C83F /* BlockBackgroundColorAttribute.swift in Sources */,
EEF1376F2259E53400D7DDE0 /* Node.swift in Sources */,
8A569F6D1E6B3ED9008BE2AC /* xml.c in Sources */,
8A569F6E1E6B3EDE008BE2AC /* DownASTRenderable.swift in Sources */,
EEF8581122FA11690025370B /* DownDebugTextView.swift in Sources */,
EEEBEE5B225D2A7E00AE438D /* Text.swift in Sources */,
EEEBEE4F225D2A1400AE438D /* CodeBlock.swift in Sources */,
EED8DA8E22BE404F00E54492 /* DownStyler.swift in Sources */,
EEEBEE5F225D2AA700AE438D /* LineBreak.swift in Sources */,
EEEBEE61225D2AC000AE438D /* Code.swift in Sources */,
8A569F491E6B3ED9008BE2AC /* blocks.c in Sources */,
EEF137712259E7E700D7DDE0 /* Visitor.swift in Sources */,
EEEBEE53225D2A3C00AE438D /* CustomBlock.swift in Sources */,
EEEBEE69225D2B1200AE438D /* Strong.swift in Sources */,
EEEBEE47225D298D00AE438D /* Document.swift in Sources */,
8A569F4F1E6B3ED9008BE2AC /* cmark_ctype.c in Sources */,
EE469B11226CF3B500C0655D /* BaseNode.swift in Sources */,
8A569F671E6B3ED9008BE2AC /* render.c in Sources */,
EEEBEE49225D29C200AE438D /* BlockQuote.swift in Sources */,
8A569F651E6B3ED9008BE2AC /* references.c in Sources */,
EEEBEE67225D2AF900AE438D /* Emphasis.swift in Sources */,
EEA2BDCA22F7152B00D0C72C /* ThematicBreakOptions.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -567,7 +1011,23 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
EE3E7E54260400F900170A52 /* ThematicBreakSyleTests.swift in Sources */,
EE3E7E4D260400F500170A52 /* BlockQuoteStyleTests.swift in Sources */,
EE97253E22C130D8004D3B3A /* NSMutableAttributedString+AttributesTests.swift in Sources */,
EE3E7E622604010000170A52 /* InlineStyleTests.swift in Sources */,
EE3E7E702604010700170A52 /* StylerTestSuite.swift in Sources */,
EE3E7E692604010300170A52 /* ListItemStyleTests.swift in Sources */,
EE3E7E46260400F100170A52 /* CodeBlockStyleTests.swift in Sources */,
EE97254322C14B79004D3B3A /* NSAttributedString+HelpersTests.swift in Sources */,
8AFAEB091E6E331700E09B68 /* StringTests.swift in Sources */,
EE3E7E5B260400FC00170A52 /* HeadingStyleTests.swift in Sources */,
EE408A3D23033B6B00E5278A /* ListItemPrefixGeneratorTests.swift in Sources */,
EE8F38CC22BFB2420056270E /* NodeTests.swift in Sources */,
EE3E7E3F260400EE00170A52 /* LinkStyleTests.swift in Sources */,
EE3E7E38260400E800170A52 /* DownDebugLayoutManagerTests.swift in Sources */,
EE408A39230338B600E5278A /* CGPointTranslateTests.swift in Sources */,
EE408A3B2303399B00E5278A /* CGRectHelpersTests.swift in Sources */,
EE3E7E88260401F000170A52 /* VisitorTests.swift in Sources */,
8AFAEB071E6E331700E09B68 /* DownViewTests.swift in Sources */,
8AFAEB061E6E331700E09B68 /* BindingTests.swift in Sources */,
8AFAEB081E6E331700E09B68 /* NSAttributedStringTests.swift in Sources */,
@@ -589,6 +1049,7 @@
isa = XCBuildConfiguration;
baseConfigurationReference = 90A40A991EC0309A004F2E91 /* Universal-Framework-Target.xcconfig */;
buildSettings = {
APPLICATION_EXTENSION_API_ONLY = YES;
CODE_SIGN_IDENTITY = "";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
CODE_SIGN_STYLE = Automatic;
@@ -597,13 +1058,12 @@
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
INFOPLIST_FILE = "Resources/Down-Info.plist";
INFOPLIST_FILE = "Supporting Files/Down-Info.plist";
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
PROVISIONING_PROFILE_SPECIFIER = "";
SKIP_INSTALL = YES;
SWIFT_INCLUDE_PATHS = "${SRCROOT}/Source/cmark";
SWIFT_SWIFT3_OBJC_INFERENCE = Off;
SWIFT_VERSION = 4.0;
SWIFT_INCLUDE_PATHS = "${SRCROOT}/Sources/cmark";
"VALID_ARCHS[sdk=iphonesimulator*]" = "i386 x86_64 arm64";
};
name = Debug;
};
@@ -611,6 +1071,7 @@
isa = XCBuildConfiguration;
baseConfigurationReference = 90A40A991EC0309A004F2E91 /* Universal-Framework-Target.xcconfig */;
buildSettings = {
APPLICATION_EXTENSION_API_ONLY = YES;
CODE_SIGN_IDENTITY = "";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
CODE_SIGN_STYLE = Automatic;
@@ -619,13 +1080,12 @@
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
INFOPLIST_FILE = "Resources/Down-Info.plist";
INFOPLIST_FILE = "Supporting Files/Down-Info.plist";
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
PROVISIONING_PROFILE_SPECIFIER = "";
SKIP_INSTALL = YES;
SWIFT_INCLUDE_PATHS = "${SRCROOT}/Source/cmark";
SWIFT_SWIFT3_OBJC_INFERENCE = Off;
SWIFT_VERSION = 4.0;
SWIFT_INCLUDE_PATHS = "${SRCROOT}/Sources/cmark";
"VALID_ARCHS[sdk=iphonesimulator*]" = "i386 x86_64 arm64";
};
name = Release;
};
@@ -633,10 +1093,17 @@
isa = XCBuildConfiguration;
baseConfigurationReference = 90A40A9A1EC0309A004F2E91 /* Universal-Target-Base.xcconfig */;
buildSettings = {
INFOPLIST_FILE = "Resources/DownTests-Info.plist";
PRODUCT_BUNDLE_IDENTIFIER = com.glazeddonut.DownTests;
SWIFT_SWIFT3_OBJC_INFERENCE = Off;
SWIFT_VERSION = 4.0;
DEVELOPMENT_TEAM = "";
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Carthage/Build/iOS",
);
INFOPLIST_FILE = "Supporting Files/DownTests-Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
PRODUCT_BUNDLE_IDENTIFIER = com.downMarkdown.DownTests;
"TARGETED_DEVICE_FAMILY[sdk=appletvos*]" = 3;
"TARGETED_DEVICE_FAMILY[sdk=appletvsimulator*]" = 3;
TVOS_DEPLOYMENT_TARGET = 13.0;
};
name = Debug;
};
@@ -644,10 +1111,17 @@
isa = XCBuildConfiguration;
baseConfigurationReference = 90A40A9A1EC0309A004F2E91 /* Universal-Target-Base.xcconfig */;
buildSettings = {
INFOPLIST_FILE = "Resources/DownTests-Info.plist";
PRODUCT_BUNDLE_IDENTIFIER = com.glazeddonut.DownTests;
SWIFT_SWIFT3_OBJC_INFERENCE = Off;
SWIFT_VERSION = 4.0;
DEVELOPMENT_TEAM = "";
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Carthage/Build/iOS",
);
INFOPLIST_FILE = "Supporting Files/DownTests-Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
PRODUCT_BUNDLE_IDENTIFIER = com.downMarkdown.DownTests;
"TARGETED_DEVICE_FAMILY[sdk=appletvos*]" = 3;
"TARGETED_DEVICE_FAMILY[sdk=appletvsimulator*]" = 3;
TVOS_DEPLOYMENT_TARGET = 13.0;
};
name = Release;
};
@@ -657,6 +1131,7 @@
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES;
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
@@ -703,12 +1178,11 @@
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
ONLY_ACTIVE_ARCH = YES;
PRODUCT_BUNDLE_IDENTIFIER = "com.glazeddonut.$(TARGET_NAME:c99-identifier)";
PRODUCT_BUNDLE_IDENTIFIER = "com.downMarkdown.$(TARGET_NAME:c99-identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_SWIFT3_OBJC_INFERENCE = Off;
SWIFT_VERSION = 4.0;
TARGETED_DEVICE_FAMILY = "1,2";
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
@@ -721,6 +1195,7 @@
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES;
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
@@ -760,11 +1235,11 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
PRODUCT_BUNDLE_IDENTIFIER = "com.glazeddonut.$(TARGET_NAME:c99-identifier)";
PRODUCT_BUNDLE_IDENTIFIER = "com.downMarkdown.$(TARGET_NAME:c99-identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OPTIMIZATION_LEVEL = "-O";
SWIFT_SWIFT3_OBJC_INFERENCE = Off;
SWIFT_VERSION = 4.0;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
VERSIONING_SYSTEM = "apple-generic";
@@ -803,6 +1278,25 @@
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
/* Begin XCRemoteSwiftPackageReference section */
EED7FED525E303000033E33A /* XCRemoteSwiftPackageReference "swift-snapshot-testing" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/pointfreeco/swift-snapshot-testing.git";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 1.8.2;
};
};
/* End XCRemoteSwiftPackageReference section */
/* Begin XCSwiftPackageProductDependency section */
EE3E7E802604019300170A52 /* SnapshotTesting */ = {
isa = XCSwiftPackageProductDependency;
package = EED7FED525E303000033E33A /* XCRemoteSwiftPackageReference "swift-snapshot-testing" */;
productName = SnapshotTesting;
};
/* End XCSwiftPackageProductDependency section */
};
rootObject = D4201E771CFA5151008EEC6E /* Project object */;
}
+1 -1
View File
@@ -2,6 +2,6 @@
<Workspace
version = "1.0">
<FileRef
location = "self:Down.xcodeproj">
location = "self:">
</FileRef>
</Workspace>
@@ -0,0 +1,16 @@
{
"object": {
"pins": [
{
"package": "SnapshotTesting",
"repositoryURL": "https://github.com/pointfreeco/swift-snapshot-testing.git",
"state": {
"branch": null,
"revision": "c466812aa2e22898f27557e2e780d3aad7a27203",
"version": "1.8.2"
}
}
]
},
"version": 1
}
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1010"
LastUpgradeVersion = "1130"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@@ -26,8 +26,17 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
codeCoverageEnabled = "YES"
shouldUseLaunchSchemeArgsEnv = "YES">
shouldUseLaunchSchemeArgsEnv = "YES"
codeCoverageEnabled = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "8A569F3F1E6B3E50008BE2AC"
BuildableName = "Down.framework"
BlueprintName = "Down"
ReferencedContainer = "container:Down.xcodeproj">
</BuildableReference>
</MacroExpansion>
<Testables>
<TestableReference
skipped = "NO">
@@ -40,17 +49,6 @@
</BuildableReference>
</TestableReference>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "8A569F3F1E6B3E50008BE2AC"
BuildableName = "Down.framework"
BlueprintName = "Down"
ReferencedContainer = "container:Down.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
@@ -71,8 +69,6 @@
ReferencedContainer = "container:Down.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
+7
View File
@@ -0,0 +1,7 @@
import XCTest
var tests = [XCTestCaseEntry]()
// FIXME: Run on macOS `swift test --generate-linuxmain` and maintain Linux Tests.
XCTMain(tests)
+64
View File
@@ -0,0 +1,64 @@
// swift-tools-version:5.3
import PackageDescription
let package = Package(
name: "Down",
platforms: [
.macOS("10.11"),
.iOS("9.0"),
.tvOS("9.0")
],
products: [
.library(
name: "Down",
targets: ["Down"]
)
],
targets: [
.target(
name: "libcmark",
dependencies: [],
path: "Sources/cmark",
exclude: [
"include",
"case_fold_switch.inc",
"entities.inc",
"COPYING"
],
publicHeadersPath: "./"
),
.target(
name: "Down",
dependencies: ["libcmark"],
path: "Sources/Down",
exclude: ["Down.h"],
resources: [
.copy("Resources/DownView.bundle"),
.copy("Resources/DownView (macOS).bundle"),
]
),
.testTarget(
name: "DownTests",
dependencies: ["Down"],
path: "Tests/DownTests",
exclude: [
"AST/VisitorTests.swift",
"AST/__Snapshots__",
"DownViewTests.swift",
"Fixtures",
"Styler/__Snapshots__",
"Styler/BlockQuoteStyleTests.swift",
"Styler/CodeBlockStyleTests.swift",
"Styler/DownDebugLayoutManagerTests.swift",
"Styler/HeadingStyleTests.swift",
"Styler/LinkStyleTests.swift",
"Styler/InlineStyleTests.swift",
"Styler/ListItemStyleTests.swift",
"Styler/StylerTestSuite.swift",
"Styler/ThematicBreakSyleTests.swift"
]
)
],
swiftLanguageVersions: [.v5]
)
+61 -25
View File
@@ -1,41 +1,59 @@
## Down
[![Build Status](https://travis-ci.org/iwasrobbed/Down.svg?branch=master)](https://travis-ci.org/iwasrobbed/Down)
[![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/iwasrobbed/Down/blob/master/LICENSE)
[![CocoaPods](https://img.shields.io/cocoapods/v/Down.svg?maxAge=10800)]()
[![Swift 4](https://img.shields.io/badge/language-Swift-blue.svg)](https://swift.org)
[![Build Status](https://travis-ci.com/johnxnguyen/Down.svg?branch=master)](https://travis-ci.com/johnxnguyen/Down)
[![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/johnxnguyen/Down/blob/master/LICENSE)
[![CocoaPods](https://img.shields.io/cocoapods/v/Down)](https://cocoapods.org/pods/Down)
[![Swift 5](https://img.shields.io/badge/language-Swift-blue.svg)](https://swift.org)
[![macOS](https://img.shields.io/badge/OS-macOS-orange.svg)](https://developer.apple.com/macos/)
[![iOS](https://img.shields.io/badge/OS-iOS-orange.svg)](https://developer.apple.com/ios/)
[![tvOS](https://img.shields.io/badge/OS-tvOS-orange.svg)](https://developer.apple.com/tvos/)
[![Coverage Status](https://coveralls.io/repos/github/iwasrobbed/Down/badge.svg?branch=master)](https://coveralls.io/github/iwasrobbed/Down?branch=master)
[![Linux](https://img.shields.io/badge/OS-Linux-orange.svg)](https://www.linux.org/)
[![Code Coverage](https://codecov.io/gh/johnxnguyen/Down/branch/master/graph/badge.svg)](https://codecov.io/gh/johnxnguyen/Down)
Blazing fast Markdown (CommonMark) rendering in Swift, built upon [cmark v0.28.3](https://github.com/commonmark/cmark).
Blazing fast Markdown (CommonMark) rendering in Swift, built upon [cmark v0.29.0](https://github.com/commonmark/cmark).
Is your app using it? [Let us know!](mailto:rob@robphillips.me)
Is your app using it? [Let us know!](mailto:polyxo@protonmail.com)
If you're looking for `iwasrobbed/Down`, you found it! [Rob Phillips](https://github.com/iwasrobbed), the originator of this repository,
has transferred it to me as I will be the primary maintainer from now on. Thanks to Rob for bringing Down as far as it has come and for
entrusting me with its care.
All existing references to `iwasrobbed/Down` should redirect to this repository. However, It is recommended to update those urls to point
to this repository.
#### Maintainers
- [John Nguyen](https://github.com/johnxnguyen)
- [Rob Phillips](https://github.com/iwasrobbed)
- [Keaton Burleson](https://github.com/128keaton)
- [phoney](https://github.com/phoney)
- [Tony Arnold](https://github.com/tonyarnold)
- [Ken Harris](https://github.com/kengruven)
- [Chris Zielinski](https://github.com/chriszielinski)
- [Other contributors](https://github.com/iwasrobbed/Down/graphs/contributors) 🙌
- [Other contributors](https://github.com/johnxnguyen/Down/graphs/contributors) 🙌
### Installation
Note: Swift 4 support is now on the `master` branch and any tag >= 0.4.x (Swift 3 is 0.3.x)
Note: Swift support is summarized in the table below.
Quickly install using [CocoaPods](https://cocoapods.org):
|Swift Version|Tag|
| --- | --- |
| Swift 5.1 | >= 0.9.0 |
| Swift 5.0 | >= 0.8.1 |
| Swift 4 | >= 0.4.x |
| Swift 3 | 0.3.x |
now on the `master` branch and any tag >= 0.8.1 (Swift 4 is >= 0.4.x, Swift 3 is 0.3.x)
#### Quickly install using [CocoaPods](https://cocoapods.org):
```ruby
pod 'Down'
```
Or [Carthage](https://github.com/Carthage/Carthage):
#### Install using [Carthage](https://github.com/Carthage/Carthage):
```
github "iwasrobbed/Down"
github "johnxnguyen/Down"
```
Due to limitations in Carthage regarding platform specification, you need to define the platform with Carthage.
@@ -43,11 +61,16 @@ e.g.
```carthage update --platform iOS```
Or manually install:
#### Install using [Swift Package Manager](https://github.com/apple/swift-package-manager):
To add *Down* to your project, select `File → Swift Packages → Add Package Dependency` and enter the GitHub URL for *Down*.
See [Adding Package Dependencies to Your App](https://developer.apple.com/documentation/xcode/adding_package_dependencies_to_your_app) for detailed instructions.
#### Or manually install:
1. Clone this repository
2. Build the Down project
3. Add the resulting framework file to your project
2. Drag and drop the Down project into your workspace file, adding the framework in the embedded framework section
2. Build and run your app
4. ?
5. Profit
@@ -91,27 +114,27 @@ Meta example of rendering this README:
The `Down` struct has everything you need if you just want out-of-the-box setup for parsing and conversion.
```swift
let down = Down(markdownString: "## [Down](https://github.com/iwasrobbed/Down)")
let down = Down(markdownString: "## [Down](https://github.com/johnxnguyen/Down)")
// Convert to HTML
let html = try? down.toHTML()
// "<h2><a href=\"https://github.com/iwasrobbed/Down\">Down</a></h2>\n"
// "<h2><a href=\"https://github.com/johnxnguyen/Down\">Down</a></h2>\n"
// Convert to XML
let xml = try? down.toXML()
// "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE document SYSTEM \"CommonMark.dtd\">\n<document xmlns=\"http://commonmark.org/xml/1.0\">\n <heading level=\"2\">\n <link destination=\"https://github.com/iwasrobbed/Down\" title=\"\">\n <text>Down</text>\n </link>\n </heading>\n</document>\n"
// "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE document SYSTEM \"CommonMark.dtd\">\n<document xmlns=\"http://commonmark.org/xml/1.0\">\n <heading level=\"2\">\n <link destination=\"https://github.com/johnxnguyen/Down\" title=\"\">\n <text>Down</text>\n </link>\n </heading>\n</document>\n"
// Convert to groff man
let man = try? down.toGroff()
// ".SS\nDown (https://github.com/iwasrobbed/Down)\n"
// ".SS\nDown (https://github.com/johnxnguyen/Down)\n"
// Convert to LaTeX
let latex = try? down.toLaTeX()
// "\\subsection{\\href{https://github.com/iwasrobbed/Down}{Down}}\n"
// "\\subsection{\\href{https://github.com/johnxnguyen/Down}{Down}}\n"
// Convert to CommonMark Markdown
let commonMark = try? down.toCommonMark()
// "## [Down](https://github.com/iwasrobbed/Down)\n"
// "## [Down](https://github.com/johnxnguyen/Down)\n"
// Convert to an attributed string
let attributedString = try? down.toAttributedString()
@@ -165,11 +188,11 @@ public struct MarkdownToHTML: DownHTMLRenderable {
`DownView` can be configured with a custom bundle using your own HTML / CSS or to do things like supporting
Dynamic Type or custom fonts, etc. It's completely configurable.
This option can be found in [DownView's instantiation function](https://github.com/iwasrobbed/Down/blob/master/Source/Views/DownView.swift#L26).
This option can be found in [DownView's instantiation function](https://github.com/johnxnguyen/Down/blob/master/Source/Views/DownView.swift#L26).
##### Prevent zoom
The default implementation of the `DownView` allows for zooming in the rendered content. If you want to disable this, then youll need to instantiate the `DownView` with a custom bundle where the `viewport` in `index.html` has been assigned `user-scalable=no`. More info can be found [here](https://github.com/iwasrobbed/Down/pull/30).
The default implementation of the `DownView` allows for zooming in the rendered content. If you want to disable this, then youll need to instantiate the `DownView` with a custom bundle where the `viewport` in `index.html` has been assigned `user-scalable=no`. More info can be found [here](https://github.com/johnxnguyen/Down/pull/30).
### Options
@@ -198,10 +221,18 @@ public static let hardBreaks = DownOptions(rawValue: 1 << 2)
`file:`, and `data:`, except for `image/png`, `image/gif`,
`image/jpeg`, or `image/webp` mime types). Raw HTML is replaced
by a placeholder HTML comment. Unsafe links are replaced by
empty strings.
empty strings. Note that this option is provided for backwards
compatibility, but safe mode is now the default.
*/
public static let safe = DownOptions(rawValue: 1 << 3)
/**
Allow raw HTML and unsafe links. Note that safe mode is now
the default, and the unsafe option must be used if rendering
of raw HTML and unsafe links is desired.
*/
public static let unsafe = DownOptions(rawValue: 1 << 17)
// MARK: - Parsing Options
/**
@@ -219,6 +250,11 @@ public static let validateUTF8 = DownOptions(rawValue: 1 << 5)
Convert straight quotes to curly, --- to em dashes, -- to en dashes.
*/
public static let smart = DownOptions(rawValue: 1 << 6)
/**
Combine smart typography with HTML rendering.
*/
public static let smartUnsaFe = DownOptions(rawValue: (1 << 17) + (1 << 6))
```
### Supports
@@ -234,4 +270,4 @@ Please feel free to fork and create a pull request for bug fixes or improvements
### Credit
This library is a wrapper around [cmark](https://github.com/commonmark/cmark), which is built upon the [CommonMark](http://commonmark.org) Markdown specification.
[cmark](https://github.com/commonmark/cmark) is Copyright (c) 2014 - 2017, John MacFarlane. View [full license](https://github.com/commonmark/cmark/blob/master/COPYING).
[cmark](https://github.com/commonmark/cmark) is Copyright (c) 2014, John MacFarlane. View [full license](https://github.com/commonmark/cmark/blob/master/COPYING).
@@ -1,4 +0,0 @@
IPHONEOS_DEPLOYMENT_TARGET = 8.0
MACOSX_DEPLOYMENT_TARGET = 10.11
TVOS_DEPLOYMENT_TARGET = 9.0
WATCHOS_DEPLOYMENT_TARGET = 3.0
-30
View File
@@ -1,30 +0,0 @@
//
// Down.swift
// Down
//
// Created by Rob Phillips on 5/28/16.
// Copyright © 2016 Glazed Donut, LLC. All rights reserved.
//
import Foundation
public struct Down: DownASTRenderable, DownHTMLRenderable, DownXMLRenderable,
DownLaTeXRenderable, DownGroffRenderable, DownCommonMarkRenderable,
DownAttributedStringRenderable {
/**
A string containing CommonMark Markdown
*/
public var markdownString: String
/**
Initializes the container with a CommonMark Markdown string which can then be rendered depending on protocol conformance
- parameter markdownString: A string containing CommonMark Markdown
- returns: An instance of Self
*/
public init(markdownString: String) {
self.markdownString = markdownString
}
}
-35
View File
@@ -1,35 +0,0 @@
//
// DownErrors.swift
// Down
//
// Created by Rob Phillips on 5/28/16.
// Copyright © 2016 Glazed Donut, LLC. All rights reserved.
//
import Foundation
public enum DownErrors: Error {
/**
Thrown when there was an issue converting the Markdown into an abstract syntax tree
*/
case markdownToASTError
/**
Thrown when the abstract syntax tree could not be rendered into another format
*/
case astRenderingError
/**
Thrown when an HTML string cannot be converted into an `NSData` representation
*/
case htmlDataConversionError
#if os(macOS)
/**
Thrown when a custom template bundle has a non-standard bundle format.
Specifically, the file URL of the bundles subdirectory containing resource files could not be found (i.e. the bundle's `resourceURL` property is nil).
*/
case nonStandardBundleFormatError
#endif
}
-60
View File
@@ -1,60 +0,0 @@
//
// DownOptions.swift
// Down
//
// Created by Rob Phillips on 5/28/16.
// Copyright © 2016 Glazed Donut, LLC. All rights reserved.
//
import Foundation
import libcmark
public struct DownOptions: OptionSet {
public let rawValue: Int32
public init(rawValue: Int32) { self.rawValue = rawValue }
/**
Default options
*/
public static let `default` = DownOptions(rawValue: CMARK_OPT_DEFAULT)
// MARK: - Rendering Options
/**
Include a `data-sourcepos` attribute on all block elements
*/
public static let sourcePos = DownOptions(rawValue: CMARK_OPT_SOURCEPOS)
/**
Render `softbreak` elements as hard line breaks.
*/
public static let hardBreaks = DownOptions(rawValue: CMARK_OPT_HARDBREAKS)
/**
Suppress raw HTML and unsafe links (`javascript:`, `vbscript:`,
`file:`, and `data:`, except for `image/png`, `image/gif`,
`image/jpeg`, or `image/webp` mime types). Raw HTML is replaced
by a placeholder HTML comment. Unsafe links are replaced by
empty strings.
*/
public static let safe = DownOptions(rawValue: CMARK_OPT_SAFE)
// MARK: - Parsing Options
/**
Normalize tree by consolidating adjacent text nodes.
*/
public static let normalize = DownOptions(rawValue: CMARK_OPT_NORMALIZE)
/**
Validate UTF-8 in the input before parsing, replacing illegal
sequences with the replacement character U+FFFD.
*/
public static let validateUTF8 = DownOptions(rawValue: CMARK_OPT_VALIDATE_UTF8)
/**
Convert straight quotes to curly, --- to em dashes, -- to en dashes.
*/
public static let smart = DownOptions(rawValue: CMARK_OPT_SMART)
}
-67
View File
@@ -1,67 +0,0 @@
//
// DownASTRenderable.swift
// Down
//
// Created by Rob Phillips on 5/31/16.
// Copyright © 2016 Glazed Donut, LLC. All rights reserved.
//
import Foundation
import libcmark
public protocol DownASTRenderable: DownRenderable {
/**
Generates an abstract syntax tree from the `markdownString` property
- parameter options: `DownOptions` to modify parsing or rendering
- throws: `MarkdownToASTError` if conversion fails
- returns: An abstract syntax tree representation of the Markdown input
*/
func toAST(_ options: DownOptions) throws -> UnsafeMutablePointer<cmark_node>
}
public extension DownASTRenderable {
/**
Generates an abstract syntax tree from the `markdownString` property
- parameter options: `DownOptions` to modify parsing or rendering, defaulting to `.default`
- throws: `MarkdownToASTError` if conversion fails
- returns: An abstract syntax tree representation of the Markdown input
*/
public func toAST(_ options: DownOptions = .default) throws -> UnsafeMutablePointer<cmark_node> {
return try DownASTRenderer.stringToAST(markdownString, options: options)
}
}
public struct DownASTRenderer {
/**
Generates an abstract syntax tree from the given CommonMark Markdown string
**Important:** It is the caller's responsibility to call `cmark_node_free(ast)` on the returned value
- parameter options: `DownOptions` to modify parsing or rendering, defaulting to `.default`
- throws: `MarkdownToASTError` if conversion fails
- returns: An abstract syntax tree representation of the Markdown input
*/
public static func stringToAST(_ string: String, options: DownOptions = .default) throws -> UnsafeMutablePointer<cmark_node> {
var tree: UnsafeMutablePointer<cmark_node>?
string.withCString {
let stringLength = Int(strlen($0))
tree = cmark_parse_document($0, stringLength, options.rawValue)
}
guard let ast = tree else {
throw DownErrors.markdownToASTError
}
return ast
}
}
@@ -1,46 +0,0 @@
//
// DownAttributedStringRenderable.swift
// Down
//
// Created by Rob Phillips on 6/1/16.
// Copyright © 2016 Glazed Donut, LLC. All rights reserved.
//
import Foundation
import libcmark
public protocol DownAttributedStringRenderable: DownHTMLRenderable {
/**
Generates an `NSAttributedString` from the `markdownString` property
- parameter options: `DownOptions` to modify parsing or rendering
- parameter stylesheet: a `String` to use as a CSS stylesheet when rendering
- throws: `DownErrors` depending on the scenario
- returns: An `NSAttributedString`
*/
func toAttributedString(_ options: DownOptions, stylesheet: String?) throws -> NSAttributedString
}
public extension DownAttributedStringRenderable {
/**
Generates an `NSAttributedString` from the `markdownString` property
- parameter options: `DownOptions` to modify parsing or rendering, defaulting to `.default`
- parameter stylesheet: a `String` to use as the CSS stylesheet when rendering, defaulting to a style that uses the `NSAttributedString` default font
- throws: `DownErrors` depending on the scenario
- returns: An `NSAttributedString`
*/
public func toAttributedString(_ options: DownOptions = .default, stylesheet: String? = nil) throws -> NSAttributedString {
let html = try self.toHTML(options)
let defaultStylesheet = "* {font-family: Helvetica } code, pre { font-family: Menlo }"
return try NSAttributedString(htmlString: "<style>" + (stylesheet ?? defaultStylesheet) + "</style>" + html)
}
}
@@ -1,75 +0,0 @@
//
// DownCommonMarkRenderable.swift
// Down
//
// Created by Rob Phillips on 5/31/16.
// Copyright © 2016 Glazed Donut, LLC. All rights reserved.
//
import Foundation
import libcmark
public protocol DownCommonMarkRenderable: DownRenderable {
/**
Generates a CommonMark Markdown string from the `markdownString` property
- parameter options: `DownOptions` to modify parsing or rendering
- parameter width: The width to break on
- throws: `DownErrors` depending on the scenario
- returns: CommonMark Markdown string
*/
func toCommonMark(_ options: DownOptions, width: Int32) throws -> String
}
public extension DownCommonMarkRenderable {
/**
Generates a CommonMark Markdown string from the `markdownString` property
- parameter options: `DownOptions` to modify parsing or rendering, defaulting to `.default`
- parameter width: The width to break on, defaulting to 0
- throws: `DownErrors` depending on the scenario
- returns: CommonMark Markdown string
*/
public func toCommonMark(_ options: DownOptions = .default, width: Int32 = 0) throws -> String {
let ast = try DownASTRenderer.stringToAST(markdownString, options: options)
let commonMark = try DownCommonMarkRenderer.astToCommonMark(ast, options: options, width: width)
cmark_node_free(ast)
return commonMark
}
}
public struct DownCommonMarkRenderer {
/**
Generates a CommonMark Markdown string from the given abstract syntax tree
**Note:** caller is responsible for calling `cmark_node_free(ast)` after this returns
- parameter options: `DownOptions` to modify parsing or rendering, defaulting to `.default`
- parameter width: The width to break on, defaulting to 0
- throws: `ASTRenderingError` if the AST could not be converted
- returns: CommonMark Markdown string
*/
public static func astToCommonMark(_ ast: UnsafeMutablePointer<cmark_node>,
options: DownOptions = .default,
width: Int32 = 0) throws -> String {
guard let cCommonMarkString = cmark_render_commonmark(ast, options.rawValue, width) else {
throw DownErrors.astRenderingError
}
defer { free(cCommonMarkString) }
guard let commonMarkString = String(cString: cCommonMarkString, encoding: String.Encoding.utf8) else {
throw DownErrors.astRenderingError
}
return commonMarkString
}
}
@@ -1,75 +0,0 @@
//
// DownGroffRenderable.swift
// Down
//
// Created by Rob Phillips on 5/31/16.
// Copyright © 2016 Glazed Donut, LLC. All rights reserved.
//
import Foundation
import libcmark
public protocol DownGroffRenderable: DownRenderable {
/**
Generates a groff man string from the `markdownString` property
- parameter options: `DownOptions` to modify parsing or rendering
- parameter width: The width to break on
- throws: `DownErrors` depending on the scenario
- returns: groff man string
*/
func toGroff(_ options: DownOptions, width: Int32) throws -> String
}
public extension DownGroffRenderable {
/**
Generates a groff man string from the `markdownString` property
- parameter options: `DownOptions` to modify parsing or rendering, defaulting to `.default`
- parameter width: The width to break on, defaulting to 0
- throws: `DownErrors` depending on the scenario
- returns: groff man string
*/
public func toGroff(_ options: DownOptions = .default, width: Int32 = 0) throws -> String {
let ast = try DownASTRenderer.stringToAST(markdownString, options: options)
let groff = try DownGroffRenderer.astToGroff(ast, options: options, width: width)
cmark_node_free(ast)
return groff
}
}
public struct DownGroffRenderer {
/**
Generates a groff man string from the given abstract syntax tree
**Note:** caller is responsible for calling `cmark_node_free(ast)` after this returns
- parameter options: `DownOptions` to modify parsing or rendering, defaulting to `.default`
- parameter width: The width to break on, defaulting to 0
- throws: `ASTRenderingError` if the AST could not be converted
- returns: groff man string
*/
public static func astToGroff(_ ast: UnsafeMutablePointer<cmark_node>,
options: DownOptions = .default,
width: Int32 = 0) throws -> String {
guard let cGroffString = cmark_render_man(ast, options.rawValue, width) else {
throw DownErrors.astRenderingError
}
defer { free(cGroffString) }
guard let groffString = String(cString: cGroffString, encoding: String.Encoding.utf8) else {
throw DownErrors.astRenderingError
}
return groffString
}
}
-67
View File
@@ -1,67 +0,0 @@
//
// DownHTMLRenderable.swift
// Down
//
// Created by Rob Phillips on 5/28/16.
// Copyright © 2016 Glazed Donut, LLC. All rights reserved.
//
import Foundation
import libcmark
public protocol DownHTMLRenderable: DownRenderable {
/**
Generates an HTML string from the `markdownString` property
- parameter options: `DownOptions` to modify parsing or rendering
- throws: `DownErrors` depending on the scenario
- returns: HTML string
*/
func toHTML(_ options: DownOptions) throws -> String
}
public extension DownHTMLRenderable {
/**
Generates an HTML string from the `markdownString` property
- parameter options: `DownOptions` to modify parsing or rendering, defaulting to `.default`
- throws: `DownErrors` depending on the scenario
- returns: HTML string
*/
public func toHTML(_ options: DownOptions = .default) throws -> String {
return try markdownString.toHTML(options)
}
}
public struct DownHTMLRenderer {
/**
Generates an HTML string from the given abstract syntax tree
**Note:** caller is responsible for calling `cmark_node_free(ast)` after this returns
- parameter options: `DownOptions` to modify parsing or rendering, defaulting to `.default`
- throws: `ASTRenderingError` if the AST could not be converted
- returns: HTML string
*/
public static func astToHTML(_ ast: UnsafeMutablePointer<cmark_node>, options: DownOptions = .default) throws -> String {
guard let cHTMLString = cmark_render_html(ast, options.rawValue) else {
throw DownErrors.astRenderingError
}
defer { free(cHTMLString) }
guard let htmlString = String(cString: cHTMLString, encoding: String.Encoding.utf8) else {
throw DownErrors.astRenderingError
}
return htmlString
}
}
@@ -1,75 +0,0 @@
//
// DownLaTeXRenderable.swift
// Down
//
// Created by Rob Phillips on 5/31/16.
// Copyright © 2016 Glazed Donut, LLC. All rights reserved.
//
import Foundation
import libcmark
public protocol DownLaTeXRenderable: DownRenderable {
/**
Generates a LaTeX string from the `markdownString` property
- parameter options: `DownOptions` to modify parsing or rendering
- parameter width: The width to break on
- throws: `DownErrors` depending on the scenario
- returns: LaTeX string
*/
func toLaTeX(_ options: DownOptions, width: Int32) throws -> String
}
public extension DownLaTeXRenderable {
/**
Generates a LaTeX string from the `markdownString` property
- parameter options: `DownOptions` to modify parsing or rendering, defaulting to `.default`
- parameter width: The width to break on, defaulting to 0
- throws: `DownErrors` depending on the scenario
- returns: LaTeX string
*/
public func toLaTeX(_ options: DownOptions = .default, width: Int32 = 0) throws -> String {
let ast = try DownASTRenderer.stringToAST(markdownString, options: options)
let latex = try DownLaTeXRenderer.astToLaTeX(ast, options: options, width: width)
cmark_node_free(ast)
return latex
}
}
public struct DownLaTeXRenderer {
/**
Generates a LaTeX string from the given abstract syntax tree
**Note:** caller is responsible for calling `cmark_node_free(ast)` after this returns
- parameter options: `DownOptions` to modify parsing or rendering, defaulting to `.default`
- parameter width: The width to break on, defaulting to 0
- throws: `ASTRenderingError` if the AST could not be converted
- returns: LaTeX string
*/
public static func astToLaTeX(_ ast: UnsafeMutablePointer<cmark_node>,
options: DownOptions = .default,
width: Int32 = 0) throws -> String {
guard let cLatexString = cmark_render_latex(ast, options.rawValue, width) else {
throw DownErrors.astRenderingError
}
defer { free(cLatexString) }
guard let latexString = String(cString: cLatexString, encoding: String.Encoding.utf8) else {
throw DownErrors.astRenderingError
}
return latexString
}
}
-70
View File
@@ -1,70 +0,0 @@
//
// DownXMLRenderable.swift
// Down
//
// Created by Rob Phillips on 5/31/16.
// Copyright © 2016 Glazed Donut, LLC. All rights reserved.
//
import Foundation
import libcmark
public protocol DownXMLRenderable: DownRenderable {
/**
Generates an XML string from the `markdownString` property
- parameter options: `DownOptions` to modify parsing or rendering
- throws: `DownErrors` depending on the scenario
- returns: XML string
*/
func toXML(_ options: DownOptions) throws -> String
}
public extension DownXMLRenderable {
/**
Generates an XML string from the `markdownString` property
- parameter options: `DownOptions` to modify parsing or rendering, defaulting to `.default`
- throws: `DownErrors` depending on the scenario
- returns: XML string
*/
public func toXML(_ options: DownOptions = .default) throws -> String {
let ast = try DownASTRenderer.stringToAST(markdownString, options: options)
let xml = try DownXMLRenderer.astToXML(ast, options: options)
cmark_node_free(ast)
return xml
}
}
public struct DownXMLRenderer {
/**
Generates an XML string from the given abstract syntax tree
**Note:** caller is responsible for calling `cmark_node_free(ast)` after this returns
- parameter options: `DownOptions` to modify parsing or rendering, defaulting to `.default`
- throws: `ASTRenderingError` if the AST could not be converted
- returns: XML string
*/
public static func astToXML(_ ast: UnsafeMutablePointer<cmark_node>, options: DownOptions = .default) throws -> String {
guard let cXMLString = cmark_render_xml(ast, options.rawValue) else {
throw DownErrors.astRenderingError
}
defer { free(cXMLString) }
guard let xmlString = String(cString: cXMLString, encoding: String.Encoding.utf8) else {
throw DownErrors.astRenderingError
}
return xmlString
}
}
-192
View File
@@ -1,192 +0,0 @@
//
// DownView.swift
// Down
//
// Created by Rob Phillips on 6/1/16.
// Copyright © 2016 Glazed Donut, LLC. All rights reserved.
//
#if os(tvOS) || os(watchOS)
// Sorry, not available for tvOS nor watchOS
#else
import WebKit
// MARK: - Public API
public typealias DownViewClosure = () -> ()
open class DownView: WKWebView {
/**
Initializes a web view with the results of rendering a CommonMark Markdown string
- parameter frame: The frame size of the web view
- parameter markdownString: A string containing CommonMark Markdown
- parameter openLinksInBrowser: Whether or not to open links using an external browser
- parameter templateBundle: Optional custom template bundle. Leaving this as `nil` will use the bundle included with Down.
- parameter configuration: Optional custom web view configuration.
- parameter didLoadSuccessfully: Optional callback for when the web content has loaded successfully
- returns: An instance of Self
*/
public init(frame: CGRect, markdownString: String, openLinksInBrowser: Bool = true, templateBundle: Bundle? = nil, configuration: WKWebViewConfiguration? = nil, didLoadSuccessfully: DownViewClosure? = nil) throws {
self.didLoadSuccessfully = didLoadSuccessfully
if let templateBundle = templateBundle {
self.bundle = templateBundle
} else {
let classBundle = Bundle(for: DownView.self)
let url = classBundle.url(forResource: "DownView", withExtension: "bundle")!
self.bundle = Bundle(url: url)!
}
super.init(frame: frame, configuration: configuration ?? WKWebViewConfiguration())
#if os(macOS)
setupMacEnvironment()
#endif
if openLinksInBrowser || didLoadSuccessfully != nil { navigationDelegate = self }
try loadHTMLView(markdownString)
}
required public init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
#if os(macOS)
deinit {
clearTemporaryDirectory()
}
#endif
// MARK: - API
/**
Renders the given CommonMark Markdown string into HTML and updates the DownView while keeping the style intact
- parameter markdownString: A string containing CommonMark Markdown
- parameter didLoadSuccessfully: Optional callback for when the web content has loaded successfully
- throws: `DownErrors` depending on the scenario
*/
public func update(markdownString: String, didLoadSuccessfully: DownViewClosure? = nil) throws {
// Note: As the init method takes this callback already, we only overwrite it here if
// a non-nil value is passed in
if let didLoadSuccessfully = didLoadSuccessfully {
self.didLoadSuccessfully = didLoadSuccessfully
}
try loadHTMLView(markdownString)
}
// MARK: - Private Properties
let bundle: Bundle
fileprivate lazy var baseURL: URL = {
return self.bundle.url(forResource: "index", withExtension: "html")!
}()
#if os(macOS)
fileprivate lazy var temporaryDirectoryURL: URL = {
return try! FileManager.default.url(for: .itemReplacementDirectory,
in: .userDomainMask,
appropriateFor: URL(fileURLWithPath: "/"),
create: true).appendingPathComponent("Down", isDirectory: true)
}()
#endif
fileprivate var didLoadSuccessfully: DownViewClosure?
}
// MARK: - Private API
private extension DownView {
func loadHTMLView(_ markdownString: String) throws {
let htmlString = try markdownString.toHTML()
let pageHTMLString = try htmlFromTemplate(htmlString)
#if os(iOS)
loadHTMLString(pageHTMLString, baseURL: baseURL)
#elseif os(macOS)
let indexURL = try createTemporaryBundle(pageHTMLString: pageHTMLString)
loadFileURL(indexURL, allowingReadAccessTo: indexURL.deletingLastPathComponent())
#endif
}
func htmlFromTemplate(_ htmlString: String) throws -> String {
let template = try String(contentsOf: baseURL, encoding: .utf8)
return template.replacingOccurrences(of: "DOWN_HTML", with: htmlString)
}
#if os(macOS)
func createTemporaryBundle(pageHTMLString: String) throws -> URL {
guard let bundleResourceURL = bundle.resourceURL
else { throw DownErrors.nonStandardBundleFormatError }
let indexURL = temporaryDirectoryURL.appendingPathComponent("index.html", isDirectory: false)
// If updating markdown contents, no need to re-copy bundle.
if !FileManager.default.fileExists(atPath: indexURL.path) {
// Copy bundle resources to temporary location.
try FileManager.default.copyItem(at: bundleResourceURL, to: temporaryDirectoryURL)
}
// Write generated index.html to temporary location.
try pageHTMLString.write(to: indexURL, atomically: true, encoding: .utf8)
return indexURL
}
func setupMacEnvironment() {
NotificationCenter.default.addObserver(self,
selector: #selector(clearTemporaryDirectory),
name: NSApplication.willTerminateNotification,
object: nil)
}
@objc
func clearTemporaryDirectory() {
try? FileManager.default.removeItem(at: temporaryDirectoryURL)
}
#endif
}
// MARK: - WKNavigationDelegate
extension DownView: WKNavigationDelegate {
public func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse, decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void) {
decisionHandler(.allow)
}
public func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
guard let url = navigationAction.request.url else { return decisionHandler(.allow) }
switch navigationAction.navigationType {
case .linkActivated:
if #available(iOS 11.0, macOS 10.13, *) {
if let scheme = url.scheme, configuration.urlSchemeHandler(forURLScheme: scheme) != nil {
decisionHandler(.allow)
return
}
}
decisionHandler(.cancel)
#if os(iOS)
UIApplication.shared.openURL(url)
#elseif os(macOS)
NSWorkspace.shared.open(url)
#endif
default:
decisionHandler(.allow)
}
}
public func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
didLoadSuccessfully?()
}
}
#endif
-7
View File
@@ -1,7 +0,0 @@
#ifndef CMARK_VERSION_H
#define CMARK_VERSION_H
#define CMARK_VERSION ((0 << 16) | (25 << 8) | 2)
#define CMARK_VERSION_STRING "0.25.2"
#endif
-36
View File
@@ -1,36 +0,0 @@
#ifndef CMARK_DEBUG_H
#define CMARK_DEBUG_H
#include <stdio.h>
#include <errno.h>
#include <string.h>
#ifdef NDEBUG
#define debug(M, ...)
#else
#define debug(M, ...) \
fprintf(stderr, "DEBUG %s:%d: " M "\n", __FILE__, __LINE__, ##__VA_ARGS__)
#endif
#define clean_errno() (errno == 0 ? "None" : strerror(errno))
#define log_err(M, ...) \
fprintf(stderr, "[ERROR] (%s:%d: errno: %s) " M "\n", __FILE__, __LINE__, \
clean_errno(), ##__VA_ARGS__)
#define log_warn(M, ...) \
fprintf(stderr, "[WARN] (%s:%d: errno: %s) " M "\n", __FILE__, __LINE__, \
clean_errno(), ##__VA_ARGS__)
#define log_info(M, ...) fprintf(stderr, "[INFO] (%s:%d) " M "\n", __FILE__, \
__LINE__, ##__VA_ARGS__)
#define check(A, M, ...) \
if(!(A)) { log_err(M, ##__VA_ARGS__); errno=0; goto error; }
#define sentinel(M, ...) \
{ log_err(M, ##__VA_ARGS__); errno=0; goto error; }
#define check_debug(A, M, ...) \
if(!(A)) { debug(M, ##__VA_ARGS__); errno=0; goto error; }
#endif
File diff suppressed because it is too large Load Diff
+37
View File
@@ -0,0 +1,37 @@
//
// BaseNode.swift
// Down
//
// Created by John Nguyen on 21.04.19.
//
//
import Foundation
import libcmark
public class BaseNode: Node {
// MARK: - Properties
public let cmarkNode: CMarkNode
public private(set) lazy var children: [Node] = Array(childSequence)
public private(set) lazy var nestDepth: Int = {
var depth = 0
var next = cmarkNode.parent
while let current = next {
depth += current.type == cmarkNode.type ? 1 : 0
next = current.parent
}
return depth
}()
// MARK: - Life cycle
init(cmarkNode: CMarkNode) {
self.cmarkNode = cmarkNode
}
}
+21
View File
@@ -0,0 +1,21 @@
//
// BlockQuote.swift
// Down
//
// Created by John Nguyen on 09.04.19.
//
import Foundation
import libcmark
public class BlockQuote: BaseNode {}
// MARK: - Debug
extension BlockQuote: CustomDebugStringConvertible {
public var debugDescription: String {
return "Block Quote"
}
}
@@ -0,0 +1,52 @@
//
// ChildSequence.swift
// Down
//
// Created by Sven Weidauer on 05.10.2020
//
import libcmark
/// Sequence of child nodes.
public struct ChildSequence: Sequence {
// MARK: - Properties
let node: CMarkNode
// MARK: - Methods
public func makeIterator() -> Iterator {
return Iterator(node: cmark_node_first_child(node))
}
}
// MARK: - Iterator
public extension ChildSequence {
struct Iterator: IteratorProtocol {
// MARK: - Properties
var node: CMarkNode?
// MARK: - Methods
public mutating func next() -> Node? {
guard let node = node else { return nil }
defer { self.node = cmark_node_next(node) }
guard let result = node.wrap() else {
assertionFailure("Couldn't wrap node of type: \(node.type)")
return nil
}
return result
}
}
}
+29
View File
@@ -0,0 +1,29 @@
//
// Code.swift
// Down
//
// Created by John Nguyen on 09.04.19.
//
import Foundation
import libcmark
public class Code: BaseNode {
// MARK: - Properties
/// The code content, if present.
public private(set) lazy var literal: String? = cmarkNode.literal
}
// MARK: - Debug
extension Code: CustomDebugStringConvertible {
public var debugDescription: String {
return "Code - \(literal ?? "nil")"
}
}
+44
View File
@@ -0,0 +1,44 @@
//
// CodeBlock.swift
// Down
//
// Created by John Nguyen on 09.04.19.
//
import Foundation
import libcmark
public class CodeBlock: BaseNode {
// MARK: - Properties
/// The code content, if present.
public private(set) lazy var literal: String? = cmarkNode.literal
/// The fence info is an optional string that trails the opening sequence of backticks.
/// It can be used to provide some contextual information about the block, such as
/// the name of a programming language.
///
/// For example:
/// ```
/// '''<fence info>
/// <literal>
/// '''
/// ```
///
public private(set) lazy var fenceInfo: String? = cmarkNode.fenceInfo
}
// MARK: - Debug
extension CodeBlock: CustomDebugStringConvertible {
public var debugDescription: String {
let content = (literal ?? "nil").replacingOccurrences(of: "\n", with: "\\n")
return "Code Block - fenceInfo: \(fenceInfo ?? "nil"), content: \(content)"
}
}
+29
View File
@@ -0,0 +1,29 @@
//
// CustomBlock.swift
// Down
//
// Created by John Nguyen on 09.04.19.
//
import Foundation
import libcmark
public class CustomBlock: BaseNode {
// MARK: - Properfies
/// The custom content, if present.
public private(set) lazy var literal: String? = cmarkNode.literal
}
// MARK: - Debug
extension CustomBlock: CustomDebugStringConvertible {
public var debugDescription: String {
return "Custom Block - \(literal ?? "nil")"
}
}
+28
View File
@@ -0,0 +1,28 @@
//
// CustomInline.swift
// Down
//
// Created by John Nguyen on 09.04.19.
//
import Foundation
import libcmark
public class CustomInline: BaseNode {
// MARK: - Properties
/// The custom content, if present.
public private(set) lazy var literal: String? = cmarkNode.literal
}
// MARK: - Debug
extension CustomInline: CustomDebugStringConvertible {
public var debugDescription: String {
return "Custom Inline - \(literal ?? "nil")"
}
}
+38
View File
@@ -0,0 +1,38 @@
//
// Document.swift
// Down
//
// Created by John Nguyen on 09.04.19.
//
import Foundation
import libcmark
public class Document: BaseNode {
// MARK: - Life cycle
deinit {
cmark_node_free(cmarkNode)
}
// MARK: - Methods
/// Accepts the given visitor and return its result.
@discardableResult
public func accept<T: Visitor>(_ visitor: T) -> T.Result {
return visitor.visit(document: self)
}
}
// MARK: - Debug
extension Document: CustomDebugStringConvertible {
public var debugDescription: String {
return "Document"
}
}
+21
View File
@@ -0,0 +1,21 @@
//
// Emphasis.swift
// Down
//
// Created by John Nguyen on 09.04.19.
//
import Foundation
import libcmark
public class Emphasis: BaseNode {}
// MARK: - Debug
extension Emphasis: CustomDebugStringConvertible {
public var debugDescription: String {
return "Emphasis"
}
}
+28
View File
@@ -0,0 +1,28 @@
//
// Heading.swift
// Down
//
// Created by John Nguyen on 09.04.19.
//
import Foundation
import libcmark
public class Heading: BaseNode {
// MARK: - Properties
/// The level of the heading, a value between 1 and 6.
public private(set) lazy var headingLevel: Int = cmarkNode.headingLevel
}
// MARK: - Debug
extension Heading: CustomDebugStringConvertible {
public var debugDescription: String {
return "Heading - L\(headingLevel)"
}
}
+30
View File
@@ -0,0 +1,30 @@
//
// HtmlBlock.swift
// Down
//
// Created by John Nguyen on 09.04.19.
//
import Foundation
import libcmark
public class HtmlBlock: BaseNode {
// MARK: - Properties
/// The html content, if present.
public private(set) lazy var literal: String? = cmarkNode.literal
}
// MARK: - Debug
extension HtmlBlock: CustomDebugStringConvertible {
public var debugDescription: String {
let content = (literal ?? "nil").replacingOccurrences(of: "\n", with: "\\n")
return "Html Block - content: \(content)"
}
}
+29
View File
@@ -0,0 +1,29 @@
//
// HtmlInline.swift
// Down
//
// Created by John Nguyen on 09.04.19.
//
import Foundation
import libcmark
public class HtmlInline: BaseNode {
// MARK: - Properties
/// The html tag, if present.
public private(set) lazy var literal: String? = cmarkNode.literal
}
// MARK: - Debug
extension HtmlInline: CustomDebugStringConvertible {
public var debugDescription: String {
return "Html Inline - \(literal ?? "nil")"
}
}
+49
View File
@@ -0,0 +1,49 @@
//
// Image.swift
// Down
//
// Created by John Nguyen on 09.04.19.
//
import Foundation
import libcmark
public class Image: BaseNode {
// MARK: - Properties
/// The title of the image, if present.
///
/// In the example below, the first line is a reference link, with the reference at the
/// bottom. `<text>` is literal text belonging to children nodes. The title occurs
/// after the url and is optional.
///
/// ```
/// ![<text>][<id>]
/// ...
/// [<id>]: <url> "<title>"
/// ```
public private(set) lazy var title: String? = cmarkNode.title
/// The url of the image, if present.
///
/// For example:
///
/// ```
/// ![<text>](<url>)
/// ```
public private(set) lazy var url: String? = cmarkNode.url
}
// MARK: - Debug
extension Image: CustomDebugStringConvertible {
public var debugDescription: String {
return "Image - title: \(title ?? "nil"), url: \(url ?? "nil"))"
}
}
+21
View File
@@ -0,0 +1,21 @@
//
// Item.swift
// Down
//
// Created by John Nguyen on 09.04.19.
//
import Foundation
import libcmark
public class Item: BaseNode {}
// MARK: - Debug
extension Item: CustomDebugStringConvertible {
public var debugDescription: String {
return "Item"
}
}
+21
View File
@@ -0,0 +1,21 @@
//
// LineBreak.swift
// Down
//
// Created by John Nguyen on 09.04.19.
//
import Foundation
import libcmark
public class LineBreak: BaseNode {}
// MARK: - Debug
extension LineBreak: CustomDebugStringConvertible {
public var debugDescription: String {
return "Line Break"
}
}
+49
View File
@@ -0,0 +1,49 @@
//
// Link.swift
// Down
//
// Created by John Nguyen on 09.04.19.
//
import Foundation
import libcmark
public class Link: BaseNode {
// MARK: - Properties
/// The title of the link, if present.
///
/// In the example below, the first line is a reference link, with the reference at the
/// bottom. `<text>` is literal text belonging to children nodes. The title occurs
/// after the url and is optional.
///
/// ```
/// [<text>][<id>]
/// ...
/// [<id>]: <url> "<title>"
/// ```
public private(set) lazy var title: String? = cmarkNode.title
/// The url of the link, if present.
///
/// For example:
///
/// ```
/// [<text>](<url>)
/// ```
public private(set) lazy var url: String? = cmarkNode.url
}
// MARK: - Debug
extension Link: CustomDebugStringConvertible {
public var debugDescription: String {
return "Link - title: \(title ?? "nil"), url: \(url ?? "nil"))"
}
}
+107
View File
@@ -0,0 +1,107 @@
//
// List.swift
// Down
//
// Created by John Nguyen on 09.04.19.
//
import Foundation
import libcmark
public class List: BaseNode {
// MARK: - Properties
/// The type of the list, either bullet or ordered.
public lazy var listType: ListType = {
guard let type = ListType(cmarkNode: cmarkNode) else {
assertionFailure("Unsupported or missing list type. Defaulting to .bullet.")
return .bullet
}
return type
}()
/// The number of items in the list.
public lazy var numberOfItems: Int = children.count
/// Whether the list is "tight".
///
/// If any of the list items are separated by a blank line, then this property is `false`. This value is
/// a hint to render the list with more (loose) or less (tight) spacing between items.
public lazy var isTight: Bool = cmark_node_get_list_tight(cmarkNode) == 1
/// The list delimiter.
public lazy var delimiter: Delimiter? = Delimiter(cmarkNode.listDelimiter)
}
// MARK: - List Type
public extension List {
enum Delimiter {
case period
case paren
init?(_ cmark: cmark_delim_type) {
switch cmark {
case CMARK_NO_DELIM: return nil
case CMARK_PERIOD_DELIM: self = .period
case CMARK_PAREN_DELIM: self = .paren
default: preconditionFailure("Invalid delim type")
}
}
}
enum ListType: CustomDebugStringConvertible {
case bullet
case ordered(start: Int)
// MARK: - Properties
public var debugDescription: String {
switch self {
case .bullet: return "Bullet"
case .ordered(let start): return "Ordered (start: \(start))"
}
}
// MARK: - Life cycle
init?(cmarkNode: CMarkNode) {
switch cmarkNode.listType {
case CMARK_BULLET_LIST: self = .bullet
case CMARK_ORDERED_LIST: self = .ordered(start: cmarkNode.listStart)
default: return nil
}
}
}
}
// MARK: - Debug
extension List: CustomDebugStringConvertible {
public var debugDescription: String {
var result = "List - type: \(listType), isTight: \(isTight)"
if let delim = delimiter {
result += ", delimiter: \(delim)"
}
return result
}
}
extension List.Delimiter: CustomDebugStringConvertible {
public var debugDescription: String {
switch self {
case .paren: return "paren"
case .period: return "period"
}
}
}
+126
View File
@@ -0,0 +1,126 @@
//
// Node.swift
// Down
//
// Created by John Nguyen on 07.04.19.
//
import Foundation
import libcmark
/// A node is a wrapper of a raw `CMarkNode` belonging to the abstract syntax tree
/// generated by cmark.
public protocol Node {
/// The wrapped node.
var cmarkNode: CMarkNode { get }
/// The wrapped child nodes.
var children: [Node] { get }
}
public extension Node {
/// True iff the node has a sibling that succeeds it.
var hasSuccessor: Bool {
return cmark_node_next(cmarkNode) != nil
}
/// Sequence of wrapped child nodes.
var childSequence: ChildSequence {
return ChildSequence(node: cmarkNode)
}
}
// MARK: - Helper extensions
public typealias CMarkNode = UnsafeMutablePointer<cmark_node>
public extension CMarkNode {
/// Wraps the cmark node referred to by this pointer.
func wrap() -> Node? {
switch type {
case CMARK_NODE_DOCUMENT: return Document(cmarkNode: self)
case CMARK_NODE_BLOCK_QUOTE: return BlockQuote(cmarkNode: self)
case CMARK_NODE_LIST: return List(cmarkNode: self)
case CMARK_NODE_ITEM: return Item(cmarkNode: self)
case CMARK_NODE_CODE_BLOCK: return CodeBlock(cmarkNode: self)
case CMARK_NODE_HTML_BLOCK: return HtmlBlock(cmarkNode: self)
case CMARK_NODE_CUSTOM_BLOCK: return CustomBlock(cmarkNode: self)
case CMARK_NODE_PARAGRAPH: return Paragraph(cmarkNode: self)
case CMARK_NODE_HEADING: return Heading(cmarkNode: self)
case CMARK_NODE_THEMATIC_BREAK: return ThematicBreak(cmarkNode: self)
case CMARK_NODE_TEXT: return Text(cmarkNode: self)
case CMARK_NODE_SOFTBREAK: return SoftBreak(cmarkNode: self)
case CMARK_NODE_LINEBREAK: return LineBreak(cmarkNode: self)
case CMARK_NODE_CODE: return Code(cmarkNode: self)
case CMARK_NODE_HTML_INLINE: return HtmlInline(cmarkNode: self)
case CMARK_NODE_CUSTOM_INLINE: return CustomInline(cmarkNode: self)
case CMARK_NODE_EMPH: return Emphasis(cmarkNode: self)
case CMARK_NODE_STRONG: return Strong(cmarkNode: self)
case CMARK_NODE_LINK: return Link(cmarkNode: self)
case CMARK_NODE_IMAGE: return Image(cmarkNode: self)
default: return nil
}
}
var parent: CMarkNode? {
return cmark_node_parent(self)
}
var type: cmark_node_type {
return cmark_node_get_type(self)
}
var literal: String? {
return String(cString: cmark_node_get_literal(self))
}
var fenceInfo: String? {
return String(cString: cmark_node_get_fence_info(self))
}
var headingLevel: Int {
return Int(cmark_node_get_heading_level(self))
}
var listType: cmark_list_type {
return cmark_node_get_list_type(self)
}
var listStart: Int {
return Int(cmark_node_get_list_start(self))
}
var listDelimiter: cmark_delim_type {
return cmark_node_get_list_delim(self)
}
var url: String? {
return String(cString: cmark_node_get_url(self))
}
var title: String? {
return String(cString: cmark_node_get_title(self))
}
}
private extension String {
init?(cString: UnsafePointer<Int8>?) {
guard let unwrapped = cString else { return nil }
let result = String(cString: unwrapped)
guard !result.isEmpty else { return nil }
self = result
}
}
+21
View File
@@ -0,0 +1,21 @@
//
// Paragraph.swift
// Down
//
// Created by John Nguyen on 09.04.19.
//
import Foundation
import libcmark
public class Paragraph: BaseNode {}
// MARK: - Debug
extension Paragraph: CustomDebugStringConvertible {
public var debugDescription: String {
return "Paragraph"
}
}
+21
View File
@@ -0,0 +1,21 @@
//
// SoftBreak.swift
// Down
//
// Created by John Nguyen on 09.04.19.
//
import Foundation
import libcmark
public class SoftBreak: BaseNode {}
// MARK: - Debug
extension SoftBreak: CustomDebugStringConvertible {
public var debugDescription: String {
return "Soft Break"
}
}
+21
View File
@@ -0,0 +1,21 @@
//
// Strong.swift
// Down
//
// Created by John Nguyen on 09.04.19.
//
import Foundation
import libcmark
public class Strong: BaseNode {}
// MARK: - Debug
extension Strong: CustomDebugStringConvertible {
public var debugDescription: String {
return "Strong"
}
}
+29
View File
@@ -0,0 +1,29 @@
//
// Text.swift
// Down
//
// Created by John Nguyen on 09.04.19.
//
import Foundation
import libcmark
public class Text: BaseNode {
// MARK: - Properties
/// The text content, if present.
public private(set) lazy var literal: String? = cmarkNode.literal
}
// MARK: - Debug
extension Text: CustomDebugStringConvertible {
public var debugDescription: String {
return "Text - \(literal ?? "nil")"
}
}
@@ -0,0 +1,21 @@
//
// ThematicBreak.swift
// Down
//
// Created by John Nguyen on 09.04.19.
//
import Foundation
import libcmark
public class ThematicBreak: BaseNode {}
// MARK: - Debug
extension ThematicBreak: CustomDebugStringConvertible {
public var debugDescription: String {
return "Thematic Break"
}
}
@@ -0,0 +1,97 @@
//
// ColorCollection.swift
// Down
//
// Created by John Nguyen on 27.07.19.
// Copyright © 2016-2019 Down. All rights reserved.
//
#if !os(watchOS) && !os(Linux)
#if canImport(UIKit)
import UIKit
public typealias DownColor = UIColor
#elseif canImport(AppKit)
import AppKit
public typealias DownColor = NSColor
#endif
public protocol ColorCollection {
var heading1: DownColor { get }
var heading2: DownColor { get }
var heading3: DownColor { get }
var heading4: DownColor { get }
var heading5: DownColor { get }
var heading6: DownColor { get }
var body: DownColor { get }
var code: DownColor { get }
var link: DownColor { get }
var quote: DownColor { get }
var quoteStripe: DownColor { get }
var thematicBreak: DownColor { get }
var listItemPrefix: DownColor { get }
var codeBlockBackground: DownColor { get }
}
public struct StaticColorCollection: ColorCollection {
// MARK: - Properties
public var heading1: DownColor
public var heading2: DownColor
public var heading3: DownColor
public var heading4: DownColor
public var heading5: DownColor
public var heading6: DownColor
public var body: DownColor
public var code: DownColor
public var link: DownColor
public var quote: DownColor
public var quoteStripe: DownColor
public var thematicBreak: DownColor
public var listItemPrefix: DownColor
public var codeBlockBackground: DownColor
// MARK: - Life cycle
public init(
heading1: DownColor = .black,
heading2: DownColor = .black,
heading3: DownColor = .black,
heading4: DownColor = .black,
heading5: DownColor = .black,
heading6: DownColor = .black,
body: DownColor = .black,
code: DownColor = .black,
link: DownColor = .blue,
quote: DownColor = .darkGray,
quoteStripe: DownColor = .darkGray,
thematicBreak: DownColor = .init(white: 0.9, alpha: 1),
listItemPrefix: DownColor = .lightGray,
codeBlockBackground: DownColor = .init(red: 0.96, green: 0.97, blue: 0.98, alpha: 1)
) {
self.heading1 = heading1
self.heading2 = heading2
self.heading3 = heading3
self.heading4 = heading4
self.heading5 = heading5
self.heading6 = heading6
self.body = body
self.code = code
self.link = link
self.quote = quote
self.quoteStripe = quoteStripe
self.thematicBreak = thematicBreak
self.listItemPrefix = listItemPrefix
self.codeBlockBackground = codeBlockBackground
}
}
#endif
@@ -0,0 +1,77 @@
//
// FontCollection.swift
// Down
//
// Created by John Nguyen on 22.06.19.
// Copyright © 2016-2019 Down. All rights reserved.
//
#if !os(watchOS) && !os(Linux)
#if canImport(UIKit)
import UIKit
public typealias DownFont = UIFont
#elseif canImport(AppKit)
import AppKit
public typealias DownFont = NSFont
#endif
public protocol FontCollection {
var heading1: DownFont { get }
var heading2: DownFont { get }
var heading3: DownFont { get }
var heading4: DownFont { get }
var heading5: DownFont { get }
var heading6: DownFont { get }
var body: DownFont { get }
var code: DownFont { get }
var listItemPrefix: DownFont { get }
}
public struct StaticFontCollection: FontCollection {
// MARK: - Properties
public var heading1: DownFont
public var heading2: DownFont
public var heading3: DownFont
public var heading4: DownFont
public var heading5: DownFont
public var heading6: DownFont
public var body: DownFont
public var code: DownFont
public var listItemPrefix: DownFont
// MARK: - Life cycle
public init(
heading1: DownFont = .boldSystemFont(ofSize: 28),
heading2: DownFont = .boldSystemFont(ofSize: 24),
heading3: DownFont = .boldSystemFont(ofSize: 20),
heading4: DownFont = .boldSystemFont(ofSize: 20),
heading5: DownFont = .boldSystemFont(ofSize: 20),
heading6: DownFont = .boldSystemFont(ofSize: 20),
body: DownFont = .systemFont(ofSize: 17),
code: DownFont = DownFont(name: "menlo", size: 17) ?? .systemFont(ofSize: 17),
listItemPrefix: DownFont = DownFont.monospacedDigitSystemFont(ofSize: 17, weight: .regular)
) {
self.heading1 = heading1
self.heading2 = heading2
self.heading3 = heading3
self.heading4 = heading4
self.heading5 = heading5
self.heading6 = heading6
self.body = body
self.code = code
self.listItemPrefix = listItemPrefix
}
}
#endif
@@ -0,0 +1,74 @@
//
// ParagraphStyleCollection.swift
// Down
//
// Created by John Nguyen on 27.07.19.
// Copyright © 2016-2019 Down. All rights reserved.
//
#if !os(watchOS) && !os(Linux)
#if canImport(UIKit)
import UIKit
#elseif canImport(AppKit)
import AppKit
#endif
public protocol ParagraphStyleCollection {
var heading1: NSParagraphStyle { get }
var heading2: NSParagraphStyle { get }
var heading3: NSParagraphStyle { get }
var heading4: NSParagraphStyle { get }
var heading5: NSParagraphStyle { get }
var heading6: NSParagraphStyle { get }
var body: NSParagraphStyle { get }
var code: NSParagraphStyle { get }
}
public struct StaticParagraphStyleCollection: ParagraphStyleCollection {
// MARK: - Properties
public var heading1: NSParagraphStyle
public var heading2: NSParagraphStyle
public var heading3: NSParagraphStyle
public var heading4: NSParagraphStyle
public var heading5: NSParagraphStyle
public var heading6: NSParagraphStyle
public var body: NSParagraphStyle
public var code: NSParagraphStyle
// MARK: - Life cycle
public init() {
let headingStyle = NSMutableParagraphStyle()
headingStyle.paragraphSpacing = 8
let bodyStyle = NSMutableParagraphStyle()
bodyStyle.paragraphSpacingBefore = 8
bodyStyle.paragraphSpacing = 8
bodyStyle.lineSpacing = 8
let codeStyle = NSMutableParagraphStyle()
codeStyle.paragraphSpacingBefore = 8
codeStyle.paragraphSpacing = 8
heading1 = headingStyle
heading2 = headingStyle
heading3 = headingStyle
heading4 = headingStyle
heading5 = headingStyle
heading6 = headingStyle
body = bodyStyle
code = codeStyle
}
}
#endif
@@ -0,0 +1,36 @@
//
// BlockBackgroundColorAttribute.swift
// Down
//
// Created by John Nguyen on 11.08.19.
// Copyright © 2016-2019 Down. All rights reserved.
//
#if !os(watchOS) && !os(Linux)
#if canImport(UIKit)
import UIKit
#elseif canImport(AppKit)
import AppKit
#endif
struct BlockBackgroundColorAttribute {
// MARK: - Properties
var color: DownColor
var inset: CGFloat
}
extension NSAttributedString.Key {
static let blockBackgroundColor = NSAttributedString.Key("blockBackgroundColor")
}
#endif
@@ -0,0 +1,64 @@
//
// QuoteStripeAttrbute.swift
// Down
//
// Created by John Nguyen on 03.08.19.
// Copyright © 2016-2019 Down. All rights reserved.
//
#if !os(watchOS) && !os(Linux)
#if canImport(UIKit)
import UIKit
#elseif canImport(AppKit)
import AppKit
#endif
struct QuoteStripeAttribute {
// MARK: - Properties
var color: DownColor
var thickness: CGFloat
var spacingAfter: CGFloat
var locations: [CGFloat]
var layoutWidth: CGFloat {
return thickness + spacingAfter
}
// MARK: - Life cycle
init(color: DownColor, thickness: CGFloat, spacingAfter: CGFloat, locations: [CGFloat]) {
self.color = color
self.thickness = thickness
self.spacingAfter = spacingAfter
self.locations = locations
}
init(level: Int, color: DownColor, options: QuoteStripeOptions) {
self.init(color: color, thickness: options.thickness, spacingAfter: options.spacingAfter, locations: [])
locations = (0..<level).map { CGFloat($0) * layoutWidth }
}
// MARK: - Methods
func indented(by indentation: CGFloat) -> QuoteStripeAttribute {
var copy = self
copy.locations = locations.map { $0 + indentation }
return copy
}
}
extension NSAttributedString.Key {
static let quoteStripe = NSAttributedString.Key(rawValue: "quoteStripe")
}
#endif
@@ -0,0 +1,36 @@
//
// ThematicBreaAttributek.swift
// Down
//
// Created by John Nguyen on 02.08.19.
// Copyright © 2016-2019 Down. All rights reserved.
//
#if !os(watchOS) && !os(Linux)
#if canImport(UIKit)
import UIKit
#elseif canImport(AppKit)
import AppKit
#endif
struct ThematicBreakAttribute {
// MARK: - Properties
var thickness: CGFloat
var color: DownColor
}
extension NSAttributedString.Key {
static let thematicBreak = NSAttributedString.Key(rawValue: "thematicBreak")
}
#endif
@@ -0,0 +1,29 @@
//
// CGPoint+Translate.swift
// Down
//
// Created by John Nguyen on 12.08.19.
// Copyright © 2016-2019 Down. All rights reserved.
//
#if !os(Linux)
#if canImport(UIKit)
import UIKit
#elseif canImport(AppKit)
import AppKit
#endif
extension CGPoint {
func translated(by point: CGPoint) -> CGPoint {
return CGPoint(x: x + point.x, y: y + point.y)
}
}
#endif
@@ -0,0 +1,33 @@
//
// CGRect+Helpers.swift
// Down
//
// Created by John Nguyen on 12.08.19.
// Copyright © 2016-2019 Down. All rights reserved.
//
#if !os(Linux)
#if canImport(UIKit)
import UIKit
#elseif canImport(AppKit)
import AppKit
#endif
extension CGRect {
init(minX: CGFloat, minY: CGFloat, maxX: CGFloat, maxY: CGFloat) {
self.init(x: minX, y: minY, width: maxX - minX, height: maxY - minY)
}
func translated(by point: CGPoint) -> CGRect {
return CGRect(origin: origin.translated(by: point), size: size)
}
}
#endif
@@ -0,0 +1,79 @@
//
// NSAttributedString+Helpers.swift
// Down
//
// Created by John Nguyen on 22.06.19.
// Copyright © 2016-2019 Down. All rights reserved.
//
import Foundation
extension NSAttributedString {
typealias Attributes = [NSAttributedString.Key: Any]
// MARK: - Ranges
var wholeRange: NSRange {
return NSRange(location: 0, length: length)
}
func ranges(of key: Key) -> [NSRange] {
return ranges(of: key, in: wholeRange)
}
func ranges(of key: Key, in range: NSRange) -> [NSRange] {
return ranges(for: key, in: range, where: { $0 != nil })
}
func rangesMissingAttribute(for key: Key) -> [NSRange] {
return rangesMissingAttribute(for: key, in: wholeRange)
}
func rangesMissingAttribute(for key: Key, in range: NSRange) -> [NSRange] {
return ranges(for: key, in: range, where: { $0 == nil })
}
private func ranges(for key: Key, in range: NSRange, where predicate: (Any?) -> Bool) -> [NSRange] {
var ranges = [NSRange]()
enumerateAttribute(key, in: range, options: []) { value, attrRange, _ in
if predicate(value) {
ranges.append(attrRange)
}
}
return ranges
}
func paragraphRanges() -> [NSRange] {
guard length > 0 else { return [] }
func nextParagraphRange(at location: Int) -> NSRange {
return NSString(string: string).paragraphRange(for: NSRange(location: location, length: 1))
}
var result = [nextParagraphRange(at: 0)]
while let currentLocation = result.last?.upperBound, currentLocation < length {
result.append(nextParagraphRange(at: currentLocation))
}
return result.filter { $0.length > 1 }
}
// MARK: - Enumerate attributes
func enumerateAttributes<A>(for key: Key, block: (_ attr: A, _ range: NSRange) -> Void) {
enumerateAttributes(for: key, in: wholeRange, block: block)
}
func enumerateAttributes<A>(for key: Key, in range: NSRange, block: (_ attr: A, _ range: NSRange) -> Void) {
enumerateAttribute(key, in: range, options: []) { value, range, _ in
if let value = value as? A {
block(value, range)
}
}
}
}
@@ -0,0 +1,58 @@
//
// NSMutableAttributedString+Attributes.swift
// Down
//
// Created by John Nguyen on 22.06.19.
// Copyright © 2016-2019 Down. All rights reserved.
//
import Foundation
extension NSMutableAttributedString {
func setAttributes(_ attrs: Attributes) {
setAttributes(attrs, range: wholeRange)
}
func addAttributes(_ attrs: Attributes) {
addAttributes(attrs, range: wholeRange)
}
func addAttribute(for key: Key, value: Any) {
addAttribute(key, value: value, range: wholeRange)
}
func removeAttribute(for key: Key) {
removeAttribute(key, range: wholeRange)
}
func replaceAttribute(for key: Key, value: Any) {
replaceAttribute(for: key, value: value, inRange: wholeRange)
}
func replaceAttribute(for key: Key, value: Any, inRange range: NSRange) {
removeAttribute(key, range: range)
addAttribute(key, value: value, range: range)
}
func updateExistingAttributes<A>(for key: Key, using transform: (A) -> A) {
updateExistingAttributes(for: key, in: wholeRange, using: transform)
}
func updateExistingAttributes<A>(for key: Key, in range: NSRange, using transform: (A) -> A) {
var existingValues = [(value: A, range: NSRange)]()
enumerateAttributes(for: key, in: range) { existingValues.append(($0, $1)) }
existingValues.forEach { addAttribute(key, value: transform($0.0), range: $0.1) }
}
func addAttributeInMissingRanges<A>(for key: Key, value: A) {
addAttributeInMissingRanges(for: key, value: value, within: wholeRange)
}
func addAttributeInMissingRanges<A>(for key: Key, value: A, within range: NSRange) {
rangesMissingAttribute(for: key, in: range).forEach {
addAttribute(key, value: value, range: $0)
}
}
}
@@ -0,0 +1,94 @@
//
// UIFont+Traits.swift
// Down
//
// Created by John Nguyen on 22.06.19.
// Copyright © 2016-2019 Down. All rights reserved.
//
#if !os(watchOS) && !os(Linux)
#if canImport(UIKit)
import UIKit
public typealias DownFontDescriptor = UIFontDescriptor
#elseif canImport(AppKit)
import AppKit
public typealias DownFontDescriptor = NSFontDescriptor
#endif
extension DownFont {
var isStrong: Bool {
return contains(.strong)
}
var isEmphasized: Bool {
return contains(.emphasis)
}
var isMonospace: Bool {
return contains(.monoSpace)
}
var strong: DownFont {
return with(.strong) ?? self
}
var emphasis: DownFont {
return with(.emphasis) ?? self
}
var monospace: DownFont {
return with(.monoSpace) ?? self
}
private func with(_ trait: DownFontDescriptor.SymbolicTraits) -> DownFont? {
guard !contains(trait) else { return self }
var traits = fontDescriptor.symbolicTraits
traits.insert(trait)
#if canImport(UIKit)
guard let newDescriptor = fontDescriptor.withSymbolicTraits(traits) else { return self }
return DownFont(descriptor: newDescriptor, size: pointSize)
#elseif canImport(AppKit)
let newDescriptor = fontDescriptor.withSymbolicTraits(traits)
return DownFont(descriptor: newDescriptor, size: pointSize)
#endif
}
private func contains(_ trait: DownFontDescriptor.SymbolicTraits) -> Bool {
return fontDescriptor.symbolicTraits.contains(trait)
}
}
#if canImport(UIKit)
private extension DownFontDescriptor.SymbolicTraits {
static let strong = DownFontDescriptor.SymbolicTraits.traitBold
static let emphasis = DownFontDescriptor.SymbolicTraits.traitItalic
static let monoSpace = DownFontDescriptor.SymbolicTraits.traitMonoSpace
}
#elseif canImport(AppKit)
private extension DownFontDescriptor.SymbolicTraits {
static let strong = DownFontDescriptor.SymbolicTraits.bold
static let emphasis = DownFontDescriptor.SymbolicTraits.italic
static let monoSpace = DownFontDescriptor.SymbolicTraits.monoSpace
}
#endif
#endif
@@ -0,0 +1,115 @@
//
// ParagraphStyler.swift
// Down
//
// Created by John Nguyen on 25.06.19.
// Copyright © 2016-2019 Down. All rights reserved.
//
#if !os(watchOS) && !os(Linux)
#if canImport(UIKit)
import UIKit
#elseif canImport(AppKit)
import AppKit
#endif
/// A convenient class used to format lists, such that list item prefixes
/// are right aligned and list item content left aligns.
public class ListItemParagraphStyler {
// MARK: - Properties
public var indentation: CGFloat {
return largestPrefixWidth + options.spacingAfterPrefix
}
/// The paragraph style intended for all paragraphs excluding the first.
public var trailingParagraphStyle: NSParagraphStyle {
let contentIndentation = indentation
let style = baseStyle
style.firstLineHeadIndent = contentIndentation
style.headIndent = contentIndentation
return style
}
private let options: ListItemOptions
private let largestPrefixWidth: CGFloat
private var baseStyle: NSMutableParagraphStyle {
let style = NSMutableParagraphStyle()
style.paragraphSpacingBefore = options.spacingAbove
style.paragraphSpacing = options.spacingBelow
style.alignment = options.alignment
return style
}
// MARK: - Life cycle
public init(options: ListItemOptions, prefixFont: DownFont) {
self.options = options
self.largestPrefixWidth = prefixFont.widthOfNumberedPrefix(digits: options.maxPrefixDigits)
}
// MARK: - Methods
/// The paragraph style intended for the first paragraph of the list item.
///
/// - Parameter prefixWidth: the width (in points) of the list item prefix.
public func leadingParagraphStyle(prefixWidth: CGFloat) -> NSParagraphStyle {
let contentIndentation = indentation
let prefixIndentation: CGFloat = contentIndentation - options.spacingAfterPrefix - prefixWidth
let prefixSpill = max(0, prefixWidth - largestPrefixWidth)
let firstLineContentIndentation = contentIndentation + prefixSpill
let style = baseStyle
style.firstLineHeadIndent = prefixIndentation
style.tabStops = [tabStop(at: firstLineContentIndentation)]
style.headIndent = contentIndentation
return style
}
private func tabStop(at location: CGFloat) -> NSTextTab {
return NSTextTab(textAlignment: options.alignment, location: location, options: [:])
}
}
// MARK: - Helpers
private extension DownFont {
func widthOfNumberedPrefix(digits: UInt) -> CGFloat {
return widthOfLargestDigit * CGFloat(digits) + widthOfPeriod
}
private var widthOfLargestDigit: CGFloat {
return Int.decimalDigits
.map { NSAttributedString(string: "\($0)", attributes: [.font: self]).size().width }
.max()!
}
private var widthOfPeriod: CGFloat {
return NSAttributedString(string: ".", attributes: [.font: self])
.size()
.width
}
}
private extension Int {
static var decimalDigits: [Int] {
return Array(0...9)
}
}
#endif
@@ -0,0 +1,64 @@
//
// DownDebugLayoutManager.swift
// Down
//
// Created by John Nguyen on 06.08.19.
// Copyright © 2016-2019 Down. All rights reserved.
//
#if !os(watchOS) && !os(Linux)
#if canImport(UIKit)
import UIKit
#elseif canImport(AppKit)
import AppKit
#endif
/// A layout manager that draws the line fragments.
///
/// Line fragments are the areas with a document that contain lines of text. There
/// are two types.
///
/// 1. A *line rect* (drawn in red) indicates the maximum rect enclosing the line.
/// This inlcudes not only the textual content, but also the padding (if any) around that text.
/// 2. A *line used rect* (drawn in blue) is the smallest rect enclosing the textual content.
///
/// The visualization of these rects is useful when determining the paragraph styles
/// of a `DownStyler`.
///
/// Insert this into a TextKit stack manually, or use the provided `DownDebugTextView`.
public class DownDebugLayoutManager: DownLayoutManager {
// MARK: - Drawing
override public func drawGlyphs(forGlyphRange glyphsToShow: NSRange, at origin: CGPoint) {
super.drawGlyphs(forGlyphRange: glyphsToShow, at: origin)
drawLineFragments(forGlyphRange: glyphsToShow, at: origin)
}
private func drawLineFragments(forGlyphRange glyphsToShow: NSRange, at origin: CGPoint) {
enumerateLineFragments(forGlyphRange: glyphsToShow) { rect, usedRect, _, _, _ in
[(usedRect, DownColor.blue), (rect, DownColor.red)].forEach { rectToDraw, color in
let adjustedRect = rectToDraw.translated(by: origin)
self.drawRect(adjustedRect, color: color.cgColor)
}
}
}
private func drawRect(_ rect: CGRect, color: CGColor) {
guard let context = context else { return }
push(context: context)
defer { popContext() }
context.setStrokeColor(color)
context.stroke(rect)
}
}
#endif
@@ -0,0 +1,231 @@
//
// DownLayoutManager.swift
// Down
//
// Created by John Nguyen on 02.08.19.
// Copyright © 2016-2019 Down. All rights reserved.
//
#if !os(watchOS) && !os(Linux)
#if canImport(UIKit)
import UIKit
#elseif canImport(AppKit)
import AppKit
#endif
/// A layout manager capable of drawing the custom attributes set by the `DownStyler`.
///
/// Insert this into a TextKit stack manually, or use the provided `DownTextView`.
public class DownLayoutManager: NSLayoutManager {
// MARK: - Graphic context
#if canImport(UIKit)
var context: CGContext? {
return UIGraphicsGetCurrentContext()
}
func push(context: CGContext) {
UIGraphicsPushContext(context)
}
func popContext() {
UIGraphicsPopContext()
}
#elseif canImport(AppKit)
var context: CGContext? {
return NSGraphicsContext.current?.cgContext
}
func push(context: CGContext) {
NSGraphicsContext.saveGraphicsState()
}
func popContext() {
NSGraphicsContext.restoreGraphicsState()
}
#endif
// MARK: - Drawing
override public func drawGlyphs(forGlyphRange glyphsToShow: NSRange, at origin: CGPoint) {
drawCustomBackgrounds(forGlyphRange: glyphsToShow, at: origin)
super.drawGlyphs(forGlyphRange: glyphsToShow, at: origin)
drawCustomAttributes(forGlyphRange: glyphsToShow, at: origin)
}
private func drawCustomBackgrounds(forGlyphRange glyphsToShow: NSRange, at origin: CGPoint) {
guard let context = context else { return }
push(context: context)
defer { popContext() }
guard let textStorage = textStorage else { return }
let characterRange = self.characterRange(forGlyphRange: glyphsToShow, actualGlyphRange: nil)
textStorage.enumerateAttributes(for: .blockBackgroundColor,
in: characterRange) { (attr: BlockBackgroundColorAttribute, blockRange) in
let inset = attr.inset
context.setFillColor(attr.color.cgColor)
let allBlockColorRanges = glyphRanges(for: .blockBackgroundColor,
in: textStorage,
inCharacterRange: blockRange)
let glyphRange = self.glyphRange(forCharacterRange: blockRange, actualCharacterRange: nil)
enumerateLineFragments(forGlyphRange: glyphRange) { lineRect, lineUsedRect, container, lineGlyphRange, _ in
let isLineStartOfBlock = allBlockColorRanges.contains {
lineGlyphRange.overlapsStart(of: $0)
}
let isLineEndOfBlock = allBlockColorRanges.contains {
lineGlyphRange.overlapsEnd(of: $0)
}
let minX = lineUsedRect.minX + container.lineFragmentPadding - inset
let maxX = lineRect.maxX
let minY = isLineStartOfBlock ? lineUsedRect.minY - inset : lineRect.minY
let maxY = isLineEndOfBlock ? lineUsedRect.maxY + inset : lineUsedRect.maxY
let blockRect = CGRect(minX: minX, minY: minY, maxX: maxX, maxY: maxY).translated(by: origin)
context.fill(blockRect)
}
}
}
private func drawCustomAttributes(forGlyphRange glyphsToShow: NSRange, at origin: CGPoint) {
let characterRange = self.characterRange(forGlyphRange: glyphsToShow, actualGlyphRange: nil)
drawThematicBreakIfNeeded(in: characterRange, at: origin)
drawQuoteStripeIfNeeded(in: characterRange, at: origin)
}
private func drawThematicBreakIfNeeded(in characterRange: NSRange, at origin: CGPoint) {
guard let context = context else { return }
push(context: context)
defer { popContext() }
textStorage?.enumerateAttributes(for: .thematicBreak,
in: characterRange) { (attr: ThematicBreakAttribute, range) in
let firstGlyphIndex = glyphIndexForCharacter(at: range.lowerBound)
let lineRect = lineFragmentRect(forGlyphAt: firstGlyphIndex, effectiveRange: nil)
let usedRect = lineFragmentUsedRect(forGlyphAt: firstGlyphIndex, effectiveRange: nil)
let lineStart = usedRect.minX + fragmentPadding(forGlyphAt: firstGlyphIndex)
let width = lineRect.width - lineStart
let height = lineRect.height
let boundingRect = CGRect(x: lineStart, y: lineRect.minY, width: width, height: height)
let adjustedLineRect = boundingRect.translated(by: origin)
drawThematicBreak(with: context, in: adjustedLineRect, attr: attr)
}
}
private func fragmentPadding(forGlyphAt glyphIndex: Int) -> CGFloat {
let textContainer = self.textContainer(forGlyphAt: glyphIndex, effectiveRange: nil)
return textContainer?.lineFragmentPadding ?? 0
}
private func drawThematicBreak(with context: CGContext, in rect: CGRect, attr: ThematicBreakAttribute) {
context.setStrokeColor(attr.color.cgColor)
context.setLineWidth(attr.thickness)
context.move(to: CGPoint(x: rect.minX, y: rect.midY))
context.addLine(to: CGPoint(x: rect.maxX, y: rect.midY))
context.strokePath()
}
private func drawQuoteStripeIfNeeded(in characterRange: NSRange, at origin: CGPoint) {
guard let context = context else { return }
push(context: context)
defer { popContext() }
textStorage?.enumerateAttributes(for: .quoteStripe,
in: characterRange) { (attr: QuoteStripeAttribute, quoteRange) in
context.setFillColor(attr.color.cgColor)
let glyphRangeOfQuote = self.glyphRange(forCharacterRange: quoteRange, actualCharacterRange: nil)
enumerateLineFragments(forGlyphRange: glyphRangeOfQuote) { lineRect, _, container, _, _ in
let locations = attr.locations.map {
CGPoint(x: $0 + container.lineFragmentPadding, y: 0)
.translated(by: lineRect.origin)
.translated(by: origin)
}
let stripeSize = CGSize(width: attr.thickness, height: lineRect.height)
self.drawQuoteStripes(with: context, locations: locations, size: stripeSize)
}
}
}
private func drawQuoteStripes(with context: CGContext, locations: [CGPoint], size: CGSize) {
locations.forEach {
let stripeRect = CGRect(origin: $0, size: size)
context.fill(stripeRect)
}
}
private func glyphRanges(for key: NSAttributedString.Key,
in storage: NSTextStorage,
inCharacterRange range: NSRange) -> [NSRange] {
return storage
.ranges(of: key, in: range)
.map { self.glyphRange(forCharacterRange: $0, actualCharacterRange: nil) }
.mergeNeighbors()
}
}
// MARK: - Helpers
private extension NSRange {
func overlapsStart(of range: NSRange) -> Bool {
return lowerBound <= range.lowerBound && upperBound > range.lowerBound
}
func overlapsEnd(of range: NSRange) -> Bool {
return lowerBound < range.upperBound && upperBound >= range.upperBound
}
}
private extension Array where Element == NSRange {
func mergeNeighbors() -> [Element] {
let sorted = self.sorted { $0.lowerBound <= $1.lowerBound }
let result = sorted.reduce(into: [NSRange]()) { acc, next in
guard let last = acc.popLast() else {
acc.append(next)
return
}
guard last.upperBound == next.lowerBound else {
acc.append(contentsOf: [last, next])
return
}
acc.append(NSRange(location: last.lowerBound, length: next.upperBound - last.lowerBound))
}
return result
}
}
#endif
@@ -0,0 +1,35 @@
//
// CodeBlockOptions.swift
// Down
//
// Created by John Nguyen on 12.08.19.
// Copyright © 2016-2019 Down. All rights reserved.
//
#if !os(watchOS) && !os(Linux)
#if canImport(UIKit)
import UIKit
#elseif canImport(AppKit)
import AppKit
#endif
public struct CodeBlockOptions {
// MARK: - Properties
public var containerInset: CGFloat
// MARK: - Life cycle
public init(containerInset: CGFloat = 8) {
self.containerInset = containerInset
}
}
#endif
@@ -0,0 +1,48 @@
//
// ListItemOptions.swift
// Down
//
// Created by John Nguyen on 04.08.19.
// Copyright © 2016-2019 Down. All rights reserved.
//
#if !os(watchOS) && !os(Linux)
#if canImport(UIKit)
import UIKit
#elseif canImport(AppKit)
import AppKit
#endif
public struct ListItemOptions {
// MARK: - Properties
public var maxPrefixDigits: UInt
public var spacingAfterPrefix: CGFloat
public var spacingAbove: CGFloat
public var spacingBelow: CGFloat
public var alignment: NSTextAlignment
// MARK: - Life cycle
public init(maxPrefixDigits: UInt = 2,
spacingAfterPrefix: CGFloat = 8,
spacingAbove: CGFloat = 4,
spacingBelow: CGFloat = 8,
alignment: NSTextAlignment = .natural) {
self.maxPrefixDigits = maxPrefixDigits
self.spacingAfterPrefix = spacingAfterPrefix
self.spacingAbove = spacingAbove
self.spacingBelow = spacingBelow
self.alignment = alignment
}
}
#endif
@@ -0,0 +1,37 @@
//
// QuoteStripeOptions.swift
// Down
//
// Created by John Nguyen on 04.08.19.
// Copyright © 2016-2019 Down. All rights reserved.
//
#if !os(Linux)
#if canImport(UIKit)
import UIKit
#elseif canImport(AppKit)
import AppKit
#endif
public struct QuoteStripeOptions {
// MARK: - Properties
public var thickness: CGFloat
public var spacingAfter: CGFloat
// MARK: - Life cycle
public init(thickness: CGFloat = 2, spacingAfter: CGFloat = 8) {
self.thickness = thickness
self.spacingAfter = spacingAfter
}
}
#endif
@@ -0,0 +1,37 @@
//
// ThematicBreakOptions.swift
// Down
//
// Created by John Nguyen on 04.08.19.
// Copyright © 2016-2019 Down. All rights reserved.
//
#if !os(watchOS) && !os(Linux)
#if canImport(UIKit)
import UIKit
#elseif canImport(AppKit)
import AppKit
#endif
public struct ThematicBreakOptions {
// MARK: - Properties
public var thickness: CGFloat
public var indentation: CGFloat
// MARK: - Life cycle
public init(thickness: CGFloat = 1, indentation: CGFloat = 0) {
self.thickness = thickness
self.indentation = indentation
}
}
#endif
@@ -0,0 +1,308 @@
//
// DownStyler.swift
// Down
//
// Created by John Nguyen on 22.06.19.
// Copyright © 2016-2019 Down. All rights reserved.
//
#if !os(watchOS) && !os(Linux)
#if canImport(UIKit)
import UIKit
#elseif canImport(AppKit)
import AppKit
#endif
/// A default `Styler` implementation that supports a variety of configurable
/// properties for font, text color and paragraph styling, as well as formatting
/// of nested lists and quotes.
open class DownStyler: Styler {
// MARK: - Properties
public let fonts: FontCollection
public let colors: ColorCollection
public let paragraphStyles: ParagraphStyleCollection
public let quoteStripeOptions: QuoteStripeOptions
public let thematicBreakOptions: ThematicBreakOptions
public let codeBlockOptions: CodeBlockOptions
private let itemParagraphStyler: ListItemParagraphStyler
private var listPrefixAttributes: [NSAttributedString.Key: Any] {[
.font: fonts.listItemPrefix,
.foregroundColor: colors.listItemPrefix]
}
// MARK: - Life cycle
public init(configuration: DownStylerConfiguration = DownStylerConfiguration()) {
fonts = configuration.fonts
colors = configuration.colors
paragraphStyles = configuration.paragraphStyles
quoteStripeOptions = configuration.quoteStripeOptions
thematicBreakOptions = configuration.thematicBreakOptions
codeBlockOptions = configuration.codeBlockOptions
itemParagraphStyler = ListItemParagraphStyler(options: configuration.listItemOptions,
prefixFont: fonts.listItemPrefix)
}
// MARK: - Styling
open func style(document str: NSMutableAttributedString) {
}
open func style(blockQuote str: NSMutableAttributedString, nestDepth: Int) {
let stripeAttribute = QuoteStripeAttribute(level: nestDepth + 1,
color: colors.quoteStripe,
options: quoteStripeOptions)
str.updateExistingAttributes(for: .paragraphStyle) { (style: NSParagraphStyle) in
style.indented(by: stripeAttribute.layoutWidth)
}
str.addAttributeInMissingRanges(for: .quoteStripe, value: stripeAttribute)
str.addAttribute(for: .foregroundColor, value: colors.quote)
}
open func style(list str: NSMutableAttributedString, nestDepth: Int) {
}
open func style(listItemPrefix str: NSMutableAttributedString) {
str.setAttributes(listPrefixAttributes)
}
open func style(item str: NSMutableAttributedString, prefixLength: Int) {
let paragraphRanges = str.paragraphRanges()
guard let leadingParagraphRange = paragraphRanges.first else { return }
indentListItemLeadingParagraph(in: str, prefixLength: prefixLength, in: leadingParagraphRange)
paragraphRanges.dropFirst().forEach {
indentListItemTrailingParagraph(in: str, inRange: $0)
}
}
open func style(codeBlock str: NSMutableAttributedString, fenceInfo: String?) {
styleGenericCodeBlock(in: str)
}
open func style(htmlBlock str: NSMutableAttributedString) {
styleGenericCodeBlock(in: str)
}
open func style(customBlock str: NSMutableAttributedString) {
}
open func style(paragraph str: NSMutableAttributedString) {
str.addAttribute(for: .paragraphStyle, value: paragraphStyles.body)
}
open func style(heading str: NSMutableAttributedString, level: Int) {
let (font, color, paragraphStyle) = headingAttributes(for: level)
str.updateExistingAttributes(for: .font) { (currentFont: DownFont) in
var newFont = font
if currentFont.isMonospace {
newFont = newFont.monospace
}
if currentFont.isEmphasized {
newFont = newFont.emphasis
}
if currentFont.isStrong {
newFont = newFont.strong
}
return newFont
}
str.addAttributes([
.foregroundColor: color,
.paragraphStyle: paragraphStyle])
}
open func style(thematicBreak str: NSMutableAttributedString) {
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.firstLineHeadIndent = thematicBreakOptions.indentation
let attr = ThematicBreakAttribute(thickness: thematicBreakOptions.thickness, color: colors.thematicBreak)
str.addAttribute(for: .thematicBreak, value: attr)
str.addAttribute(for: .paragraphStyle, value: paragraphStyle)
}
open func style(text str: NSMutableAttributedString) {
str.setAttributes([
.font: fonts.body,
.foregroundColor: colors.body])
}
open func style(softBreak str: NSMutableAttributedString) {
}
open func style(lineBreak str: NSMutableAttributedString) {
}
open func style(code str: NSMutableAttributedString) {
styleGenericInlineCode(in: str)
}
open func style(htmlInline str: NSMutableAttributedString) {
styleGenericInlineCode(in: str)
}
open func style(customInline str: NSMutableAttributedString) {
}
open func style(emphasis str: NSMutableAttributedString) {
str.updateExistingAttributes(for: .font) { (font: DownFont) in
font.emphasis
}
}
open func style(strong str: NSMutableAttributedString) {
str.updateExistingAttributes(for: .font) { (font: DownFont) in
font.strong
}
}
open func style(link str: NSMutableAttributedString, title: String?, url: String?) {
guard let url = url else { return }
styleGenericLink(in: str, url: url)
}
open func style(image str: NSMutableAttributedString, title: String?, url: String?) {
guard let url = url else { return }
styleGenericLink(in: str, url: url)
}
// MARK: - Common Styling
private func styleGenericCodeBlock(in str: NSMutableAttributedString) {
let blockBackgroundAttribute = BlockBackgroundColorAttribute(
color: colors.codeBlockBackground,
inset: codeBlockOptions.containerInset)
let adjustedParagraphStyle = paragraphStyles.code.inset(by: blockBackgroundAttribute.inset)
str.setAttributes([
.font: fonts.code,
.foregroundColor: colors.code,
.paragraphStyle: adjustedParagraphStyle,
.blockBackgroundColor: blockBackgroundAttribute])
}
private func styleGenericInlineCode(in str: NSMutableAttributedString) {
str.setAttributes([
.font: fonts.code,
.foregroundColor: colors.code])
}
private func styleGenericLink(in str: NSMutableAttributedString, url: String) {
str.addAttributes([
.link: url,
.foregroundColor: colors.link])
}
// MARK: - Helpers
private func headingAttributes(for level: Int) -> (DownFont, DownColor, NSParagraphStyle) {
switch level {
case 1: return (fonts.heading1, colors.heading1, paragraphStyles.heading1)
case 2: return (fonts.heading2, colors.heading2, paragraphStyles.heading2)
case 3: return (fonts.heading3, colors.heading3, paragraphStyles.heading3)
case 4: return (fonts.heading4, colors.heading4, paragraphStyles.heading4)
case 5: return (fonts.heading5, colors.heading5, paragraphStyles.heading5)
case 6: return (fonts.heading6, colors.heading6, paragraphStyles.heading6)
default: return (fonts.heading1, colors.heading1, paragraphStyles.heading1)
}
}
private func indentListItemLeadingParagraph(in str: NSMutableAttributedString,
prefixLength: Int,
in range: NSRange) {
str.updateExistingAttributes(for: .paragraphStyle, in: range) { (existingStyle: NSParagraphStyle) in
existingStyle.indented(by: itemParagraphStyler.indentation)
}
let attributedPrefix = str.prefix(with: prefixLength)
let prefixWidth = attributedPrefix.size().width
let defaultStyle = itemParagraphStyler.leadingParagraphStyle(prefixWidth: prefixWidth)
str.addAttributeInMissingRanges(for: .paragraphStyle, value: defaultStyle, within: range)
}
private func indentListItemTrailingParagraph(in str: NSMutableAttributedString, inRange range: NSRange) {
str.updateExistingAttributes(for: .paragraphStyle, in: range) { (existingStyle: NSParagraphStyle) in
existingStyle.indented(by: itemParagraphStyler.indentation)
}
let defaultStyle = itemParagraphStyler.trailingParagraphStyle
str.addAttributeInMissingRanges(for: .paragraphStyle, value: defaultStyle, within: range)
indentListItemQuotes(in: str, inRange: range)
}
private func indentListItemQuotes(in str: NSMutableAttributedString, inRange range: NSRange) {
str.updateExistingAttributes(for: .quoteStripe, in: range) { (stripe: QuoteStripeAttribute) in
stripe.indented(by: itemParagraphStyler.indentation)
}
}
}
// MARK: - Helper Extensions
private extension NSParagraphStyle {
func indented(by indentation: CGFloat) -> NSParagraphStyle {
guard let result = mutableCopy() as? NSMutableParagraphStyle else { return self }
result.firstLineHeadIndent += indentation
result.headIndent += indentation
result.tabStops = tabStops.map {
NSTextTab(textAlignment: $0.alignment, location: $0.location + indentation, options: $0.options)
}
return result
}
func inset(by amount: CGFloat) -> NSParagraphStyle {
guard let result = mutableCopy() as? NSMutableParagraphStyle else { return self }
result.paragraphSpacingBefore += amount
result.paragraphSpacing += amount
result.firstLineHeadIndent += amount
result.headIndent += amount
result.tailIndent = -amount
return result
}
}
private extension NSAttributedString {
func prefix(with length: Int) -> NSAttributedString {
guard length <= self.length else { return self }
guard length > 0 else { return NSAttributedString() }
return attributedSubstring(from: NSRange(location: 0, length: length))
}
}
#endif
@@ -0,0 +1,47 @@
//
// DownStylerConfiguration.swift
// Down
//
// Created by John Nguyen on 10.08.19.
// Copyright © 2016-2019 Down. All rights reserved.
//
#if !os(watchOS) && !os(Linux)
/// A configuration object used to initialze the `DownStyler`.
public struct DownStylerConfiguration {
// MARK: - Properties
public var fonts: FontCollection
public var colors: ColorCollection
public var paragraphStyles: ParagraphStyleCollection
public var listItemOptions: ListItemOptions
public var quoteStripeOptions: QuoteStripeOptions
public var thematicBreakOptions: ThematicBreakOptions
public var codeBlockOptions: CodeBlockOptions
// MARK: - Life cycle
public init(fonts: FontCollection = StaticFontCollection(),
colors: ColorCollection = StaticColorCollection(),
paragraphStyles: ParagraphStyleCollection = StaticParagraphStyleCollection(),
listItemOptions: ListItemOptions = ListItemOptions(),
quoteStripeOptions: QuoteStripeOptions = QuoteStripeOptions(),
thematicBreakOptions: ThematicBreakOptions = ThematicBreakOptions(),
codeBlockOptions: CodeBlockOptions = CodeBlockOptions()
) {
self.fonts = fonts
self.colors = colors
self.paragraphStyles = paragraphStyles
self.listItemOptions = listItemOptions
self.quoteStripeOptions = quoteStripeOptions
self.thematicBreakOptions = thematicBreakOptions
self.codeBlockOptions = codeBlockOptions
}
}
#endif
@@ -0,0 +1,189 @@
//
// Styler.swift
// Down
//
// Created by John Nguyen on 13.04.19.
// Copyright © 2016-2019 Down. All rights reserved.
//
import Foundation
/// A styler is an object that manipulates the appearance of attributed strings generated
/// for each particular markdown node. The attributed string passed into each method is
/// mutable, so new attributes can be added and/or existing attributes modified or removed.
///
/// When applying paragraph styles to a string, take care not to cause any conflicts with
/// existing paragraph styles, as this can lead to visual bugs that are difficult to
/// understand.
///
/// A styler is used in conjunction with an instance of `AttributedStringVisitor` in order
/// to generate an NSAttributedString from an abstract syntax tree.
public protocol Styler {
/// Styles the content of the document in the given string.
///
/// - Parameters:
/// - str: the document content.
func style(document str: NSMutableAttributedString)
/// Styles the content of the block quote contained in the given string.
///
/// - Parameters:
/// - str: the quote content.
/// - nestDepth: the zero indexed nesting depth of the block quote node.
func style(blockQuote str: NSMutableAttributedString, nestDepth: Int)
/// Styles the content of the list contained in the given string.
///
/// - Parameters:
/// - str: the list content.
/// - nestDepth: the zero indexed nesting depth of the list node.
func style(list str: NSMutableAttributedString, nestDepth: Int)
/// Styles the number or bullet list item prefix.
///
/// - Parameters:
/// - str: the list item prefix.
func style(listItemPrefix str: NSMutableAttributedString)
/// Styles the content of the list item contained in the given string, including the
/// number or bullet prefix.
///
/// - Parameters:
/// - str: the item content.
/// - prefixLength: the character length of the number or bullet prefix.
func style(item str: NSMutableAttributedString, prefixLength: Int)
/// Styles the content of the code block in the given string.
///
/// An example use case for `fenceInfo` is to specify a programming language name,
/// which could be used to support syntax highlighting.
///
/// - Parameters:
/// - str: the code content.
/// - fenceInfo: the string that trails the initial \`\`\` ticks.
func style(codeBlock str: NSMutableAttributedString, fenceInfo: String?)
/// Styles the content of the html block contained in the given string.
///
/// - Parameters:
/// - str: the html content.
func style(htmlBlock str: NSMutableAttributedString)
/// Styles the content of the custom block contained in the given string.
///
/// - Parameters:
/// - str: the content.
func style(customBlock str: NSMutableAttributedString)
/// Styles the content of the paragraph in the given string.
///
/// - Parameters:
/// - str: the paragraph content.
func style(paragraph str: NSMutableAttributedString)
/// Styles the content of the heading in the given string.
///
/// - Parameters:
/// - str: the heading content.
/// - level: the heading level [1, 6]
func style(heading str: NSMutableAttributedString, level: Int)
/// Styles the content of the thematic break in the given string.
///
/// - Parameters:
/// - str: the thematic break.
func style(thematicBreak str: NSMutableAttributedString)
/// Styles the content of the inline text node in the given string.
///
/// The text nodes are always the leaves of the AST, thus they
/// contain the base style upon which other nodes can work with.
///
/// - Parameters:
/// - str: the text content.
func style(text str: NSMutableAttributedString)
/// Styles the content of the soft break in the given string.
///
/// - Parameters:
/// - str: the soft break.
func style(softBreak str: NSMutableAttributedString)
/// Styles the content of the line break in the given string.
///
/// - Parameters:
/// - str: the line break.
func style(lineBreak str: NSMutableAttributedString)
/// Styles the content of the inline code in the given string.
///
/// - Parameters:
/// - str: the code content.
func style(code str: NSMutableAttributedString)
/// Styles the content of the inline html tags in the given string.
///
/// Note, the content does not include text between matching tags.
///
/// - Parameters:
/// - str: the html content.
func style(htmlInline str: NSMutableAttributedString)
/// Styles the content of the inline custom node in the given string.
///
/// - Parameters:
/// - str: the custom content.
func style(customInline str: NSMutableAttributedString)
/// Styles the content of the inline emphasis node in the given string.
///
/// - Parameters:
/// - str: the ephasized content.
func style(emphasis str: NSMutableAttributedString)
/// Styles the content of the inline strong node in the given string.
///
/// - Parameters:
/// - str: the strong content.
func style(strong str: NSMutableAttributedString)
/// Styles the content of the inline link node in the given string.
///
/// - Parameters:
/// - str: the link content.
/// - title: the link title.
/// - url: the linked url.
func style(link str: NSMutableAttributedString, title: String?, url: String?)
/// Styles the content of the inline image node in the given string.
///
/// - Parameters:
/// - str: the link content.
/// - title: the link title.
/// - url: the linked url.
func style(image str: NSMutableAttributedString, title: String?, url: String?)
}
@@ -0,0 +1,39 @@
//
// DownDebugTextView.swift
// Down
//
// Created by John Nguyen on 06.08.19.
// Copyright © 2016-2019 Down. All rights reserved.
//
#if !os(watchOS) && !os(Linux)
#if canImport(UIKit)
import UIKit
#elseif canImport(AppKit)
import AppKit
#endif
/// A text view capable of parsing and rendering markdown via the AST, as well as line fragments.
///
/// See `DownDebugLayoutManager`.
public class DownDebugTextView: DownTextView {
// MARK: - Life cycle
public init(frame: CGRect, styler: Styler = DownStyler()) {
super.init(frame: frame, styler: styler, layoutManager: DownDebugLayoutManager())
}
required public init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
#endif
@@ -0,0 +1,100 @@
//
// DownTextView.swift
// Down
//
// Created by John Nguyen on 03.08.19.
// Copyright © 2016-2019 Down. All rights reserved.
//
#if !os(watchOS) && !os(Linux)
#if canImport(UIKit)
import UIKit
public typealias TextView = UITextView
#elseif canImport(AppKit)
import AppKit
public typealias TextView = NSTextView
#endif
/// A text view capable of parsing and rendering markdown via the AST.
open class DownTextView: TextView {
// MARK: - Properties
open var styler: Styler {
didSet {
try? render()
}
}
#if canImport(UIKit)
open override var text: String! {
didSet {
guard oldValue != text else { return }
try? render()
}
}
#elseif canImport(AppKit)
open override var string: String {
didSet {
guard oldValue != string else { return }
try? render()
}
}
#endif
// MARK: - Life cycle
public convenience init(frame: CGRect, styler: Styler = DownStyler()) {
self.init(frame: frame, styler: styler, layoutManager: DownLayoutManager())
}
public init(frame: CGRect, styler: Styler, layoutManager: NSLayoutManager) {
self.styler = styler
let textStorage = NSTextStorage()
let textContainer = NSTextContainer()
textStorage.addLayoutManager(layoutManager)
layoutManager.addTextContainer(textContainer)
super.init(frame: frame, textContainer: textContainer)
// We don't want the text view to overwrite link attributes set
// by the styler.
linkTextAttributes = [:]
}
required public init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
// MARK: - Methods
open func render() throws {
#if canImport(UIKit)
let down = Down(markdownString: text)
let markdown = try down.toAttributedString(styler: styler)
attributedText = markdown
#elseif canImport(AppKit)
guard let textStorage = textStorage else { return }
let down = Down(markdownString: string)
let markdown = try down.toAttributedString(styler: styler)
textStorage.replaceCharacters(in: textStorage.wholeRange, with: markdown)
#endif
}
}
#endif
@@ -0,0 +1,249 @@
//
// AttributedStringVisitor.swift
// Down
//
// Created by John Nguyen on 09.04.19.
//
#if !os(Linux)
import Foundation
/// This class is used to generated an `NSMutableAttributedString` from the abstract syntax
/// tree produced by a markdown string. It traverses the tree to construct substrings
/// represented at each node and uses an instance of `Styler` to apply the visual attributes.
/// These substrings are joined together to produce the final result.
public typealias ListPrefixGeneratorBuilder = (List) -> ListItemPrefixGenerator
public class AttributedStringVisitor {
// MARK: - Properties
private let styler: Styler
private let options: DownOptions
private let listPrefixGeneratorBuilder: ListPrefixGeneratorBuilder
private var listPrefixGenerators = [ListItemPrefixGenerator]()
/// Creates a new instance with the given styler and options.
///
/// - parameters:
/// - styler: used to style the markdown elements.
/// - options: may be used to modify rendering.
/// - listPrefixGeneratorBuilder: may be used to modify list prefixes.
public init(
styler: Styler,
options: DownOptions = .default,
listPrefixGeneratorBuilder: @escaping ListPrefixGeneratorBuilder = { StaticListItemPrefixGenerator(list: $0) }
) {
self.styler = styler
self.options = options
self.listPrefixGeneratorBuilder = listPrefixGeneratorBuilder
}
}
extension AttributedStringVisitor: Visitor {
public typealias Result = NSMutableAttributedString
public func visit(document node: Document) -> NSMutableAttributedString {
let result = visitChildren(of: node).joined
styler.style(document: result)
return result
}
public func visit(blockQuote node: BlockQuote) -> NSMutableAttributedString {
let result = visitChildren(of: node).joined
if node.hasSuccessor { result.append(.paragraphSeparator) }
styler.style(blockQuote: result, nestDepth: node.nestDepth)
return result
}
public func visit(list node: List) -> NSMutableAttributedString {
listPrefixGenerators.append(listPrefixGeneratorBuilder(node))
defer { listPrefixGenerators.removeLast() }
let items = visitChildren(of: node)
let result = items.joined
if node.hasSuccessor { result.append(.paragraphSeparator) }
styler.style(list: result, nestDepth: node.nestDepth)
return result
}
public func visit(item node: Item) -> NSMutableAttributedString {
let result = visitChildren(of: node).joined
let prefix = listPrefixGenerators.last?.next() ?? ""
let attributedPrefix = "\(prefix)\t".attributed
styler.style(listItemPrefix: attributedPrefix)
result.insert(attributedPrefix, at: 0)
if node.hasSuccessor { result.append(.paragraphSeparator) }
styler.style(item: result, prefixLength: (prefix as NSString).length)
return result
}
public func visit(codeBlock node: CodeBlock) -> NSMutableAttributedString {
guard let literal = node.literal else { return .empty }
let result = literal.replacingNewlinesWithLineSeparators().attributed
if node.hasSuccessor { result.append(.paragraphSeparator) }
styler.style(codeBlock: result, fenceInfo: node.fenceInfo)
return result
}
public func visit(htmlBlock node: HtmlBlock) -> NSMutableAttributedString {
guard let literal = node.literal else { return .empty }
let result = literal.replacingNewlinesWithLineSeparators().attributed
if node.hasSuccessor { result.append(.paragraphSeparator) }
styler.style(htmlBlock: result)
return result
}
public func visit(customBlock node: CustomBlock) -> NSMutableAttributedString {
guard let result = node.literal?.attributed else { return .empty }
styler.style(customBlock: result)
return result
}
public func visit(paragraph node: Paragraph) -> NSMutableAttributedString {
let result = visitChildren(of: node).joined
if node.hasSuccessor { result.append(.paragraphSeparator) }
styler.style(paragraph: result)
return result
}
public func visit(heading node: Heading) -> NSMutableAttributedString {
let result = visitChildren(of: node).joined
if node.hasSuccessor { result.append(.paragraphSeparator) }
styler.style(heading: result, level: node.headingLevel)
return result
}
public func visit(thematicBreak node: ThematicBreak) -> NSMutableAttributedString {
let result = "\(String.zeroWidthSpace)\n".attributed
styler.style(thematicBreak: result)
return result
}
public func visit(text node: Text) -> NSMutableAttributedString {
guard let result = node.literal?.attributed else { return .empty }
styler.style(text: result)
return result
}
public func visit(softBreak node: SoftBreak) -> NSMutableAttributedString {
let result = (options.contains(.hardBreaks) ? String.lineSeparator : " ").attributed
styler.style(softBreak: result)
return result
}
public func visit(lineBreak node: LineBreak) -> NSMutableAttributedString {
let result = String.lineSeparator.attributed
styler.style(lineBreak: result)
return result
}
public func visit(code node: Code) -> NSMutableAttributedString {
guard let result = node.literal?.attributed else { return .empty }
styler.style(code: result)
return result
}
public func visit(htmlInline node: HtmlInline) -> NSMutableAttributedString {
guard let result = node.literal?.attributed else { return .empty }
styler.style(htmlInline: result)
return result
}
public func visit(customInline node: CustomInline) -> NSMutableAttributedString {
guard let result = node.literal?.attributed else { return .empty }
styler.style(customInline: result)
return result
}
public func visit(emphasis node: Emphasis) -> NSMutableAttributedString {
let result = visitChildren(of: node).joined
styler.style(emphasis: result)
return result
}
public func visit(strong node: Strong) -> NSMutableAttributedString {
let result = visitChildren(of: node).joined
styler.style(strong: result)
return result
}
public func visit(link node: Link) -> NSMutableAttributedString {
let result = visitChildren(of: node).joined
styler.style(link: result, title: node.title, url: node.url)
return result
}
public func visit(image node: Image) -> NSMutableAttributedString {
let result = visitChildren(of: node).joined
styler.style(image: result, title: node.title, url: node.url)
return result
}
}
// MARK: - Helper extensions
private extension Sequence where Iterator.Element == NSMutableAttributedString {
var joined: NSMutableAttributedString {
return reduce(into: NSMutableAttributedString()) { $0.append($1) }
}
}
private extension NSMutableAttributedString {
static var empty: NSMutableAttributedString {
return "".attributed
}
}
private extension NSAttributedString {
static var paragraphSeparator: NSAttributedString {
return String.paragraphSeparator.attributed
}
}
private extension String {
var attributed: NSMutableAttributedString {
return NSMutableAttributedString(string: self)
}
// This codepoint marks the end of a paragraph and the start of the next.
static var paragraphSeparator: String {
return "\u{2029}"
}
// This code point allows line breaking, without starting a new paragraph.
static var lineSeparator: String {
return "\u{2028}"
}
static var zeroWidthSpace: String {
return "\u{200B}"
}
func replacingNewlinesWithLineSeparators() -> String {
let trimmed = trimmingCharacters(in: .newlines)
let lines = trimmed.components(separatedBy: .newlines)
return lines.joined(separator: .lineSeparator)
}
}
#endif // !os(Linux)
@@ -0,0 +1,125 @@
//
// DebugVisitor.swift
// Down
//
// Created by John Nguyen on 09.04.19.
//
import Foundation
/// This visitor will generate the debug description of an entire abstract syntax tree,
/// indicating relationships between nodes with indentation.
public class DebugVisitor: Visitor {
// MARK: - Properties
private var depth = 0
private var indent: String {
return String(repeating: " ", count: depth)
}
// MARK: - Life cycle
public init() {}
// MARK: - Helpers
private func report(_ node: Node) -> String {
return "\(indent)\(node is Document ? "" : "")\(String(reflecting: node))\n"
}
private func reportWithChildren(_ node: Node) -> String {
let thisNode = report(node)
depth += 1
let children = visitChildren(of: node).joined()
depth -= 1
return "\(thisNode)\(children)"
}
// MARK: - Visitor
public typealias Result = String
public func visit(document node: Document) -> String {
return reportWithChildren(node)
}
public func visit(blockQuote node: BlockQuote) -> String {
return reportWithChildren(node)
}
public func visit(list node: List) -> String {
return reportWithChildren(node)
}
public func visit(item node: Item) -> String {
return reportWithChildren(node)
}
public func visit(codeBlock node: CodeBlock) -> String {
return reportWithChildren(node)
}
public func visit(htmlBlock node: HtmlBlock) -> String {
return reportWithChildren(node)
}
public func visit(customBlock node: CustomBlock) -> String {
return reportWithChildren(node)
}
public func visit(paragraph node: Paragraph) -> String {
return reportWithChildren(node)
}
public func visit(heading node: Heading) -> String {
return reportWithChildren(node)
}
public func visit(thematicBreak node: ThematicBreak) -> String {
return report(node)
}
public func visit(text node: Text) -> String {
return report(node)
}
public func visit(softBreak node: SoftBreak) -> String {
return report(node)
}
public func visit(lineBreak node: LineBreak) -> String {
return report(node)
}
public func visit(code node: Code) -> String {
return report(node)
}
public func visit(htmlInline node: HtmlInline) -> String {
return report(node)
}
public func visit(customInline node: CustomInline) -> String {
return report(node)
}
public func visit(emphasis node: Emphasis) -> String {
return reportWithChildren(node)
}
public func visit(strong node: Strong) -> String {
return reportWithChildren(node)
}
public func visit(link node: Link) -> String {
return reportWithChildren(node)
}
public func visit(image node: Image) -> String {
return reportWithChildren(node)
}
}
@@ -0,0 +1,54 @@
//
// ListItemPrefixGenerator.swift
// Down
//
// Created by John Nguyen on 23.06.19.
// Copyright © 2016-2019 Down. All rights reserved.
//
import Foundation
/// A ListItemPrefixGenerator is an object used to generate list item prefix.
public protocol ListItemPrefixGenerator {
init(listType: List.ListType, numberOfItems: Int, nestDepth: Int)
func next() -> String?
}
public extension ListItemPrefixGenerator {
init(list: List) {
self.init(listType: list.listType, numberOfItems: list.numberOfItems, nestDepth: list.nestDepth)
}
}
/// Default implementation of `ListItemPrefixGenerator`.
/// Generating the following symbol based on `List.ListType`:
/// - List.ListType is bullet => ""
/// - List.ListType is ordered => "X." (where is the item number)
public class StaticListItemPrefixGenerator: ListItemPrefixGenerator {
// MARK: - Properties
private var prefixes: IndexingIterator<[String]>
// MARK: - Life cycle
required public init(listType: List.ListType, numberOfItems: Int, nestDepth: Int) {
switch listType {
case .bullet:
prefixes = [String](repeating: "", count: numberOfItems)
.makeIterator()
case .ordered(let start):
prefixes = (start..<(start + numberOfItems))
.map { "\($0)." }
.makeIterator()
}
}
// MARK: - Methods
public func next() -> String? {
prefixes.next()
}
}
+75
View File
@@ -0,0 +1,75 @@
//
// Vistor.swift
// Down
//
// Created by John Nguyen on 07.04.19.
//
import Foundation
/// Visitor describes a type that is able to traverse the abstract syntax tree. It visits
/// each node of the tree and produces some result for that node. A visitor is "accepted" by
/// the root node (of type `Document`), which will start the traversal by first invoking
/// `visit(document:)`.
public protocol Visitor {
associatedtype Result
func visit(document node: Document) -> Result
func visit(blockQuote node: BlockQuote) -> Result
func visit(list node: List) -> Result
func visit(item node: Item) -> Result
func visit(codeBlock node: CodeBlock) -> Result
func visit(htmlBlock node: HtmlBlock) -> Result
func visit(customBlock node: CustomBlock) -> Result
func visit(paragraph node: Paragraph) -> Result
func visit(heading node: Heading) -> Result
func visit(thematicBreak node: ThematicBreak) -> Result
func visit(text node: Text) -> Result
func visit(softBreak node: SoftBreak) -> Result
func visit(lineBreak node: LineBreak) -> Result
func visit(code node: Code) -> Result
func visit(htmlInline node: HtmlInline) -> Result
func visit(customInline node: CustomInline) -> Result
func visit(emphasis node: Emphasis) -> Result
func visit(strong node: Strong) -> Result
func visit(link node: Link) -> Result
func visit(image node: Image) -> Result
func visitChildren(of node: Node) -> [Result]
}
extension Visitor {
public func visitChildren(of node: Node) -> [Result] {
return node.childSequence.compactMap { child in
switch child {
case let child as Document: return visit(document: child)
case let child as BlockQuote: return visit(blockQuote: child)
case let child as List: return visit(list: child)
case let child as Item: return visit(item: child)
case let child as CodeBlock: return visit(codeBlock: child)
case let child as HtmlBlock: return visit(htmlBlock: child)
case let child as CustomBlock: return visit(customBlock: child)
case let child as Paragraph: return visit(paragraph: child)
case let child as Heading: return visit(heading: child)
case let child as ThematicBreak: return visit(thematicBreak: child)
case let child as Text: return visit(text: child)
case let child as SoftBreak: return visit(softBreak: child)
case let child as LineBreak: return visit(lineBreak: child)
case let child as Code: return visit(code: child)
case let child as HtmlInline: return visit(htmlInline: child)
case let child as CustomInline: return visit(customInline: child)
case let child as Emphasis: return visit(emphasis: child)
case let child as Strong: return visit(strong: child)
case let child as Link: return visit(link: child)
case let child as Image: return visit(image: child)
default:
assertionFailure("Unexpected child")
return nil
}
}
}
}
+1 -1
View File
@@ -3,7 +3,7 @@
// Down
//
// Created by Rob Phillips on 6/1/16.
// Copyright © 2016 Glazed Donut, LLC. All rights reserved.
// Copyright © 2016-2019 Down. All rights reserved.
//
@import Foundation;
+27
View File
@@ -0,0 +1,27 @@
//
// Down.swift
// Down
//
// Created by Rob Phillips on 5/28/16.
// Copyright © 2016-2019 Down. All rights reserved.
//
import Foundation
public struct Down: DownASTRenderable, DownHTMLRenderable, DownXMLRenderable,
DownLaTeXRenderable, DownGroffRenderable, DownCommonMarkRenderable {
/// A string containing CommonMark Markdown
public var markdownString: String
/// Initializes the container with a CommonMark Markdown string which can then be
/// rendered depending on protocol conformance.
///
/// - Parameter markdownString: A string containing CommonMark Markdown
public init(markdownString: String) {
self.markdownString = markdownString
}
}
#if !os(Linux)
extension Down: DownAttributedStringRenderable { }
#endif // !os(Linux)
@@ -0,0 +1,36 @@
//
// DownErrors.swift
// Down
//
// Created by Rob Phillips on 5/28/16.
// Copyright © 2016-2019 Down. All rights reserved.
//
import Foundation
public enum DownErrors: Error {
/// Thrown when there was an issue converting the Markdown into an abstract syntax tree.
case markdownToASTError
/// Thrown when the abstract syntax tree could not be rendered into another format.
case astRenderingError
/// Thrown when an HTML string cannot be converted into an `NSData` representation.
case htmlDataConversionError
#if os(macOS)
/// Thrown when a custom template bundle has a non-standard bundle format.
///
/// Specifically, the file URL of the bundles subdirectory containing resource files could
/// not be found (i.e. the bundle's `resourceURL` property is nil).
case nonStandardBundleFormatError
#endif
}
@@ -0,0 +1,78 @@
//
// DownOptions.swift
// Down
//
// Created by Rob Phillips on 5/28/16.
// Copyright © 2016-2019 Down. All rights reserved.
//
import Foundation
import libcmark
public struct DownOptions: OptionSet {
// MARK: - Properties
public let rawValue: Int32
// MARK: - Life cycle
public init(rawValue: Int32) { self.rawValue = rawValue }
/// Default options.
public static let `default` = DownOptions(rawValue: CMARK_OPT_DEFAULT)
// MARK: - Rendering Options
/// Include a `data-sourcepos` attribute on all block elements.
public static let sourcePos = DownOptions(rawValue: CMARK_OPT_SOURCEPOS)
/// Render `softbreak` elements as hard line breaks.
public static let hardBreaks = DownOptions(rawValue: CMARK_OPT_HARDBREAKS)
/// Suppress raw HTML and unsafe links (`javascript:`, `vbscript:`,
/// `file:`, and `data:`, except for `image/png`, `image/gif`,
/// `image/jpeg`, or `image/webp` mime types). Raw HTML is replaced
/// by a placeholder HTML comment. Unsafe links are replaced by
/// empty strings.
///
/// Note: this is the default option as of cmark v0.29.0. Use `unsafe`
/// to disable this behavior.
public static let safe = DownOptions(rawValue: CMARK_OPT_SAFE)
/// Render raw HTML and unsafe links (`javascript:`, `vbscript:`,
/// `file:`, and `data:`, except for `image/png`, `image/gif`,
/// `image/jpeg`, or `image/webp` mime types). By default,
/// raw HTML is replaced by a placeholder HTML comment. Unsafe
/// links are replaced by empty strings.
///
/// Note: `safe` is the default as of cmark v0.29.0
public static let unsafe = DownOptions(rawValue: CMARK_OPT_UNSAFE)
// MARK: - Parsing Options
/// Normalize tree by consolidating adjacent text nodes.
public static let normalize = DownOptions(rawValue: CMARK_OPT_NORMALIZE)
/// Validate UTF-8 in the input before parsing, replacing illegal
/// sequences with the replacement character U+FFFD.
public static let validateUTF8 = DownOptions(rawValue: CMARK_OPT_VALIDATE_UTF8)
/// Convert straight quotes to curly, --- to em dashes, -- to en dashes.
public static let smart = DownOptions(rawValue: CMARK_OPT_SMART)
// MARK: - Combo Options
/// Combines 'unsafe' and 'smart' to render raw HTML and produce smart typography.
public static let smartUnsafe = DownOptions(rawValue: CMARK_OPT_SMART + CMARK_OPT_UNSAFE)
}
@@ -3,27 +3,31 @@
// Down
//
// Created by Rob Phillips on 6/1/16.
// Copyright © 2016 Glazed Donut, LLC. All rights reserved.
// Copyright © 2016-2019 Down. All rights reserved.
//
#if os(macOS)
import AppKit
#else
import UIKit
#endif
#if !os(Linux)
#if os(macOS)
import AppKit
#else
import UIKit
#endif
extension NSAttributedString {
/**
Instantiates an attributed string with the given HTML string
/// Instantiates an attributed string with the given HTML string
///
/// - Parameters:
/// - htmlString: An HTML string.
///
/// - Throws:
/// `HTMLDataConversionError` or an instantiation error.
- parameter htmlString: An HTML string
- throws: `HTMLDataConversionError` or an instantiation error
- returns: An attributed string
*/
convenience init(htmlString: String) throws {
guard let data = htmlString.data(using: String.Encoding.utf8) else {
throw DownErrors.htmlDataConversionError
@@ -33,7 +37,10 @@ extension NSAttributedString {
.documentType: NSAttributedString.DocumentType.html,
.characterEncoding: NSNumber(value: String.Encoding.utf8.rawValue)
]
try self.init(data: data, options: options, documentAttributes: nil)
}
}
#endif // !os(Linux)
@@ -3,7 +3,7 @@
// Down
//
// Created by Rob Phillips on 6/1/16.
// Copyright © 2016 Glazed Donut, LLC. All rights reserved.
// Copyright © 2016-2019 Down. All rights reserved.
//
import Foundation
@@ -11,15 +11,16 @@ import libcmark
extension String {
/**
Generates an HTML string from the contents of the string (self), which should contain CommonMark Markdown
/// Generates an HTML string from the contents of the string (self), which should contain CommonMark Markdown.
///
/// - Parameters:
/// - options: `DownOptions` to modify parsing or rendering, defaulting to `.default`.
/// - Returns:
/// An HTML string.
///
/// - Throws:
/// `DownErrors` depending on the scenario.
- parameter options: `DownOptions` to modify parsing or rendering, defaulting to `.default`
- throws: `DownErrors` depending on the scenario
- returns: HTML string
*/
public func toHTML(_ options: DownOptions = .default) throws -> String {
let ast = try DownASTRenderer.stringToAST(self, options: options)
let html = try DownHTMLRenderer.astToHTML(ast, options: options)
@@ -0,0 +1,88 @@
//
// DownASTRenderable.swift
// Down
//
// Created by Rob Phillips on 5/31/16.
// Copyright © 2016-2019 Down. All rights reserved.
//
import Foundation
import libcmark
public protocol DownASTRenderable: DownRenderable {
func toAST(_ options: DownOptions) throws -> CMarkNode
}
extension DownASTRenderable {
/// Generates an abstract syntax tree from the `markdownString` property.
///
/// - Parametera:
/// - options: `DownOptions` to modify parsing or rendering, defaulting to `.default`.
///
/// - Returns:
/// An abstract syntax tree representation of the Markdown input.
///
/// - Throws:
/// `MarkdownToASTError` if conversion fails.
public func toAST(_ options: DownOptions = .default) throws -> CMarkNode {
return try DownASTRenderer.stringToAST(markdownString, options: options)
}
/// Parses the `markdownString` property into an abstract syntax tree and returns the root `Document` node.
///
/// - Parameters:
/// - options: `DownOptions` to modify parsing or rendering, defaulting to `.default`.
///
/// - Returns:
/// The root Document node for the abstract syntax tree representation of the Markdown input.
///
/// - Throws:
/// `MarkdownToASTError` if conversion fails.
public func toDocument(_ options: DownOptions = .default) throws -> Document {
let tree = try toAST(options)
guard tree.type == CMARK_NODE_DOCUMENT else {
throw DownErrors.astRenderingError
}
return Document(cmarkNode: tree)
}
}
public struct DownASTRenderer {
/// Generates an abstract syntax tree from the given CommonMark Markdown string.
///
/// **Important:** It is the caller's responsibility to call `cmark_node_free(ast)` on the returned value.
///
/// - Parameters:
/// - string: A string containing CommonMark Markdown.
/// - options: `DownOptions` to modify parsing or rendering, defaulting to `.default`.
///
/// - Returns:
/// An abstract syntax tree representation of the Markdown input.
///
/// - Throws:
/// `MarkdownToASTError` if conversion fails.
public static func stringToAST(_ string: String, options: DownOptions = .default) throws -> CMarkNode {
var tree: CMarkNode?
string.withCString {
let stringLength = Int(strlen($0))
tree = cmark_parse_document($0, stringLength, options.rawValue)
}
guard let ast = tree else {
throw DownErrors.markdownToASTError
}
return ast
}
}

Some files were not shown because too many files have changed in this diff Show More