Skip to content

Commit a38bce2

Browse files
committed
Support for render the markdown source code instead of the formatted output.
1 parent c336438 commit a38bce2

File tree

13 files changed

+239
-99
lines changed

13 files changed

+239
-99
lines changed

CHANGELOG.md

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

4+
5+
### 1.0.7 (32)
6+
New features:
7+
- Support for render the markdown source code instead of the formatted output.
8+
9+
410
### 1.0.6 (31)
511
New features:
612
- Application menu item to install/reveal the CLI tool on `/usr/local/bin` folder.

QLExtension/PreviewViewController.swift

+3-2
Original file line numberDiff line numberDiff line change
@@ -235,9 +235,10 @@ class PreviewViewController: NSViewController, QLPreviewingController {
235235
markdown_url = url
236236
}
237237

238-
let text = try settings.render(file: markdown_url, forAppearance: type == "Light" ? .light : .dark, baseDir: markdown_url.deletingLastPathComponent().path, log: self.log)
238+
let appearance: Appearance = type == "Light" ? .light : .dark
239+
let text = try settings.render(file: markdown_url, forAppearance: appearance, baseDir: markdown_url.deletingLastPathComponent().path, log: self.log)
239240

240-
let html = settings.getCompleteHTML(title: url.lastPathComponent, body: text, footer: "", basedir: url.deletingLastPathComponent())
241+
let html = settings.getCompleteHTML(title: url.lastPathComponent, body: text, footer: "", basedir: url.deletingLastPathComponent(), forAppearance: appearance)
241242

242243
return html
243244
}

QLMarkdown.xcodeproj/project.pbxproj

+8-8
Original file line numberDiff line numberDiff line change
@@ -1426,7 +1426,7 @@
14261426
CODE_SIGN_ENTITLEMENTS = QLExtension/QLExtension.entitlements;
14271427
CODE_SIGN_IDENTITY = "-";
14281428
CODE_SIGN_STYLE = Manual;
1429-
CURRENT_PROJECT_VERSION = 31;
1429+
CURRENT_PROJECT_VERSION = 32;
14301430
DEVELOPMENT_TEAM = "";
14311431
ENABLE_HARDENED_RUNTIME = NO;
14321432
HEADER_SEARCH_PATHS = (
@@ -1447,7 +1447,7 @@
14471447
"$(PROJECT_DIR)/re2",
14481448
);
14491449
MACOSX_DEPLOYMENT_TARGET = 10.15;
1450-
MARKETING_VERSION = 1.0.6;
1450+
MARKETING_VERSION = 1.0.7;
14511451
PRODUCT_BUNDLE_IDENTIFIER = org.sbarex.QLMarkdown.QLExtension;
14521452
PRODUCT_NAME = "$(TARGET_NAME)";
14531453
PROVISIONING_PROFILE_SPECIFIER = "";
@@ -1464,7 +1464,7 @@
14641464
CODE_SIGN_ENTITLEMENTS = QLExtension/QLExtension.entitlements;
14651465
CODE_SIGN_IDENTITY = "-";
14661466
CODE_SIGN_STYLE = Manual;
1467-
CURRENT_PROJECT_VERSION = 31;
1467+
CURRENT_PROJECT_VERSION = 32;
14681468
DEVELOPMENT_TEAM = "";
14691469
ENABLE_HARDENED_RUNTIME = NO;
14701470
HEADER_SEARCH_PATHS = (
@@ -1485,7 +1485,7 @@
14851485
"$(PROJECT_DIR)/re2",
14861486
);
14871487
MACOSX_DEPLOYMENT_TARGET = 10.15;
1488-
MARKETING_VERSION = 1.0.6;
1488+
MARKETING_VERSION = 1.0.7;
14891489
PRODUCT_BUNDLE_IDENTIFIER = org.sbarex.QLMarkdown.QLExtension;
14901490
PRODUCT_NAME = "$(TARGET_NAME)";
14911491
PROVISIONING_PROFILE_SPECIFIER = "";
@@ -1671,7 +1671,7 @@
16711671
CODE_SIGN_IDENTITY = "-";
16721672
CODE_SIGN_STYLE = Manual;
16731673
COMBINE_HIDPI_IMAGES = YES;
1674-
CURRENT_PROJECT_VERSION = 31;
1674+
CURRENT_PROJECT_VERSION = 32;
16751675
DEVELOPMENT_TEAM = "";
16761676
ENABLE_HARDENED_RUNTIME = NO;
16771677
FRAMEWORK_SEARCH_PATHS = (
@@ -1697,7 +1697,7 @@
16971697
"$(PROJECT_DIR)/re2",
16981698
);
16991699
MACOSX_DEPLOYMENT_TARGET = 10.15;
1700-
MARKETING_VERSION = 1.0.6;
1700+
MARKETING_VERSION = 1.0.7;
17011701
PRODUCT_BUNDLE_IDENTIFIER = org.sbarex.QLMarkdown;
17021702
PRODUCT_NAME = "$(TARGET_NAME)";
17031703
PROVISIONING_PROFILE_SPECIFIER = "";
@@ -1718,7 +1718,7 @@
17181718
CODE_SIGN_IDENTITY = "-";
17191719
CODE_SIGN_STYLE = Manual;
17201720
COMBINE_HIDPI_IMAGES = YES;
1721-
CURRENT_PROJECT_VERSION = 31;
1721+
CURRENT_PROJECT_VERSION = 32;
17221722
DEVELOPMENT_TEAM = "";
17231723
ENABLE_HARDENED_RUNTIME = NO;
17241724
FRAMEWORK_SEARCH_PATHS = (
@@ -1744,7 +1744,7 @@
17441744
"$(PROJECT_DIR)/re2",
17451745
);
17461746
MACOSX_DEPLOYMENT_TARGET = 10.15;
1747-
MARKETING_VERSION = 1.0.6;
1747+
MARKETING_VERSION = 1.0.7;
17481748
PRODUCT_BUNDLE_IDENTIFIER = org.sbarex.QLMarkdown;
17491749
PRODUCT_NAME = "$(TARGET_NAME)";
17501750
PROVISIONING_PROFILE_SPECIFIER = "";

QLMarkdown/Base.lproj/Main.storyboard

+65-52
Large diffs are not rendered by default.

QLMarkdown/Settings+ext.swift

+1
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ extension Settings {
5656

5757
defaultsDomain["debug"] = self.debug
5858
defaultsDomain["inline-link"] = openInlineLink
59+
defaultsDomain["render-as-code"] = self.renderAsCode
5960

6061
let file: String
6162
if let url = customCSS {

QLMarkdown/Settings.swift

+124-24
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ class Settings {
7878
@objc var customCSSOverride: Bool = false
7979
@objc var openInlineLink: Bool = false
8080

81+
@objc var renderAsCode: Bool = false
8182
@objc var debug: Bool = false
8283

8384

@@ -250,6 +251,9 @@ class Settings {
250251
if let opt = defaultsDomain["inline-link"] as? Bool {
251252
openInlineLink = opt
252253
}
254+
if let opt = defaultsDomain["render-as-code"] as? Bool {
255+
renderAsCode = opt
256+
}
253257

254258
sanitizeEmojiOption()
255259
}
@@ -307,6 +311,7 @@ class Settings {
307311
self.openInlineLink = s.openInlineLink
308312

309313
self.debug = s.debug
314+
self.renderAsCode = s.renderAsCode
310315

311316
DistributedNotificationCenter.default().post(name: .QLMarkdownSettingsUpdated, object: nil)
312317
}
@@ -445,7 +450,60 @@ class Settings {
445450
return "```yaml\n"+text+"```\n"
446451
}
447452

453+
func renderCode(text: String, forAppearance appearance: Appearance, baseDir: String, log: OSLog? = nil) -> String? {
454+
455+
if let path = getHighlightSupportPath() {
456+
cmark_syntax_highlight_init("\(path)/".cString(using: .utf8))
457+
} else {
458+
if let l = log {
459+
os_log("Unable to found the `highlight` support dir!", log: l, type: .error)
460+
}
461+
}
462+
463+
let theme: String
464+
switch appearance {
465+
case .light:
466+
theme = self.syntaxThemeLight
467+
case .dark:
468+
theme = self.syntaxThemeDark
469+
case .undefined:
470+
let mode = UserDefaults.standard.string(forKey: "AppleInterfaceStyle") ?? "Light"
471+
if mode == "Light" {
472+
theme = self.syntaxThemeLight
473+
} else {
474+
theme = self.syntaxThemeDark
475+
}
476+
}
477+
478+
// Initialize a new generator and clear previous settings.
479+
highlight_init_generator()
480+
481+
highlight_set_print_line_numbers(self.syntaxLineNumbersOption ? 1 : 0)
482+
highlight_set_formatting_mode(Int32(self.syntaxWordWrapOption), Int32(self.syntaxTabsOption))
483+
484+
if !self.syntaxFontFamily.isEmpty {
485+
highlight_set_current_font(self.syntaxFontFamily, self.syntaxFontSize > 0 ? String(format: "%.02f", self.syntaxFontSize) : "1rem") // 1rem is rendered as 1rempt, so it is ignored.
486+
} else {
487+
highlight_set_current_font("ui-monospace, -apple-system, BlinkMacSystemFont, sans-serif", "10");
488+
}
489+
490+
if let s = colorizeCode(text, "md", theme, true, self.syntaxLineNumbersOption) {
491+
defer {
492+
s.deallocate()
493+
}
494+
let code = String(cString: s)
495+
return code
496+
} else {
497+
return nil
498+
}
499+
}
500+
448501
func render(text: String, filename: String, forAppearance appearance: Appearance, baseDir: String, log: OSLog? = nil) throws -> String {
502+
503+
if self.renderAsCode, let code = self.renderCode(text: text, forAppearance: appearance, baseDir: baseDir, log: log) {
504+
return code
505+
}
506+
449507
cmark_gfm_core_extensions_ensure_registered()
450508

451509
var options = CMARK_OPT_DEFAULT
@@ -912,7 +970,8 @@ table.debug td {
912970
}
913971
}
914972

915-
func getCompleteHTML(title: String, body: String, header: String = "", footer: String = "", basedir: URL) -> String {
973+
func getCompleteHTML(title: String, body: String, header: String = "", footer: String = "", basedir: URL, forAppearance appearance: Appearance) -> String {
974+
916975
let css_doc: String
917976
let css_doc_extended: String
918977

@@ -923,40 +982,81 @@ table.debug td {
923982
return "<style type='text/css'>\(css)\n</style>\n"
924983
}
925984

926-
if let css = self.getCustomCSSCode() {
927-
css_doc_extended = formatCSS(css)
928-
if !self.customCSSOverride {
929-
css_doc = formatCSS(getBundleContents(forResource: "default", ofType: "css"))
985+
if !self.renderAsCode {
986+
if let css = self.getCustomCSSCode() {
987+
css_doc_extended = formatCSS(css)
988+
if !self.customCSSOverride {
989+
css_doc = formatCSS(getBundleContents(forResource: "default", ofType: "css"))
990+
} else {
991+
css_doc = ""
992+
}
930993
} else {
931-
css_doc = ""
994+
css_doc_extended = ""
995+
css_doc = formatCSS(getBundleContents(forResource: "default", ofType: "css"))
932996
}
997+
// css_doc = "<style type=\"text/css\">\n\(css_doc)\n</style>\n"
933998
} else {
934999
css_doc_extended = ""
935-
css_doc = formatCSS(getBundleContents(forResource: "default", ofType: "css"))
1000+
css_doc = ""
9361001
}
937-
// css_doc = "<style type=\"text/css\">\n\(css_doc)\n</style>\n"
9381002

9391003
var css_highlight: String = ""
940-
if self.syntaxHighlightExtension, let ext = cmark_find_syntax_extension("syntaxhighlight"), cmark_syntax_extension_highlight_get_rendered_count(ext) > 0 {
1004+
if self.renderAsCode {
1005+
let theme: String
1006+
var background: String = ""
1007+
switch appearance {
1008+
case .light:
1009+
theme = self.syntaxThemeLight
1010+
case .dark:
1011+
theme = self.syntaxThemeDark
1012+
case .undefined:
1013+
let mode = UserDefaults.standard.string(forKey: "AppleInterfaceStyle") ?? "Light"
1014+
if mode == "Light" {
1015+
theme = self.syntaxThemeLight
1016+
} else {
1017+
theme = self.syntaxThemeDark
1018+
}
1019+
}
1020+
var release: ReleaseTheme?
1021+
var exit_code: Int32 = 0
1022+
if let theme = highlight_get_theme2(theme, &exit_code, &release) {
1023+
defer {
1024+
release?(theme)
1025+
}
1026+
if let s = theme.pointee.canvas?.pointee.color {
1027+
background = String(cString: s)
1028+
}
1029+
}
1030+
exit_code = 0
1031+
if let p = highlight_format_style2(&exit_code, background) {
1032+
css_highlight = String(cString: p) + "\npre.hl { white-space: pre; }\n"
1033+
p.deallocate()
1034+
}
1035+
} else if self.syntaxHighlightExtension, let ext = cmark_find_syntax_extension("syntaxhighlight"), cmark_syntax_extension_highlight_get_rendered_count(ext) > 0 {
9411036
let theme = String(cString: cmark_syntax_extension_highlight_get_theme_name(ext))
9421037
if !theme.isEmpty, let p = cmark_syntax_extension_get_style(ext) {
9431038
// Embed the theme style.
944-
let font = self.syntaxFontFamily
9451039
css_highlight = String(cString: p)
946-
if font != "" {
947-
css_highlight += """
948-
:root {
949-
--code-font: "\(font)", -apple-system, Menlo, monospace;
950-
}
951-
""";
952-
}
953-
css_highlight = formatCSS(css_highlight);
954-
p.deallocate();
1040+
p.deallocate()
9551041
}
9561042
}
1043+
if !css_highlight.isEmpty {
1044+
let font = self.syntaxFontFamily
1045+
if font != "" {
1046+
let code = """
1047+
:root {
1048+
--code-font: "\(font)", ui-monospace, -apple-system, Menlo, monospace;
1049+
}
1050+
"""
1051+
css_highlight += code
1052+
}
1053+
css_highlight = formatCSS(css_highlight)
1054+
}
9571055

9581056
let style = css_doc + css_highlight + css_doc_extended
959-
1057+
let wrapper_open = self.renderAsCode ? "<pre class='hl'>" : "<article class='markdown-body'>"
1058+
let wrapper_close = self.renderAsCode ? "</pre>" : "</article>"
1059+
let body_style = self.renderAsCode ? " class='hl'" : ""
9601060
var html =
9611061
"""
9621062
<!doctype html>
@@ -968,15 +1068,15 @@ table.debug td {
9681068
\(style)
9691069
\(header)
9701070
</head>
971-
<body>
972-
<article class="markdown-body">
1071+
<body\(body_style)>
1072+
\(wrapper_open)
9731073
\(body)
974-
</article>
1074+
\(wrapper_close)
9751075
\(footer)
9761076
</body>
9771077
</html>
9781078
"""
979-
if self.unsafeHTMLOption && self.inlineImageExtension, let ext = cmark_find_syntax_extension("inlineimage"), cmark_syntax_extension_inlineimage_get_raw_images_count(ext) > 0 {
1079+
if !self.renderAsCode && self.unsafeHTMLOption && self.inlineImageExtension, let ext = cmark_find_syntax_extension("inlineimage"), cmark_syntax_extension_inlineimage_get_raw_images_count(ext) > 0 {
9801080
var changed = false
9811081
do {
9821082
let doc = try SwiftSoup.parse(html, basedir.path)

QLMarkdown/Themes/Theme.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -377,7 +377,7 @@ import Cocoa
377377
<title>\(self.name)</title>
378378
<style type="text/css">
379379
body {
380-
font-family: -apple-system, BlinkMacSystemFont, sans-serif;
380+
font-family: ui-monospace, -apple-system, BlinkMacSystemFont, sans-serif;
381381
user-select: none;
382382
}
383383
\(css)

QLMarkdown/Themes/ThemesViewController.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import Foundation
1010
import Cocoa
1111
import WebKit
1212

13-
protocol ThemesViewDelegate: class {
13+
protocol ThemesViewDelegate: AnyObject {
1414
var theme: ThemePreview? { get set }
1515
}
1616

0 commit comments

Comments
 (0)