Sources/OrgCore/Semantic/FileSummary.swift
32 lines · 1526 bytes
2 symbols in this file
1import Foundation
2
3/// What Spotlight shows and searches for a file: its keywords, tags and headings.
4public struct FileSummary: Sendable, Equatable {
5 public var title: String?
6 public var author: String?
7 public var description: String?
8 /// `#+FILETAGS` and every heading's tags, in order, once each.
9 public var tags: [String]
10 /// Heading titles, with TODO keywords, priorities and tags left out.
11 public var headings: [String]
12
13 public init(_ text: String) {
14 let tree = OrgParser.parse(text)
15 func keyword(_ name: String) -> String? {
16 let pattern = "^[ \\t]*#\\+" + name + ":[ \\t]*(.*?)[ \\t]*$"
17 guard let m = try! NSRegularExpression(pattern: pattern, options: [.anchorsMatchLines, .caseInsensitive])
18 .firstMatch(in: text, range: NSRange(location: 0, length: (text as NSString).length)) else { return nil }
19 let value = (text as NSString).substring(with: m.range(at: 1))
20 return value.isEmpty ? nil : value
21 }
22 title = keyword("TITLE")
23 author = keyword("AUTHOR")
24 description = keyword("DESCRIPTION")
25 let model = DocumentModel(tree: tree)
26 var tags = (keyword("FILETAGS") ?? "").split { $0 == ":" || $0 == " " }.map(String.init)
27 for heading in model.headings { tags += heading.localTags }
28 var seen = Set<String>()
29 self.tags = tags.filter { seen.insert($0).inserted }
30 headings = model.headings.map { Links.normalizedTitle($0.title) }
31 }
32}