mirror of
https://github.com/block/buzz.git
synced 2026-10-31 06:21:34 +00:00
mobile: keep multi-backtick code spans and decode link labels in previews
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -151,6 +151,7 @@ List<PreviewPiece> messagePreviewPieces(
|
||||
}
|
||||
|
||||
const _maxLineLength = 2000;
|
||||
const _backtick = 0x60;
|
||||
|
||||
final _rule = RegExp(r'^([-*_])(?:\s*\1){2,}$');
|
||||
final _tableDivider = RegExp(r'^\|?(?:\s*:?-+:?\s*\|)+\s*:?-*:?\s*\|?$');
|
||||
@@ -236,20 +237,57 @@ class _PreviewBuilder {
|
||||
piece is PreviewText ? text(piece.text) : pieces.add(piece);
|
||||
|
||||
/// One line of prose: inline code is literal, everything else is inline
|
||||
/// Markdown.
|
||||
/// Markdown. A code span opens at a run of backticks and closes at the next
|
||||
/// run of the same length; a run with no match is literal.
|
||||
void line(String line) {
|
||||
final parts = line.split('`');
|
||||
// An unpaired backtick is literal.
|
||||
if (parts.length.isEven) {
|
||||
parts[parts.length - 2] += '`${parts.removeLast()}';
|
||||
}
|
||||
for (var i = 0; i < parts.length; i++) {
|
||||
if (i.isOdd) {
|
||||
text(parts[i]);
|
||||
} else {
|
||||
_inline(parts[i]);
|
||||
var prose = 0;
|
||||
var cursor = 0;
|
||||
while (cursor < line.length) {
|
||||
if (line.codeUnitAt(cursor) != _backtick) {
|
||||
cursor++;
|
||||
continue;
|
||||
}
|
||||
final open = cursor;
|
||||
final openEnd = _runEnd(line, open);
|
||||
final run = openEnd - open;
|
||||
int? close;
|
||||
var scan = openEnd;
|
||||
while (scan < line.length) {
|
||||
if (line.codeUnitAt(scan) != _backtick) {
|
||||
scan++;
|
||||
continue;
|
||||
}
|
||||
final end = _runEnd(line, scan);
|
||||
if (end - scan == run) {
|
||||
close = scan;
|
||||
break;
|
||||
}
|
||||
scan = end;
|
||||
}
|
||||
if (close == null) {
|
||||
cursor = openEnd;
|
||||
continue;
|
||||
}
|
||||
_inline(line.substring(prose, open));
|
||||
var code = line.substring(openEnd, close);
|
||||
if (code.length > 2 &&
|
||||
code.startsWith(' ') &&
|
||||
code.endsWith(' ') &&
|
||||
code.trim().isNotEmpty) {
|
||||
code = code.substring(1, code.length - 1);
|
||||
}
|
||||
text(code);
|
||||
cursor = prose = close + run;
|
||||
}
|
||||
_inline(line.substring(prose));
|
||||
}
|
||||
|
||||
static int _runEnd(String line, int start) {
|
||||
var end = start;
|
||||
while (end < line.length && line.codeUnitAt(end) == _backtick) {
|
||||
end++;
|
||||
}
|
||||
return end;
|
||||
}
|
||||
|
||||
void _inline(String source) {
|
||||
@@ -274,7 +312,9 @@ class _PreviewBuilder {
|
||||
add(PreviewChannel(_channelName(deepLink.channelId)));
|
||||
continue;
|
||||
}
|
||||
_tokens(_unwrapEmphasis(label.isEmpty ? url : label));
|
||||
_tokens(
|
||||
_unwrapEmphasis(label.isEmpty ? url : decodeMarkdownLabelSyntax(label)),
|
||||
);
|
||||
}
|
||||
_tokens(_unwrapEmphasis(source.substring(start)));
|
||||
}
|
||||
|
||||
@@ -45,6 +45,14 @@ void main() {
|
||||
('lone asterisk', '2 * 3 = 6', '2 * 3 = 6'),
|
||||
('inline code', 'run `**not bold**` here', 'run **not bold** here'),
|
||||
('unpaired backtick', 'a ` b **c**', 'a ` b c'),
|
||||
('double-backtick code', 'x ``**a** `b` @c`` y', 'x **a** `b` @c y'),
|
||||
('unmatched backtick run', 'a `` b `c` **d**', 'a `` b c d'),
|
||||
('padded code span', '`` `x` ``', '`x`'),
|
||||
(
|
||||
'encoded label brackets',
|
||||
'[report [Q4]](https://x.y)',
|
||||
'report [Q4]',
|
||||
),
|
||||
('link', 'see [the docs](https://example.com)', 'see the docs'),
|
||||
('bare link label', '[https://x.y](https://x.y)', 'https://x.y'),
|
||||
('rule', 'above\n---\nbelow', 'above\nbelow'),
|
||||
|
||||
Reference in New Issue
Block a user