refactor: use structured rich text for Notes editing
This commit is contained in:
@@ -1,17 +1,18 @@
|
||||
import AppKit
|
||||
import ConjureKit
|
||||
import Testing
|
||||
@testable import Conjure
|
||||
|
||||
@Test @MainActor func fencedCodeHighlightsTokensWithoutChangingSourceOrApplyingMarkdown() throws {
|
||||
@Test @MainActor
|
||||
func codeBlocksHighlightTokensWithoutInterpretingTheirLiteralMarkdown() throws {
|
||||
_ = NSApplication.shared
|
||||
for fence in ["```", "~~~~"] {
|
||||
let text = "# Heading 🦊\n\(fence)py\ndef main():\n # comment\n return \"**not bold**\"\n\(fence)\nAfter\n```unknown-language\n# literal\n```"
|
||||
let editor = NSTextView()
|
||||
editor.string = text
|
||||
MarkdownHighlighting.apply(to: editor)
|
||||
let source = "# Heading 🦊\n\(fence)py\ndef main():\n # comment\n return \"**not bold**\"\n\(fence)\nAfter\n```unknown-language\n# literal\n```"
|
||||
let editor = NotesTextView(frame: NSRect(x: 0, y: 0, width: 600, height: 500))
|
||||
editor.setDocumentContents(NoteDocument.importMarkdown(NSAttributedString(string: source)))
|
||||
let storage = try #require(editor.textStorage)
|
||||
func attributes(_ token: String) -> [NSAttributedString.Key: Any] {
|
||||
storage.attributes(at: (text as NSString).range(of: token).location, effectiveRange: nil)
|
||||
storage.attributes(at: (editor.string as NSString).range(of: token).location, effectiveRange: nil)
|
||||
}
|
||||
let keyword = try #require(attributes("def")[.foregroundColor] as? NSColor)
|
||||
let name = try #require(attributes("main")[.foregroundColor] as? NSColor)
|
||||
@@ -19,20 +20,23 @@ import Testing
|
||||
#expect(keyword != name)
|
||||
#expect(comment != keyword)
|
||||
#expect((attributes("**not bold**")[.font] as? NSFont)?.isFixedPitch == true)
|
||||
#expect(storage.string == text)
|
||||
editor.string = "```python\ndef main():\n pass"
|
||||
MarkdownHighlighting.apply(to: editor)
|
||||
#expect(attributes("**not bold**")[NoteAttributes.bold] as? Bool != true)
|
||||
#expect(attributes("# literal")[NoteAttributes.headingLevel] == nil)
|
||||
#expect(attributes("# literal")[NoteAttributes.block] as? String == "code")
|
||||
#expect(editor.string == "Heading 🦊\ndef main():\n # comment\n return \"**not bold**\"\nAfter\n# literal")
|
||||
editor.setDocumentContents(NoteDocument.importMarkdown(NSAttributedString(string: "```python\ndef main():\n pass")))
|
||||
let unfinished = try #require(editor.textStorage)
|
||||
#expect(unfinished.attribute(.foregroundColor, at: 10, effectiveRange: nil) as? NSColor == keyword)
|
||||
#expect(unfinished.attribute(.foregroundColor, at: 0, effectiveRange: nil) as? NSColor == keyword)
|
||||
#expect(editor.string == "def main():\n pass")
|
||||
}
|
||||
}
|
||||
|
||||
@Test @MainActor func noteHeadingsShrinkByLevelWithoutChangingMarkdownOrCode() throws {
|
||||
@Test @MainActor
|
||||
func headingLevelsUseDescendingSizesAndCodeRemainsBodySized() throws {
|
||||
_ = NSApplication.shared
|
||||
let editor = NSTextView()
|
||||
let text = "# One\n## Two\n### Three\n#### Four\n##### Five\n###### Six\nBody\n## **Bold** and *italic*\n```text\n# Literal\n```\n####### Not a heading"
|
||||
editor.string = text
|
||||
MarkdownHighlighting.apply(to: editor)
|
||||
let editor = NotesTextView(frame: NSRect(x: 0, y: 0, width: 600, height: 600))
|
||||
let source = "# One\n## Two\n### Three\n#### Four\n##### Five\n###### Six\nBody\n## **Bold** and *italic*\n```text\n# Literal\n```\n####### Not a heading"
|
||||
editor.setDocumentContents(NoteDocument.importMarkdown(NSAttributedString(string: source)))
|
||||
let storage = try #require(editor.textStorage)
|
||||
func font(_ token: String) throws -> NSFont {
|
||||
try #require(storage.attribute(.font, at: (editor.string as NSString).range(of: token).location,
|
||||
@@ -41,13 +45,14 @@ import Testing
|
||||
let sizes = try ["One", "Two", "Three", "Four", "Five", "Six"].map { try font($0).pointSize }
|
||||
for (larger, smaller) in zip(sizes, sizes.dropFirst()) { #expect(larger > smaller) }
|
||||
#expect(try font("Six").pointSize >= font("Body").pointSize)
|
||||
#expect(try font("**Bold**").pointSize == font("Two").pointSize)
|
||||
#expect(try font("*italic*").pointSize == font("Two").pointSize)
|
||||
#expect(try font("Bold").pointSize == font("Two").pointSize)
|
||||
#expect(try font("italic").pointSize == font("Two").pointSize)
|
||||
#expect(try font("Literal").pointSize == font("Body").pointSize)
|
||||
#expect(try font("Not a heading").pointSize == font("Body").pointSize)
|
||||
#expect(try font("Three").isFixedPitch)
|
||||
#expect(editor.string == text)
|
||||
storage.replaceCharacters(in: (editor.string as NSString).range(of: "### Three"), with: "Three")
|
||||
MarkdownHighlighting.apply(to: editor)
|
||||
let three = (editor.string as NSString).range(of: "Three")
|
||||
editor.setSelectedRange(three)
|
||||
for _ in 0..<4 { editor.format(0) }
|
||||
#expect(editor.string.contains("Three"))
|
||||
#expect(try font("Three").pointSize == font("Body").pointSize)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user