diff --git a/Examples/Demo/Demo/CodeSyntaxHighlightView.swift b/Examples/Demo/Demo/CodeSyntaxHighlightView.swift index 671bd49f..e27a09a6 100644 --- a/Examples/Demo/Demo/CodeSyntaxHighlightView.swift +++ b/Examples/Demo/Demo/CodeSyntaxHighlightView.swift @@ -26,7 +26,7 @@ struct CodeSyntaxHighlightView: View { } func highlightCode(_ content: String, language: String?) -> Text { - guard language?.lowercased() == "swift" else { + guard language != nil else { return Text(content) } @@ -50,15 +50,92 @@ struct CodeSyntaxHighlightView: View { .markdownCodeSyntaxHighlighter(.splash(theme: .sunset(withFont: .init(size: 16)))) } ``` + + More languages to render: + + ``` + A plain code block without the specifying a language name. + ``` + + ```cpp + #include + #include + + int main() { + std::vector fruits = {"apple", "banana", "orange"}; + for (const std::string& fruit : fruits) { + std::cout << "I love " << fruit << "s!" << std::endl; + } + return 0; + } + ``` + + ```typescript + interface Person { + name: string; + age: number; + } + + const person = Person(); + ``` + + ```ruby + fruits = ["apple", "banana", "orange"] + fruits.each do |fruit| + puts "I love #{fruit}s!" + end + ``` + """# var body: some View { DemoView { Markdown(self.content) + .markdownBlockStyle(\.codeBlock) { + codeBlock($0) + } .markdownCodeSyntaxHighlighter(.splash(theme: self.theme)) } } + @ViewBuilder + private func codeBlock(_ configuration: CodeBlockConfiguration) -> some View { + VStack(spacing: 0) { + HStack { + Text(configuration.language ?? "plain text") + .font(.system(.caption, design: .monospaced)) + .fontWeight(.semibold) + .foregroundColor(Color(theme.plainTextColor)) + Spacer() + + Image(systemName: "clipboard") + .onTapGesture { + copyToClipboard(configuration.content) + } + } + .padding(.horizontal) + .padding(.vertical, 8) + .background { + Color(theme.backgroundColor) + } + + Divider() + + ScrollView(.horizontal) { + configuration.label + .relativeLineSpacing(.em(0.25)) + .markdownTextStyle { + FontFamilyVariant(.monospaced) + FontSize(.em(0.85)) + } + .padding() + } + } + .background(Color(.secondarySystemBackground)) + .clipShape(RoundedRectangle(cornerRadius: 8)) + .markdownMargin(top: .zero, bottom: .em(0.8)) + } + private var theme: Splash.Theme { // NOTE: We are ignoring the Splash theme font switch self.colorScheme { @@ -68,6 +145,17 @@ struct CodeSyntaxHighlightView: View { return .sunset(withFont: .init(size: 16)) } } + + private func copyToClipboard(_ string: String) { +#if os(macOS) + if let pasteboard = NSPasteboard.general { + pasteboard.clearContents() + pasteboard.setString(string, forType: .string) + } +#elseif os(iOS) + UIPasteboard.general.string = string +#endif + } } struct CodeSyntaxHighlightView_Previews: PreviewProvider { diff --git a/Examples/Demo/Demo/SyntaxHighlighter/SplashCodeSyntaxHighlighter.swift b/Examples/Demo/Demo/SyntaxHighlighter/SplashCodeSyntaxHighlighter.swift index 91af848a..008d735d 100644 --- a/Examples/Demo/Demo/SyntaxHighlighter/SplashCodeSyntaxHighlighter.swift +++ b/Examples/Demo/Demo/SyntaxHighlighter/SplashCodeSyntaxHighlighter.swift @@ -10,7 +10,7 @@ struct SplashCodeSyntaxHighlighter: CodeSyntaxHighlighter { } func highlightCode(_ content: String, language: String?) -> Text { - guard language?.lowercased() == "swift" else { + guard language != nil else { return Text(content) }