Skip to content

Commit 2c8fe02

Browse files
content: Add support for search highlighting in code blocks
Fixes: #1695
1 parent 7e6402c commit 2c8fe02

File tree

3 files changed

+64
-0
lines changed

3 files changed

+64
-0
lines changed

lib/model/code_block.dart

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@ enum CodeBlockSpanType {
88
unknown,
99
/// A run of unstyled text in a code block.
1010
text,
11+
/// A code-block span with CSS class `highlight`.
12+
///
13+
/// This span is emitted by server for content matching
14+
/// used for displaying keyword search highlighting.
15+
highlight,
1116
/// A code-block span with CSS class `hll`.
1217
///
1318
/// Unlike most `CodeBlockSpanToken` values, this does not correspond to
@@ -174,6 +179,7 @@ enum CodeBlockSpanType {
174179

175180
CodeBlockSpanType codeBlockSpanTypeFromClassName(String className) {
176181
return switch (className) {
182+
'highlight' => CodeBlockSpanType.highlight,
177183
'hll' => CodeBlockSpanType.highlightedLines,
178184
'w' => CodeBlockSpanType.whitespace,
179185
'esc' => CodeBlockSpanType.escape,

lib/widgets/code_block.dart

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ class CodeBlockTextStyles {
1919
height: 1.4))
2020
.merge(weightVariableTextStyle(context)),
2121

22+
// .highlight { background-color: hsl(51deg 100% 79%); }
23+
// See https://github.com/zulip/zulip/blob/f87479703/web/styles/rendered_markdown.css#L1037-L1039
24+
highlight: TextStyle(backgroundColor: const HSLColor.fromAHSL(1, 51, 1, 0.79).toColor()),
25+
2226
// .hll { background-color: hsl(60deg 100% 90%); }
2327
hll: TextStyle(backgroundColor: const HSLColor.fromAHSL(1, 60, 1, 0.90).toColor()),
2428

@@ -259,6 +263,10 @@ class CodeBlockTextStyles {
259263
height: 1.4))
260264
.merge(weightVariableTextStyle(context)),
261265

266+
// .highlight { background-color: hsl(51deg 100% 23%); }
267+
// See https://github.com/zulip/zulip/blob/f87479703/web/styles/dark_theme.css#L410-L412
268+
highlight: TextStyle(backgroundColor: const HSLColor.fromAHSL(1, 51, 1, 0.23).toColor()),
269+
262270
// .hll { background-color: #49483e; }
263271
hll: const TextStyle(backgroundColor: Color(0xff49483e)),
264272

@@ -500,6 +508,7 @@ class CodeBlockTextStyles {
500508

501509
CodeBlockTextStyles._({
502510
required this.plain,
511+
required TextStyle highlight,
503512
required TextStyle hll,
504513
required TextStyle c,
505514
required TextStyle err,
@@ -580,6 +589,7 @@ class CodeBlockTextStyles {
580589
required TextStyle? vm,
581590
required TextStyle il,
582591
}) :
592+
_highlight = highlight,
583593
_hll = hll,
584594
_c = c,
585595
_err = err,
@@ -663,6 +673,7 @@ class CodeBlockTextStyles {
663673
/// The baseline style that the [forSpan] styles get applied on top of.
664674
final TextStyle plain;
665675

676+
final TextStyle _highlight;
666677
final TextStyle _hll;
667678
final TextStyle _c;
668679
final TextStyle _err;
@@ -751,6 +762,7 @@ class CodeBlockTextStyles {
751762
TextStyle? forSpan(CodeBlockSpanType type) {
752763
return switch (type) {
753764
CodeBlockSpanType.text => null, // A span with type of text is always unstyled.
765+
CodeBlockSpanType.highlight => _highlight,
754766
CodeBlockSpanType.highlightedLines => _hll,
755767
CodeBlockSpanType.comment => _c,
756768
CodeBlockSpanType.error => _err,
@@ -839,6 +851,7 @@ class CodeBlockTextStyles {
839851

840852
return CodeBlockTextStyles._(
841853
plain: TextStyle.lerp(a.plain, b.plain, t)!,
854+
highlight: TextStyle.lerp(a._highlight, b._highlight, t)!,
842855
hll: TextStyle.lerp(a._hll, b._hll, t)!,
843856
c: TextStyle.lerp(a._c, b._c, t)!,
844857
err: TextStyle.lerp(a._err, b._err, t)!,

test/model/content_test.dart

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -533,6 +533,49 @@ class ContentExample {
533533
ParagraphNode(links: null, nodes: [TextNode("some content")]),
534534
]);
535535

536+
static const codeBlockSearchHighlight = ContentExample(
537+
'code block, search highlight',
538+
'```dart\nclass A {}\n```',
539+
'<div class="codehilite" data-code-language="Dart">'
540+
'<pre>'
541+
'<span></span>'
542+
'<code>'
543+
'<span class="kd">'
544+
'<span class="highlight">class</span></span>'
545+
'<span class="w"> </span>'
546+
'<span class="nc">A</span>'
547+
'<span class="w"> </span>'
548+
'<span class="p">{}</span>\n</code></pre></div>', [
549+
CodeBlockNode([
550+
CodeBlockSpanNode(text: 'class', spanTypes: [CodeBlockSpanType.keywordDeclaration, CodeBlockSpanType.highlight]),
551+
CodeBlockSpanNode(text: ' ', spanTypes: [CodeBlockSpanType.whitespace]),
552+
CodeBlockSpanNode(text: 'A', spanTypes: [CodeBlockSpanType.nameClass]),
553+
CodeBlockSpanNode(text: ' ', spanTypes: [CodeBlockSpanType.whitespace]),
554+
CodeBlockSpanNode(text: '{}', spanTypes: [CodeBlockSpanType.punctuation]),
555+
]),
556+
]);
557+
558+
static const codeBlockSearchHighlightBetweenText = ContentExample(
559+
'code block, search highlight between text',
560+
'```console\n# postgresql\nThe World\'s Most Advanced Open Source Relational Database\n```',
561+
'<div class="codehilite" data-code-language="Bash Session">'
562+
'<pre>'
563+
'<span></span>'
564+
'<code>'
565+
'<span class="gp"># </span>postgresql\n'
566+
'<span class="go">'
567+
'The '
568+
'<span class="highlight">World</span>'
569+
'\'s Most Advanced Open Source Relational Database</span>\n</code></pre></div>', [
570+
CodeBlockNode([
571+
CodeBlockSpanNode(text: '# ', spanTypes: [CodeBlockSpanType.genericPrompt]),
572+
CodeBlockSpanNode(text: "postgresql\n", spanTypes: [CodeBlockSpanType.text]),
573+
CodeBlockSpanNode(text: 'The ', spanTypes: [CodeBlockSpanType.genericOutput]),
574+
CodeBlockSpanNode(text: 'World', spanTypes: [CodeBlockSpanType.genericOutput, CodeBlockSpanType.highlight]),
575+
CodeBlockSpanNode(text: '\'s Most Advanced Open Source Relational Database', spanTypes: [CodeBlockSpanType.genericOutput]),
576+
]),
577+
]);
578+
536579
static final mathInline = ContentExample.inline(
537580
'inline math',
538581
r"$$ \lambda $$",
@@ -2047,6 +2090,8 @@ void main() async {
20472090
testParseExample(ContentExample.codeBlockWithHighlightedLines);
20482091
testParseExample(ContentExample.codeBlockWithUnknownSpanType);
20492092
testParseExample(ContentExample.codeBlockFollowedByMultipleLineBreaks);
2093+
testParseExample(ContentExample.codeBlockSearchHighlight);
2094+
testParseExample(ContentExample.codeBlockSearchHighlightBetweenText);
20502095

20512096
testParseExample(ContentExample.mathBlock);
20522097
testParseExample(ContentExample.mathBlocksMultipleInParagraph);

0 commit comments

Comments
 (0)