Skip to content

Commit 2c61b34

Browse files
committed
Support for macOS Monterey and bugfix.
1 parent cf14bda commit 2c61b34

File tree

11 files changed

+376
-173
lines changed

11 files changed

+376
-173
lines changed

CHANGELOG.md

+11
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,17 @@
11
# Changelog
22
=======
33

4+
### 1.0.4 (29)
5+
New features:
6+
- On macOS 12 Monterey, the new lightweight data based preview will be used.
7+
- Addeded more arguments to the CLI tool.
8+
- CLI tool embed inline images handle also raw HTML fragments.
9+
Bugfix:
10+
- Handle markdown associated only to a dynamic UTI.
11+
- Fixed issue with instantiated and never released `Markdown QL Extension Web Content` process for each file previewed.
12+
- On macOS 12 Monterey now you can scroll the preview with the scrollbars.
13+
- On macOS 12 Monterey the bug of trackpad scrolling in fullscreen preview has been fixed.
14+
415
### 1.0.3 (28)
516
New features:
617
- Command line interface (CLI) tool.

QLExtension/Info.plist

+3
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
<dict>
2727
<key>NSExtensionAttributes</key>
2828
<dict>
29+
<key>QLIsDataBasedPreview</key>
30+
<true/>
2931
<key>QLSupportedContentTypes</key>
3032
<array>
3133
<string>net.ia.markdown</string>
@@ -34,6 +36,7 @@
3436
<string>org.textbundle.package</string>
3537
<string>com.rstudio.rmarkdown</string>
3638
<string>dyn.ah62d4rv4ge81e5pe</string>
39+
<string>dyn.ah62d4rv4ge8043a</string>
3740
</array>
3841
<key>QLSupportsSearchableItems</key>
3942
<false/>

QLExtension/PreviewViewController.swift

+48-84
Original file line numberDiff line numberDiff line change
@@ -54,12 +54,14 @@ class PreviewViewController: NSViewController, QLPreviewingController {
5454
}
5555

5656
override func viewDidDisappear() {
57+
// This code will not be called on macOS 12 Monterey with QLIsDataBasedPreview set.
58+
5759
self.launcherService = nil
58-
// Releases the script handler which retain a strong reference to self which prevents the WebKit process from being released.
59-
self.webView.configuration.userContentController.removeScriptMessageHandler(forName: "imageExtensionHandler")
6060
}
6161

6262
override func loadView() {
63+
// This code will not be called on macOS 12 Monterey with QLIsDataBasedPreview set.
64+
6365
super.loadView()
6466
// Do any additional setup after loading the view.
6567

@@ -109,9 +111,6 @@ class PreviewViewController: NSViewController, QLPreviewingController {
109111
configuration.preferences.javaScriptEnabled = settings.unsafeHTMLOption && settings.inlineImageExtension
110112
configuration.allowsAirPlayForMediaPlayback = false
111113

112-
// Handler to replace raw <image> src with the embedded data.
113-
configuration.userContentController.add(self, name: "imageExtensionHandler")
114-
115114
self.webView = MyWKWebView(frame: previewRect, configuration: configuration)
116115
self.webView.autoresizingMask = [.height, .width]
117116

@@ -167,6 +166,7 @@ class PreviewViewController: NSViewController, QLPreviewingController {
167166
*/
168167

169168
func preparePreviewOfFile(at url: URL, completionHandler handler: @escaping (Error?) -> Void) {
169+
// This code will not be called on macOS 12 Monterey with QLIsDataBasedPreview set.
170170

171171
// Add the supported content types to the QLSupportedContentTypes array in the Info.plist of the extension.
172172

@@ -175,6 +175,44 @@ class PreviewViewController: NSViewController, QLPreviewingController {
175175
// Call the completion handler so Quick Look knows that the preview is fully loaded.
176176
// Quick Look will display a loading spinner while the completion handler is not called.
177177

178+
do {
179+
self.handler = handler
180+
181+
let html = try renderMD(url: url)
182+
/*
183+
if #available(macOS 11, *) {
184+
self.webView.mainFrame.loadHTMLString(html, baseURL: nil)
185+
} else {
186+
*/
187+
self.webView.isHidden = true // hide the webview until complete rendering
188+
self.webView.loadHTMLString(html, baseURL: url.deletingLastPathComponent())
189+
/* } */
190+
} catch {
191+
handler(error)
192+
}
193+
}
194+
195+
@available(macOSApplicationExtension 12.0, *)
196+
func providePreview(for request: QLFilePreviewRequest, completionHandler handler: @escaping (QLPreviewReply?, Error?) -> Void) {
197+
// This code will be called on macOS 12 Monterey with QLIsDataBasedPreview set.
198+
199+
// print("providePreview for \(request.fileURL)")
200+
201+
do {
202+
let html = try renderMD(url: request.fileURL)
203+
let replay = QLPreviewReply(dataOfContentType: .html, contentSize: .zero) { _ in
204+
return html.data(using: .utf8)!
205+
}
206+
207+
// replay.title = request.fileURL.lastPathComponent
208+
replay.stringEncoding = .utf8
209+
handler(replay, nil)
210+
} catch {
211+
handler(nil, error)
212+
}
213+
}
214+
215+
func renderMD(url: URL) throws -> String {
178216
os_log(
179217
"Generating preview for file %{public}s",
180218
log: self.log,
@@ -184,8 +222,6 @@ class PreviewViewController: NSViewController, QLPreviewingController {
184222

185223
let type = UserDefaults.standard.string(forKey: "AppleInterfaceStyle") ?? "Light"
186224

187-
self.handler = handler
188-
189225
let settings = Settings.shared
190226

191227
let markdown_url: URL
@@ -199,27 +235,11 @@ class PreviewViewController: NSViewController, QLPreviewingController {
199235
markdown_url = url
200236
}
201237

202-
do {
203-
let text = try settings.render(file: markdown_url, forAppearance: type == "Light" ? .light : .dark, baseDir: markdown_url.deletingLastPathComponent().path, log: self.log)
238+
let text = try settings.render(file: markdown_url, forAppearance: type == "Light" ? .light : .dark, baseDir: markdown_url.deletingLastPathComponent().path, log: self.log)
239+
240+
let html = settings.getCompleteHTML(title: url.lastPathComponent, body: text, footer: "", basedir: url.deletingLastPathComponent())
204241

205-
let extrajs: String
206-
if settings.unsafeHTMLOption && settings.inlineImageExtension {
207-
extrajs = "<script type=\"text/javascript\">" + (settings.getBundleContents(forResource: "inlineimages", ofType: "js") ?? "") + "</script>\n";
208-
} else {
209-
extrajs = ""
210-
}
211-
let html = settings.getCompleteHTML(title: url.lastPathComponent, body: text, footer: extrajs)
212-
/*
213-
if #available(macOS 11, *) {
214-
self.webView.mainFrame.loadHTMLString(html, baseURL: nil)
215-
} else {
216-
*/
217-
self.webView.isHidden = true // hide the webview until complete rendering
218-
self.webView.loadHTMLString(html, baseURL: url.deletingLastPathComponent())
219-
/* } */
220-
} catch {
221-
handler(error)
222-
}
242+
return html
223243
}
224244
}
225245

@@ -239,69 +259,13 @@ extension PreviewViewController: WebFrameLoadDelegate {
239259
}
240260
}
241261

242-
extension PreviewViewController: WKScriptMessageHandler {
243-
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
244-
guard message.name == "imageExtensionHandler", Settings.shared.unsafeHTMLOption && Settings.shared.inlineImageExtension else {
245-
return
246-
}
247-
guard let dict = message.body as? [String : AnyObject], let src = dict["src"] as? String, let id = dict["id"] as? String else {
248-
return
249-
}
250-
251-
guard let data = get_base64_image(
252-
src.cString(using: .utf8),
253-
{ (path: UnsafePointer<Int8>?, context: UnsafeMutableRawPointer?) -> UnsafeMutablePointer<Int8>? in
254-
let magic_file = Settings.shared.getResourceBundle().path(forResource: "magic", ofType: "mgc")?.cString(using: .utf8)
255-
256-
let r = magic_get_mime_by_file(path, magic_file)
257-
return r
258-
},
259-
nil
260-
) else {
261-
return
262-
}
263-
defer {
264-
data.deallocate()
265-
}
266-
let response: [String: String] = [
267-
"src": src,
268-
"id": id,
269-
"data": String(cString: data)
270-
]
271-
let encoder = JSONEncoder()
272-
guard let j = try? encoder.encode(response), let js = String(data: j, encoding: .utf8) else {
273-
return
274-
}
275-
276-
message.webView?.evaluateJavaScript("replaceImageSrc(\(js))") { (r, error) in
277-
if let result = r as? Bool, !result {
278-
os_log(
279-
"Unable to replace <img> src %{public}s with the inline data.",
280-
log: self.log,
281-
type: .error,
282-
src
283-
)
284-
}
285-
if let error = error {
286-
os_log(
287-
"Unable to replace <img> src %{public}s with the inline data: %{public}s.",
288-
log: self.log,
289-
type: .error,
290-
src, error.localizedDescription
291-
)
292-
}
293-
}
294-
}
295-
}
296-
297262
extension PreviewViewController: WKNavigationDelegate {
298263
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
299264
if let handler = self.handler {
300-
// Show the Quick Look preview only after the complete rendering (preventing a flickering glitch).
301-
302265
handler(nil)
303266
self.handler = nil
304267
}
268+
// Show the Quick Look preview only after the complete rendering (preventing a flickering glitch).
305269
// Wait to show the webview to prevent a resize glitch.
306270
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
307271
self.webView.isHidden = false

0 commit comments

Comments
 (0)