mirror of
https://seed.radicle.dev/rad:z4D5UCArafTzTQpDZNQRuqswh3ury.git
synced 2026-10-18 19:10:45 +08:00
Move comment preview text into lib
The regex-heavy markdown stripping was untested in the component.
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
import type { Thread } from "@bindings/cob/thread/Thread";
|
||||
|
||||
import type { Resolution } from "@app/lib/commentResolutions";
|
||||
import { plainText } from "@app/lib/markdownPlain";
|
||||
import type { CommentAnchor } from "@app/lib/pierreComments";
|
||||
import { anchorOf, formatAnchorLines } from "@app/lib/pierreComments";
|
||||
import {
|
||||
@@ -51,30 +52,9 @@
|
||||
return author.alias ?? truncateId(authorKey(author));
|
||||
}
|
||||
|
||||
/// Inline markdown, dropped down to the words it decorates. A row is a couple
|
||||
/// of truncated lines, and on a narrow column the punctuation crowds out the
|
||||
/// text that says what the comment is about. Deliberately shallow — this is a
|
||||
/// preview, not a parser; the comment itself is one click away in the diff.
|
||||
function plain(body: string): string {
|
||||
return (
|
||||
body
|
||||
.replace(/!?\[([^\]]*)\]\([^)]*\)/gu, "$1")
|
||||
.replace(/`/gu, "")
|
||||
.replace(/~~(.+?)~~/gu, "$1")
|
||||
// Emphasis only where a marker sits on a word boundary, so `snake_case`,
|
||||
// `MAX_SIZE` and `_private` survive being read as italics.
|
||||
.replace(/(^|[^\w])[*_]{1,2}([^*_]+?)[*_]{1,2}(?=[^\w]|$)/gu, "$1$2")
|
||||
.replace(/^\s{0,3}#{1,6}\s+/gmu, "")
|
||||
.replace(/^\s{0,3}>\s?/gmu, "")
|
||||
.replace(/^\s{0,3}(?:[-+*]|\d+\.)\s+/gmu, "")
|
||||
.replace(/\s+/gu, " ")
|
||||
.trim()
|
||||
);
|
||||
}
|
||||
|
||||
/// The last edit is the current text.
|
||||
function preview(comment: Comment<CodeLocation>): string {
|
||||
return plain(comment.edits.at(-1)?.body ?? "");
|
||||
return plainText(comment.edits.at(-1)?.body ?? "");
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
/// Inline markdown, dropped down to the words it decorates. A row is a couple
|
||||
/// of truncated lines, and on a narrow column the punctuation crowds out the
|
||||
/// text that says what the comment is about. Deliberately shallow — this is a
|
||||
/// preview, not a parser; the comment itself is one click away in the diff.
|
||||
export function plainText(body: string): string {
|
||||
return (
|
||||
body
|
||||
.replace(/!?\[([^\]]*)\]\([^)]*\)/gu, "$1")
|
||||
.replace(/`/gu, "")
|
||||
.replace(/~~(.+?)~~/gu, "$1")
|
||||
// Emphasis only where a marker sits on a word boundary, so `snake_case`,
|
||||
// `MAX_SIZE` and `_private` survive being read as italics.
|
||||
.replace(/(^|[^\w])[*_]{1,2}([^*_]+?)[*_]{1,2}(?=[^\w]|$)/gu, "$1$2")
|
||||
.replace(/^\s{0,3}#{1,6}\s+/gmu, "")
|
||||
.replace(/^\s{0,3}>\s?/gmu, "")
|
||||
.replace(/^\s{0,3}(?:[-+*]|\d+\.)\s+/gmu, "")
|
||||
.replace(/\s+/gu, " ")
|
||||
.trim()
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
import { expect, test } from "vitest";
|
||||
|
||||
import { plainText } from "@app/lib/markdownPlain";
|
||||
|
||||
test.each([
|
||||
["[the docs](https://example.com)", "the docs"],
|
||||
[" here", "diagram here"],
|
||||
["run `npm test` now", "run npm test now"],
|
||||
["~~old~~ new", "old new"],
|
||||
["**bold** and _italic_", "bold and italic"],
|
||||
["__strong__ and *em*", "strong and em"],
|
||||
["# Heading", "Heading"],
|
||||
["### Deep heading", "Deep heading"],
|
||||
["> quoted\n> text", "quoted text"],
|
||||
["- one\n* two\n+ three\n1. four", "one two three four"],
|
||||
["line one\n\n line two", "line one line two"],
|
||||
[" padded ", "padded"],
|
||||
])("%j reads as %j", (markdown, expected) => {
|
||||
expect(plainText(markdown)).toBe(expected);
|
||||
});
|
||||
|
||||
test.each(["snake_case_name", "MAX_SIZE", "_private", "a*b*c"])(
|
||||
"leaves %j alone",
|
||||
text => {
|
||||
expect(plainText(text)).toBe(text);
|
||||
},
|
||||
);
|
||||
Reference in New Issue
Block a user