2021/05/31

SwiftUIでswiftのコードのシンタックスハイライトを表示する

swiftuiswift

JohnSundell/Splashのライブラリを利用させていただきました。

こちらのライブラリはWebでも使えて、swiftのコードのシンタックスハイライトをしたhtml+cssを吐き出すような使い方をするようでしたが、
swiftアプリ用に、NSAttributedString形式での出力にも対応していたため、そちらを利用しました。

以下完成版です。

  • UILabelをうまく使って、SwiftUI用のViewを作っています。
    • numberOfLines = 0 を指定して、行数の表示と高さを可変にするようにしています。
import SwiftUI
import Splash

struct MarkdownCodeView: View {
    
    var code: String
    
    var body: some View {
        ScrollView(.horizontal, showsIndicators: false) {
            MarkdownCodeLabel(code: code)
                .padding()
                .background(Color.Gray900)
        }
    }
}


struct MarkdownCodeLabel: UIViewRepresentable {
    
    var code: String
    
    func makeUIView(context: Context) -> UILabel {
        let label = UILabel()
        label.numberOfLines = 0
        label.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
        return label
    }
    
    func updateUIView(_ uiView: UILabel, context: Context) {
        let theme = Theme(
            font: Font(size: 12),
            plainTextColor: UIColor(.Gray50),
            tokenColors: [
                .keyword: UIColor(.Pink500),
                .string: UIColor(.Red500),
                .type: UIColor(.Violet500),
                .call: UIColor(.Gray50),
                .number: UIColor(.LightBlue500),
                .comment: UIColor(.Gray400),
                .property: UIColor(.Violet500),
                .dotAccess: UIColor(.Violet500),
                .preprocessing: UIColor(.Orange500)
            ],
            backgroundColor: UIColor(.Gray900)
        )
        let highlighter = SyntaxHighlighter(
            format: AttributedStringOutputFormat(theme: theme)
        )
        uiView.attributedText = highlighter.highlight(code)
    }
}

色の定義はこちらの記事を参考にしてください。

以上です。