Skip to content

Commit a45d6c7

Browse files
author
Kalyan Kanuri
committed
fix: HTML-escape snippet/title before Lucene highlight conversion
Raw '<' in paragraph source (e.g. WHERE id < 100) was being parsed as a broken DOM tag by the browser when rendered via [innerHTML]/ng-bind-html, silently dropping the text that followed. Fix: escape &, <, > to HTML entities first, then promote &lt;B&gt; markers to <mark> elements. Applied to both Angular (result-item.component.ts) and Classic UI (result-list.controller.js). Addresses voidmatcha review comment (May 24).
1 parent 5fb4f26 commit a45d6c7

2 files changed

Lines changed: 28 additions & 7 deletions

File tree

zeppelin-web-angular/src/app/pages/workspace/notebook-search/result-item/result-item.component.ts

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,13 +65,14 @@ export class NotebookSearchResultItemComponent implements OnChanges {
6565
this.displayName = this.result.name ? this.result.name : `Note ${noteId}`;
6666

6767
const snippet = this.result.snippet || '';
68-
// Preserve Lucene <B> highlighting by converting to <mark>
69-
this.codeHtml = snippet.replace(/<B>/gi, '<mark>').replace(/<\/B>/gi, '</mark>');
68+
// HTML-escape first so raw '<' in code (e.g. WHERE id < 100) is not parsed
69+
// as a DOM tag, then promote only the Lucene <B> markers to <mark>.
70+
this.codeHtml = this.highlightToMark(snippet);
7071
this.codeText = snippet.replace(/<\/?B>/gi, '');
7172
this.interpreter = this.detectInterpreter(this.codeText);
7273

7374
const title = this.result.title || '';
74-
this.titleHtml = title.replace(/<B>/gi, '<mark>').replace(/<\/B>/gi, '</mark>');
75+
this.titleHtml = this.highlightToMark(title);
7576

7677
const tables = this.result.tables || '';
7778
this.tablesText = tables
@@ -82,6 +83,17 @@ export class NotebookSearchResultItemComponent implements OnChanges {
8283
this.outputText = this.result.output || '';
8384
}
8485

86+
private highlightToMark(text: string): string {
87+
// Escape HTML so raw '<' in source (e.g. WHERE id < 100) is not parsed as
88+
// a DOM tag, then convert the Lucene <B>/<\/B> markers back to <mark>.
89+
return text
90+
.replace(/&/g, '&amp;')
91+
.replace(/</g, '&lt;')
92+
.replace(/>/g, '&gt;')
93+
.replace(/&lt;B&gt;/gi, '<mark>')
94+
.replace(/&lt;\/B&gt;/gi, '</mark>');
95+
}
96+
8597
private detectInterpreter(text: string): string {
8698
if (!text) {
8799
return '';

zeppelin-web/src/app/search/result-list.controller.js

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,17 @@ function SearchResultCtrl($scope, $routeParams, searchService) {
5252
return '';
5353
}
5454

55+
// HTML-escape raw text so '<' in source (e.g. WHERE id < 100) is not parsed
56+
// as a DOM tag, then promote only the Lucene <B>/<\/B> markers to <mark>.
57+
function highlightToMark(text) {
58+
return text
59+
.replace(/&/g, '&amp;')
60+
.replace(/</g, '&lt;')
61+
.replace(/>/g, '&gt;')
62+
.replace(/&lt;B&gt;/gi, '<mark>')
63+
.replace(/&lt;\/B&gt;/gi, '</mark>');
64+
}
65+
5566
results.$promise.then(function(result) {
5667
$scope.notes = result.body.map(function(note) {
5768
if (!/\/paragraph\//.test(note.id)) {
@@ -60,17 +71,15 @@ function SearchResultCtrl($scope, $routeParams, searchService) {
6071
note.id = note.id.replace('paragraph/', '?paragraph=') +
6172
'&term=' + $routeParams.searchTerm;
6273

63-
// Preserve Lucene <B> highlighting by converting to <mark>
64-
let codeHtml = (note.snippet || '').replace(/<B>/gi, '<mark>').replace(/<\/B>/gi, '</mark>');
6574
let code = (note.snippet || '').replace(/<B>/g, '').replace(/<\/B>/g, '');
6675

6776
let tables = (note.tables || '').trim().split(/\s+/).filter(function(t) {
6877
return t;
6978
}).join(', ');
7079

7180
note.codeText = code;
72-
note.codeHtml = codeHtml;
73-
note.titleHtml = (note.title || '').replace(/<B>/gi, '<mark>').replace(/<\/B>/gi, '</mark>');
81+
note.codeHtml = highlightToMark(note.snippet || '');
82+
note.titleHtml = highlightToMark(note.title || '');
7483
note.outputText = note.output || '';
7584
note.tablesText = tables;
7685
note.langBadge = detectLang(code);

0 commit comments

Comments
 (0)