Skip to content

Commit c79bf5b

Browse files
content: Add support for search highlighting in code blocks
Fixes: #1695
1 parent 87355b7 commit c79bf5b

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
@@ -540,6 +540,49 @@ class ContentExample {
540540
ParagraphNode(links: null, nodes: [TextNode("some content")]),
541541
]);
542542

543+
static const codeBlockSearchHighlight = ContentExample(
544+
'code block, search highlight',
545+
'```dart\nclass A {}\n```',
546+
'<div class="codehilite" data-code-language="Dart">'
547+
'<pre>'
548+
'<span></span>'
549+
'<code>'
550+
'<span class="kd">'
551+
'<span class="highlight">class</span></span>'
552+
'<span class="w"> </span>'
553+
'<span class="nc">A</span>'
554+
'<span class="w"> </span>'
555+
'<span class="p">{}</span>\n</code></pre></div>', [
556+
CodeBlockNode([
557+
CodeBlockSpanNode(text: 'class', spanTypes: [CodeBlockSpanType.keywordDeclaration, CodeBlockSpanType.highlight]),
558+
CodeBlockSpanNode(text: ' ', spanTypes: [CodeBlockSpanType.whitespace]),
559+
CodeBlockSpanNode(text: 'A', spanTypes: [CodeBlockSpanType.nameClass]),
560+
CodeBlockSpanNode(text: ' ', spanTypes: [CodeBlockSpanType.whitespace]),
561+
CodeBlockSpanNode(text: '{}', spanTypes: [CodeBlockSpanType.punctuation]),
562+
]),
563+
]);
564+
565+
static const codeBlockSearchHighlightBetweenText = ContentExample(
566+
'code block, search highlight between text',
567+
'```console\n# postgresql\nThe World\'s Most Advanced Open Source Relational Database\n```',
568+
'<div class="codehilite" data-code-language="Bash Session">'
569+
'<pre>'
570+
'<span></span>'
571+
'<code>'
572+
'<span class="gp"># </span>postgresql\n'
573+
'<span class="go">'
574+
'The '
575+
'<span class="highlight">World</span>'
576+
'\'s Most Advanced Open Source Relational Database</span>\n</code></pre></div>', [
577+
CodeBlockNode([
578+
CodeBlockSpanNode(text: '# ', spanTypes: [CodeBlockSpanType.genericPrompt]),
579+
CodeBlockSpanNode(text: "postgresql\n", spanTypes: [CodeBlockSpanType.text]),
580+
CodeBlockSpanNode(text: 'The ', spanTypes: [CodeBlockSpanType.genericOutput]),
581+
CodeBlockSpanNode(text: 'World', spanTypes: [CodeBlockSpanType.genericOutput, CodeBlockSpanType.highlight]),
582+
CodeBlockSpanNode(text: '\'s Most Advanced Open Source Relational Database', spanTypes: [CodeBlockSpanType.genericOutput]),
583+
]),
584+
]);
585+
543586
static final mathInline = ContentExample.inline(
544587
'inline math',
545588
r"$$ \lambda $$",
@@ -2006,6 +2049,8 @@ void main() async {
20062049
testParseExample(ContentExample.codeBlockWithHighlightedLines);
20072050
testParseExample(ContentExample.codeBlockWithUnknownSpanType);
20082051
testParseExample(ContentExample.codeBlockFollowedByMultipleLineBreaks);
2052+
testParseExample(ContentExample.codeBlockSearchHighlight);
2053+
testParseExample(ContentExample.codeBlockSearchHighlightBetweenText);
20092054

20102055
testParseExample(ContentExample.mathBlock);
20112056
testParseExample(ContentExample.mathBlocksMultipleInParagraph);

0 commit comments

Comments
 (0)