← back to dennylee2026__MDViewer

Function bodies 8 total

All specs Real LLM only Function bodies
AppDelegate class · swift · L745-L749 (5 LOC)
MDViewer/App/AppDelegate.swift
class AppDelegate: NSObject, NSApplicationDelegate {
    func application(_ application: NSApplication, open urls: [URL]) {
        for url in urls { WindowCoordinator.shared.open(url: url) }
    }
}
WindowCoordinator class · swift · L5-L74 (70 LOC)
MDViewer/App/WindowCoordinator.swift
final class WindowCoordinator {
    static let shared = WindowCoordinator()
    private init() {}

    private var openHandler: ((WindowID) -> Void)?
    private var pendingURLs: [URL] = []

    // Weak references to all live AppState instances
    private struct WeakRef { weak var appState: AppState? }
    private var registeredStates: [WeakRef] = []

    /// Each WindowView registers its AppState so we can reuse empty windows.
    func registerAppState(_ appState: AppState) {
        registeredStates.removeAll { $0.appState == nil }
        registeredStates.append(WeakRef(appState: appState))
    }

    /// Called by the first window on appear. Drains any URLs queued before a window existed.
    func register(handler: @escaping (WindowID) -> Void) {
        openHandler = handler
        let pending = pendingURLs
        pendingURLs = []
        for url in pending { open(url: url) }
    }

    func openEmpty() {
        openHandler?(.empty())
    }

    func open(url: URL) {
        r
Coordinator class · swift · L230-L309 (80 LOC)
MDViewer/Rendering/EditorView.swift
    class Coordinator: NSObject, NSTextViewDelegate {
        var parent:      EditorView
        weak var textView: NSTextView?
        var highlighter: MarkdownHighlighter?
        var currentFontFamily: String = "system"
        var lastScrollToken: UUID? = nil
        var lastEditorStyle: EditorStyle? = nil

        init(_ parent: EditorView) { self.parent = parent }

        func textDidChange(_ notification: Notification) {
            guard let tv = notification.object as? NSTextView else { return }
            // Don't propagate partial IME composition — wait for confirmed text
            guard !tv.hasMarkedText() else { return }
            parent.text = tv.string
        }

        func textViewDidChangeSelection(_ notification: Notification) {
            guard let tv = notification.object as? NSTextView else { return }
            // Skip cursor-sync while IME is composing
            guard !tv.hasMarkedText() else { return }
            let cursor = tv.selectedRange().loc
LineNumberRulerView class · swift · L4-L99 (96 LOC)
MDViewer/Rendering/LineNumberRulerView.swift
final class LineNumberRulerView: NSRulerView {

    private weak var textView: NSTextView?
    private let numberFont  = NSFont.monospacedSystemFont(ofSize: 10.5, weight: .regular)
    private let rightPad: CGFloat = 8

    init(textView: NSTextView, scrollView: NSScrollView) {
        self.textView = textView
        super.init(scrollView: scrollView, orientation: .verticalRuler)
        clientView   = textView
        ruleThickness = 42

        let nc = NotificationCenter.default
        nc.addObserver(self, selector: #selector(refresh),
                       name: NSText.didChangeNotification, object: textView)
        nc.addObserver(self, selector: #selector(refresh),
                       name: NSView.boundsDidChangeNotification,
                       object: scrollView.contentView)
    }

    required init(coder: NSCoder) { fatalError() }

    @objc private func refresh() { needsDisplay = true }

    // MARK: - Drawing

    override func drawHashMarksAndLabels(in rect: NSRect
MarkdownHighlighter class · swift · L4-L215 (212 LOC)
MDViewer/Rendering/MarkdownHighlighter.swift
final class MarkdownHighlighter: NSObject, NSTextStorageDelegate {

    var baseFont: NSFont = .systemFont(ofSize: 14)         // updated by EditorView on zoom
    var paragraphStyle: NSParagraphStyle = .default        // updated by EditorView on zoom
    weak var textView: NSTextView?                         // set by EditorView; used for IME check
    var editorStyle: EditorStyle = StylesFile.systemDefaults.styles[0].editorStyle
    private var isWorking = false

    /// Bold version of baseFont, preserving its cascade list (e.g. PingFang SC).
    private func makeBoldFont(size: CGFloat? = nil) -> NSFont {
        let sz = size ?? baseFont.pointSize
        let descriptor = baseFont.fontDescriptor.withSymbolicTraits(.bold)
        return NSFont(descriptor: descriptor, size: sz) ?? NSFont.boldSystemFont(ofSize: sz)
    }

    // MARK: - Delegate

    func textStorage(
        _ textStorage: NSTextStorage,
        didProcessEditing editedMask: NSTextStorageEditActions,
        range: N
Coordinator class · swift · L80-L185 (106 LOC)
MDViewer/Rendering/MarkdownWebView.swift
    class Coordinator: NSObject, WKNavigationDelegate, WKScriptMessageHandler {
        weak var webView: WKWebView?
        var pendingContent: String = ""
        var pendingFileURL: URL? = nil
        var pendingCSS: String = ""
        var lastContent: String = ""
        var lastFileURL: URL? = nil
        var lastCSS: String = ""
        var isLoaded: Bool = false
        var onPreviewClick: ((Int, CGFloat, CGFloat) -> Void)?

        // Debounce timer for editor-mode renders (file-open bypasses it)
        private var renderTimer: Timer?

        deinit { renderTimer?.invalidate() }

        func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
            isLoaded = true
            let css = pendingCSS
            let escaped = css
                .replacingOccurrences(of: "\\", with: "\\\\")
                .replacingOccurrences(of: "`", with: "\\`")
                .replacingOccurrences(of: "$", with: "\\$")
            webView.evaluateJavaScript("applyCu
StyleManager class · swift · L5-L82 (78 LOC)
MDViewer/Styles/StyleManager.swift
final class StyleManager: ObservableObject {
    static let shared = StyleManager()

    @Published private(set) var stylesFile: StylesFile
    @Published private(set) var activeStyle: MarkdownStyle

    private let fileWatcher = FileWatcher()
    private var isRestoring = false
    private var appearanceObserver: NSKeyValueObservation?

    private init() {
        let file = StylesFile.load()
        stylesFile = file
        activeStyle = file.resolvedEffectiveStyle()
    }

    func setup() {
        // Ensure config file exists on disk
        if !FileManager.default.fileExists(atPath: StylesFile.configURL.path) {
            stylesFile.save()
        }
        // Watch for changes
        fileWatcher.watch(url: StylesFile.configURL) { [weak self] in
            self?.reload()
        }
        // Follow system dark/light mode transitions
        appearanceObserver = NSApp.observe(\.effectiveAppearance) { [weak self] _, _ in
            DispatchQueue.main.async {
                g
Repobility · severity-and-effort ranking · https://repobility.com
FileWatcher class · swift · L3-L57 (55 LOC)
MDViewer/Utilities/FileWatcher.swift
final class FileWatcher {
    private var source: DispatchSourceFileSystemObject?
    private var watchedURL: URL?
    private var onChange: (() -> Void)?

    func watch(url: URL, onChange: @escaping () -> Void) {
        self.watchedURL = url
        self.onChange = onChange
        startWatching(url: url)
    }

    func stop() {
        source?.cancel()
        source = nil
    }

    private func startWatching(url: URL) {
        source?.cancel()
        source = nil

        let fd = open(url.path, O_EVTONLY)
        guard fd != -1 else { return }

        let src = DispatchSource.makeFileSystemObjectSource(
            fileDescriptor: fd,
            eventMask: [.write, .rename, .delete, .attrib],
            queue: .main
        )

        src.setEventHandler { [weak self] in
            guard let self else { return }
            let flags = src.data
            self.onChange?()
            // Atomic-save editors replace the file via rename/delete;
            // re-watch the p