Improve editor fidelity#10
Conversation
…daily-use # Conflicts: # docmostly/Features/Editor/ProseMirrorNode.swift
There was a problem hiding this comment.
2 issues found and verified against the latest diff
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="docmostly/Features/Editor/NativeEditorMarkdownParser+RichBlocks.swift">
<violation number="1" location="docmostly/Features/Editor/NativeEditorMarkdownParser+RichBlocks.swift:506">
P2: Require a filename segment before assigning attachmentId. Otherwise `/api/files/manual.pdf` or another one-segment files route is imported as attachmentId `manual.pdf`, corrupting the rich block metadata.</violation>
</file>
<file name="docmostly/Features/Editor/NativeEditorMarkdownParser.swift">
<violation number="1" location="docmostly/Features/Editor/NativeEditorMarkdownParser.swift:130">
P1: `detailsInputRule` checks `text == ":::details "` (trailing space), but on the paste/import path, `block(from:)` trims the line first via `line.trimmingCharacters(in: .whitespaces)`, so `:::details ` becomes `:::details` and never matches.</violation>
</file>
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 0def049a76
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
2 issues found across 6 files (changes from recent commits).
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="docmostly/Features/Editor/NativeEditorMarkdownParser+DocmostInlineHTML.swift">
<violation number="1" location="docmostly/Features/Editor/NativeEditorMarkdownParser+DocmostInlineHTML.swift:43">
P2: Literal `<span>` text inside a Docmost comment/mention body prevents finding the closing tag, dropping the preserved comment/mention during Markdown import. Only count real nested span tags in parsed HTML context, or skip Markdown code/text literals before adjusting depth.</violation>
</file>
<file name="docmostly/Features/Editor/NativeEditorMarkdownParser+DocmostLinks.swift">
<violation number="1" location="docmostly/Features/Editor/NativeEditorMarkdownParser+DocmostLinks.swift:334">
P2: `data-resolved="false"` is treated as resolved because the code checks only for attribute presence. Parse the attribute value so explicit false/unset stays unresolved.</violation>
</file>
Tip: Review your code locally with the cubic CLI to iterate faster.
Re-trigger cubic
There was a problem hiding this comment.
1 issue found across 1 file (changes from recent commits).
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="docmostlyTests/Editor/NativeEditorTablePayloadTests.swift">
<violation number="1" location="docmostlyTests/Editor/NativeEditorTablePayloadTests.swift:122">
P1: Test rgb(100%, 0%, 50%) will fail because cssColorComponent doesn't parse percentage values</violation>
</file>
Tip: Review your code locally with the cubic CLI to iterate faster.
Re-trigger cubic
|
|
||
| @MainActor | ||
| @Test func tableCellBackgroundRespectsRGBColorPercentages() { | ||
| let components = NativeEditorTableLayout.cssRGBAComponents(from: "rgb(100%, 0%, 50%)") |
There was a problem hiding this comment.
P1: Test rgb(100%, 0%, 50%) will fail because cssColorComponent doesn't parse percentage values
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At docmostlyTests/Editor/NativeEditorTablePayloadTests.swift, line 122:
<comment>Test rgb(100%, 0%, 50%) will fail because cssColorComponent doesn't parse percentage values</comment>
<file context>
@@ -116,4 +116,14 @@ struct NativeEditorTablePayloadTests {
+
+ @MainActor
+ @Test func tableCellBackgroundRespectsRGBColorPercentages() {
+ let components = NativeEditorTableLayout.cssRGBAComponents(from: "rgb(100%, 0%, 50%)")
+
+ #expect(components?.red == 255)
</file context>
There was a problem hiding this comment.
1 issue found across 1 file (changes from recent commits).
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="docmostly/Features/Editor/NativeEditorMarkdownParser+InlineMarks.swift">
<violation number="1" location="docmostly/Features/Editor/NativeEditorMarkdownParser+InlineMarks.swift:197">
P2: New `_` matcher can miss valid single-underscore emphasis spans when preceded by an unmatched repeated delimiter. `delimitedInlineMarkdownMatch` only searches for the first occurrence of the delimiter; if that first `_` is part of `__` and `isPartOfRepeatedDelimiter` returns true, the matcher returns nil instead of continuing to find a later valid `_..._` span. For example, in `__draft _important_` the `_important_` emphasis would be entirely skipped because the first `_` is adjacent to another underscore.</violation>
</file>
Tip: Review your code locally with the cubic CLI to iterate faster.
Re-trigger cubic
| } | ||
|
|
||
| if delimiter == "*", isPartOfStrongDelimiter(openRange, in: markdown) { | ||
| if delimiter.count == 1, isPartOfRepeatedDelimiter(openRange, delimiter: delimiter, in: markdown) { |
There was a problem hiding this comment.
P2: New _ matcher can miss valid single-underscore emphasis spans when preceded by an unmatched repeated delimiter. delimitedInlineMarkdownMatch only searches for the first occurrence of the delimiter; if that first _ is part of __ and isPartOfRepeatedDelimiter returns true, the matcher returns nil instead of continuing to find a later valid _..._ span. For example, in __draft _important_ the _important_ emphasis would be entirely skipped because the first _ is adjacent to another underscore.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At docmostly/Features/Editor/NativeEditorMarkdownParser+InlineMarks.swift, line 197:
<comment>New `_` matcher can miss valid single-underscore emphasis spans when preceded by an unmatched repeated delimiter. `delimitedInlineMarkdownMatch` only searches for the first occurrence of the delimiter; if that first `_` is part of `__` and `isPartOfRepeatedDelimiter` returns true, the matcher returns nil instead of continuing to find a later valid `_..._` span. For example, in `__draft _important_` the `_important_` emphasis would be entirely skipped because the first `_` is adjacent to another underscore.</comment>
<file context>
@@ -182,7 +194,7 @@ extension NativeEditorMarkdownParser {
}
- if delimiter == "*", isPartOfStrongDelimiter(openRange, in: markdown) {
+ if delimiter.count == 1, isPartOfRepeatedDelimiter(openRange, delimiter: delimiter, in: markdown) {
return nil
}
</file context>
There was a problem hiding this comment.
3 issues found across 5 files (changes from recent commits).
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="docmostly/Features/Editor/NativeEditorMarkdownParser.swift">
<violation number="1" location="docmostly/Features/Editor/NativeEditorMarkdownParser.swift:374">
P2: Script/underline formatting is bypassed for runs carrying status, inline math, or mention attributes, risking silent mark loss during Markdown export.</violation>
</file>
<file name="docmostly/Features/Editor/NativeEditorMarkdownParser+ScriptUnderline.swift">
<violation number="1" location="docmostly/Features/Editor/NativeEditorMarkdownParser+ScriptUnderline.swift:104">
P2: Closing tags are only matched by a literal `</tag>` search, which misses valid HTML end tags with whitespace before `>` (e.g. `</u >`). The opening-tag parser already scans character-by-character and tolerates such whitespace, so this creates an asymmetric parser that can fail on otherwise valid HTML.</violation>
</file>
<file name="docmostly/Features/Editor/NativeEditorMarkdownParser+InlineMarks.swift">
<violation number="1" location="docmostly/Features/Editor/NativeEditorMarkdownParser+InlineMarks.swift:61">
P2: Raw HTML wrapping doesn't escape the body, risking broken round-trips when user text contains tag-like content</violation>
</file>
Tip: Review your code locally with the cubic CLI to iterate faster.
Re-trigger cubic
| runMarkdown = mentionMarkdown(from: mention, fallbackText: runText) | ||
| } else { | ||
| output += inlineRunMarkdown(from: run, text: runText) | ||
| let scriptMarkdown = scriptUnderlineMarkdown( |
There was a problem hiding this comment.
P2: Script/underline formatting is bypassed for runs carrying status, inline math, or mention attributes, risking silent mark loss during Markdown export.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At docmostly/Features/Editor/NativeEditorMarkdownParser.swift, line 374:
<comment>Script/underline formatting is bypassed for runs carrying status, inline math, or mention attributes, risking silent mark loss during Markdown export.</comment>
<file context>
@@ -371,10 +371,14 @@ enum NativeEditorMarkdownParser {
runMarkdown = mentionMarkdown(from: mention, fallbackText: runText)
} else {
- let coloredMarkdown = textColorMarkdown(
+ let scriptMarkdown = scriptUnderlineMarkdown(
from: run,
body: inlineRunMarkdown(from: run, text: runText)
</file context>
| var searchStart = bodyStart | ||
|
|
||
| while searchStart < markdown.endIndex, | ||
| let closeRange = markdown[searchStart...].range(of: closingTag, options: .caseInsensitive) { |
There was a problem hiding this comment.
P2: Closing tags are only matched by a literal </tag> search, which misses valid HTML end tags with whitespace before > (e.g. </u >). The opening-tag parser already scans character-by-character and tolerates such whitespace, so this creates an asymmetric parser that can fail on otherwise valid HTML.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At docmostly/Features/Editor/NativeEditorMarkdownParser+ScriptUnderline.swift, line 104:
<comment>Closing tags are only matched by a literal `</tag>` search, which misses valid HTML end tags with whitespace before `>` (e.g. `</u >`). The opening-tag parser already scans character-by-character and tolerates such whitespace, so this creates an asymmetric parser that can fail on otherwise valid HTML.</comment>
<file context>
@@ -0,0 +1,166 @@
+ var searchStart = bodyStart
+
+ while searchStart < markdown.endIndex,
+ let closeRange = markdown[searchStart...].range(of: closingTag, options: .caseInsensitive) {
+ guard isInsideMarkdownCodeSpan(closeRange.lowerBound, ranges: codeSpanRanges) == false else {
+ searchStart = closeRange.upperBound
</file context>
| ) -> String { | ||
| var output = body | ||
|
|
||
| if let baselineOffset = run.baselineOffset, baselineOffset != 0 { |
There was a problem hiding this comment.
P2: Raw HTML wrapping doesn't escape the body, risking broken round-trips when user text contains tag-like content
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At docmostly/Features/Editor/NativeEditorMarkdownParser+InlineMarks.swift, line 61:
<comment>Raw HTML wrapping doesn't escape the body, risking broken round-trips when user text contains tag-like content</comment>
<file context>
@@ -52,6 +52,24 @@ extension NativeEditorMarkdownParser {
+ ) -> String {
+ var output = body
+
+ if let baselineOffset = run.baselineOffset, baselineOffset != 0 {
+ let tagName = baselineOffset > 0 ? "sup" : "sub"
+ output = "<\(tagName)>\(output)</\(tagName)>"
</file context>
There was a problem hiding this comment.
1 issue found across 1 file (changes from recent commits).
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="docmostlyTests/Editor/NativeEditorTableMarkdownImportTests.swift">
<violation number="1" location="docmostlyTests/Editor/NativeEditorTableMarkdownImportTests.swift:20">
P2: Use #require instead of #expect for row count to prevent crash on failure</violation>
</file>
Tip: Review your code locally with the cubic CLI to iterate faster.
Re-trigger cubic
| return | ||
| } | ||
|
|
||
| #expect(table.rows.count == 2) |
There was a problem hiding this comment.
P2: Use #require instead of #expect for row count to prevent crash on failure
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At docmostlyTests/Editor/NativeEditorTableMarkdownImportTests.swift, line 20:
<comment>Use #require instead of #expect for row count to prevent crash on failure</comment>
<file context>
@@ -0,0 +1,27 @@
+ return
+ }
+
+ #expect(table.rows.count == 2)
+ #expect(table.rows[1].cells[0].plainText == "a | b")
+ #expect(table.rows[1].cells[1].plainText == "Ready")
</file context>
Summary
/tableshape.Validation
28346938478passed on commit941d08f: SwiftLint, Git hygiene, CRDT runtime drift, iPad build, macOS unit tests, and iOS unit tests.git diff --check,xcrun swiftc -parse ..., andswiftlint lint --strict -- ...on the touched parser/test files.Local Xcode builds/tests, simulator launches, and previews were not run because this repo's agent instructions require explicit user approval for local Apple-platform build/test/run commands.