From 65cc14655169e0a7cce82cd18864d860509426af Mon Sep 17 00:00:00 2001 From: iamkeeler <8247438+iamkeeler@users.noreply.github.com> Date: Sun, 7 Jun 2026 16:16:45 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=94=8D=20Lens:=20Fix=20typographic=20scal?= =?UTF-8?q?e=20inversion=20in=20Settings=20&=20ContentView?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com> --- .Jules/lens.md | 3 +++ MarkTo/Views/ContentView.swift | 2 +- .../Views/FormattingCustomizationView.swift | 6 ++--- commit_msg.txt | 14 ++++++++--- fix.rb | 25 ++++++------------- 5 files changed, 25 insertions(+), 25 deletions(-) create mode 100644 .Jules/lens.md diff --git a/.Jules/lens.md b/.Jules/lens.md new file mode 100644 index 0000000..10a9428 --- /dev/null +++ b/.Jules/lens.md @@ -0,0 +1,3 @@ +## 2024-06-07 - Typographic Scale & Logical Sectioning +**Learning:** Found a typographic scale inversion in `FormattingCustomizationView` where the page's container title used a smaller font (`.title3`) than the specific section title (`.title2`). This creates cognitive friction because the visual hierarchy contradicts the spatial/logical hierarchy (Page > Component). Also observed that the main input label in `ContentView` lacked sufficient weight (`.subheadline`) to establish a clear section. +**Action:** Always verify that headings maintain a descending scale (e.g., `.largeTitle` > `.title` > `.title2` > `.title3` > `.headline`) that maps to the nesting depth. Promote small labels that act as primary section headers up to `.headline`. diff --git a/MarkTo/Views/ContentView.swift b/MarkTo/Views/ContentView.swift index c48164d..ba0f28e 100644 --- a/MarkTo/Views/ContentView.swift +++ b/MarkTo/Views/ContentView.swift @@ -12,7 +12,7 @@ struct ContentView: View { VStack(alignment: .leading, spacing: 12) { HStack { Label("Markdown", systemImage: "text.alignleft") - .font(.subheadline) + .font(.headline) .fontWeight(.medium) .foregroundStyle(.secondary) diff --git a/MarkTo/Views/FormattingCustomizationView.swift b/MarkTo/Views/FormattingCustomizationView.swift index aae7b7c..40aeb52 100644 --- a/MarkTo/Views/FormattingCustomizationView.swift +++ b/MarkTo/Views/FormattingCustomizationView.swift @@ -24,7 +24,7 @@ struct FormattingCustomizationView: View { .foregroundColor(.accentColor) Text("Rich Text Formatting") - .font(.title3) + .font(.title2) .fontWeight(.medium) .padding(.leading, 12) @@ -163,12 +163,12 @@ struct FormattingCustomizationView: View { // MARK: - Element Header private var elementHeader: some View { HStack { Image(systemName: iconForElement(viewModel.selectedElement)) - .font(.title) + .font(.title2) .foregroundStyle(.blue) VStack(alignment: .leading, spacing: 2) { Text(viewModel.selectedElement.displayName) - .font(.title2) + .font(.title3) .fontWeight(.medium) Text("Customize appearance and spacing") diff --git a/commit_msg.txt b/commit_msg.txt index db71db6..79aa885 100644 --- a/commit_msg.txt +++ b/commit_msg.txt @@ -1,7 +1,13 @@ -⚡ Optimize NSRegularExpression match substring extraction +🔍 Lens: Fix typographic scale inversion in Settings & ContentView -💡 **What:** Replaced the `Range(contentRange, in: string)` Swift `String.Index` translation with `NSString`'s `.substring(with:)` across all inline regex processors in `InlineProcessor.swift`. +The Problem: +In `FormattingCustomizationView`, the page's main title "Rich Text Formatting" used `.title3`, but the specific element header (e.g. "Body Text") used `.title2`. This inverted the typographical hierarchy, creating cognitive friction by making the sub-section visually more dominant than the page title. In `ContentView`, the "Markdown" label used `.subheadline`, which was too small to establish a clear section hierarchy over the input field. -🎯 **Why:** Translating an `NSRange` to a Swift `Range` requires traversing the String from the beginning since Swift Strings use UTF-8/UTF-16 encoding dynamically and count characters by grapheme clusters (O(N) operation for index translations). Doing this inside a loop proportional to the number of matches causes O(N*M) or O(N^2) complexity where N is the text length. Additionally, casting substring slices directly to `String(string[contentSwiftRange])` incurs extra memory allocations. By casting the base string to `NSString` once and using `.substring(with:)`, we utilize O(1) direct integer-offset memory reads, saving huge amounts of CPU cycles and memory allocations for documents with many format matches. +The Visual Logic: +Typographic Scale dictates that headings must be larger than body text and descend logically (Page > Section > Component). By promoting the Page Title to `.title2` and demoting the section header to `.title3`, we map the visual hierarchy to the logical hierarchy. Promoting the input label to `.headline` establishes it as a section leader without overpowering the CTA. -📊 **Measured Improvement:** Standard Swift build tools (`swiftc`, `xcodebuild`) were unavailable in the development environment to execute benchmarks. However, the theoretical algorithmic improvement is changing the inner loop extraction string lookup from O(N) index traversal to O(1) integer-based substring bounds lookup per match. For a text containing hundreds of formatting directives (e.g. `**bold**`), this saves N traversals, translating to a substantial performance increase during the RTF conversion process and significantly fewer ARC allocations due to substring memory bridging optimizations. +The Surgery: +Modified existing `.font()` view modifiers in `FormattingCustomizationView.swift` and `ContentView.swift`. No new components or custom font sizes were created; relied entirely on Apple's standard dynamic type scale values (`.headline`, `.title2`, `.title3`). + +A11y/IA Impact: +Standardizing to the correct Apple dynamic type scale improves the predictability of the mental model, ensuring users immediately recognize their current context within the hierarchy, while fully supporting dynamic type scaling. diff --git a/fix.rb b/fix.rb index 3960dcb..2b96b64 100644 --- a/fix.rb +++ b/fix.rb @@ -1,20 +1,11 @@ -#!/usr/bin/env ruby +content = File.read('MarkTo/Views/FormattingCustomizationView.swift') +# Change page title +content.sub!(/Text\("Rich Text Formatting"\)\n\s*\.font\(\.title3\)/, "Text(\"Rich Text Formatting\")\n .font(.title2)") -file_path = 'MarkTo/Models/InlineProcessor.swift' -content = File.read(file_path) +# Change element header icon font +content.sub!(/Image\(systemName: iconForElement\(viewModel\.selectedElement\)\)\n\s*\.font\(\.title\)/, "Image(systemName: iconForElement(viewModel.selectedElement))\n .font(.title2)") -methods = [ - 'processStrikethrough', - 'processBoldPattern', - 'processItalicPattern', - 'processCode', - 'processAutoLinks', - 'processBareURLs', - 'processEmojis', - 'processImages' -] +# Change element header title font +content.sub!(/Text\(viewModel\.selectedElement\.displayName\)\n\s*\.font\(\.title2\)/, "Text(viewModel.selectedElement.displayName)\n .font(.title3)") -methods.each do |method_name| - # Replace 'let string = attributedString.string' - # with 'let nsString = attributedString.string as NSString' -end +File.write('MarkTo/Views/FormattingCustomizationView.swift', content)