diff --git a/Source/Views/DownView.swift b/Source/Views/DownView.swift
index 4b95eef5..e570ab57 100644
--- a/Source/Views/DownView.swift
+++ b/Source/Views/DownView.swift
@@ -28,10 +28,12 @@ open class DownView: WKWebView {
/// - configuration: Optional custom web view configuration.
/// - options: `DownOptions` to modify parsing or rendering, defaulting to `.default`
/// - didLoadSuccessfully: Optional callback for when the web content has loaded successfully
+ /// - writableBundle: Whether or not the bundle folder is writable.
/// - Throws: `DownErrors` depending on the scenario
- public init(frame: CGRect, markdownString: String, openLinksInBrowser: Bool = true, templateBundle: Bundle? = nil, configuration: WKWebViewConfiguration? = nil, options: DownOptions = .default, didLoadSuccessfully: DownViewClosure? = nil) throws {
+ public init(frame: CGRect, markdownString: String, openLinksInBrowser: Bool = true, templateBundle: Bundle? = nil, writableBundle: Bool = false, configuration: WKWebViewConfiguration? = nil, options: DownOptions = .default, didLoadSuccessfully: DownViewClosure? = nil) throws {
self.options = options
self.didLoadSuccessfully = didLoadSuccessfully
+ self.writableBundle = writableBundle
if let templateBundle = templateBundle {
self.bundle = templateBundle
@@ -86,6 +88,7 @@ open class DownView: WKWebView {
// MARK: - Private Properties
let bundle: Bundle
+ let writableBundle: Bool
var options: DownOptions
private lazy var baseURL: URL = {
@@ -113,7 +116,12 @@ private extension DownView {
let pageHTMLString = try htmlFromTemplate(htmlString)
#if os(iOS)
- loadHTMLString(pageHTMLString, baseURL: baseURL)
+ if writableBundle {
+ let newIndexUrl = try writeTempIndexFile(pageHTMLString: pageHTMLString)
+ loadFileURL(newIndexUrl, allowingReadAccessTo: newIndexUrl.deletingLastPathComponent())
+ } else {
+ loadHTMLString(pageHTMLString, baseURL: baseURL)
+ }
#elseif os(macOS)
let indexURL = try createTemporaryBundle(pageHTMLString: pageHTMLString)
loadFileURL(indexURL, allowingReadAccessTo: indexURL.deletingLastPathComponent())
@@ -125,6 +133,14 @@ private extension DownView {
return template.replacingOccurrences(of: "DOWN_HTML", with: htmlString)
}
+ #if os(iOS)
+ func writeTempIndexFile(pageHTMLString: String) throws -> URL {
+ let newIndexUrl = bundle.resourceURL!.appendingPathComponent("tmp_index.html")
+ try pageHTMLString.write(to: newIndexUrl, atomically: true, encoding: .utf8)
+ return newIndexUrl
+ }
+ #endif
+
#if os(macOS)
func createTemporaryBundle(pageHTMLString: String) throws -> URL {
guard let bundleResourceURL = bundle.resourceURL
diff --git a/Tests/DownViewTests.swift b/Tests/DownViewTests.swift
index 69a4d469..3402ca43 100644
--- a/Tests/DownViewTests.swift
+++ b/Tests/DownViewTests.swift
@@ -97,6 +97,40 @@ class DownViewTests: XCTestCase {
}
}
+ func testInstantiationWithCustomWritableTemplateBundle() {
+ let expect1 = expectation(description: "DownView accepts and loads custom bundle files from a user writable location")
+
+ guard
+ let bundle = Bundle(for: type(of: self)).url(forResource: "TestDownView", withExtension: "bundle"),
+ let templateBundle = Bundle(url: bundle)
+ else {
+ XCTFail("Test template bundle not found in test target!")
+ return
+ }
+
+ let markdownString = """
+```swift
+let x = 1
+```
+"""
+ var downView: DownView?
+ downView = try? DownView(frame: .zero, markdownString: markdownString, templateBundle: templateBundle, writableBundle: true, didLoadSuccessfully: {
+ self._pageContents(for: downView!) { htmlString in
+ XCTAssertTrue(htmlString!.contains("css/down.min.css"))
+ XCTAssertTrue(htmlString!.contains("hljs-keyword"))
+ XCTAssertTrue(htmlString!.contains("But also, custom HTML!"))
+
+ expect1.fulfill()
+ }
+ })
+
+ waitForExpectations(timeout: 10) { (error: Error?) in
+ if let error = error {
+ XCTFail("waitForExpectationsWithTimeout errored: \(error)")
+ }
+ }
+ }
+
func testDownOptions() {
let markdownString = "## [Down](https://github.com/iwasrobbed/Down)\n\nI'm strong!"
let renderedHTML = "I'm strong!"