3030 </span >
3131 <div ref =" leftPayload" class =" left-payload payload" @contextmenu.prevent =" customMenu($event)" >
3232 <p class =" left-info" >
33- <span class =" topic" >Topic: {{ topic }} </span >
33+ <span class =" topic" >Topic: < span v-html = " highlightedTopic " ></ span > </span >
3434 <span class =" qos" >QoS: {{ qos }}</span >
3535 <span v-if =" retain" class =" retain" >Retained</span >
3636 </p >
3737 <MqttProperties class =" meta" :properties =" properties" direction =" left" />
3838 <template v-if =" isLargeMsg " >
39- <div class =" large-message { .el-button { margin-top: 12px;}} " >
40- <pre >{{ payload.substr(0, showMaxLen) }}< span >< i class = " iconfont icon-more " ></ i ></ span ></pre >
39+ <div class =" large-message" >
40+ <pre v-html = " highlightedPayloadPreview " ></pre >
4141 <el-tooltip
4242 placement =" bottom"
4343 :effect =" theme !== 'light' ? 'light' : 'dark'"
5151 </div >
5252 </template >
5353 <template v-else >
54- <pre v-if =" !hightlight" >{{ payload }} </pre >
55- <pre v-else ><code class =" language-js" >{{ payload }}</code ></pre >
54+ <pre v-if =" !hightlight" v-html = " highlightedPayload " > </pre >
55+ <pre v-else ref = " highlightedCode " ><code class =" language-js" >{{ payload }}</code ></pre >
5656 </template >
5757 </div >
5858 <p class =" left-time time" >{{ createAt }}</p >
6161</template >
6262
6363<script lang="ts">
64- import { Component , Vue , Prop } from ' vue-property-decorator'
64+ import { Component , Vue , Prop , Watch } from ' vue-property-decorator'
6565import FullMsgDialog from ' ./FullMsgDialog.vue'
6666import Prism from ' prismjs'
6767import { Getter } from ' vuex-class'
6868import { SHOW_MAX_LENGTH } from ' @/utils/data'
6969import MqttProperties from ' ./MqttProperties.vue'
70+ import { highlightSearchTerm , highlightInPrismCode } from ' @/utils/highlightSearch'
7071
7172@Component ({
7273 components: {
@@ -84,6 +85,10 @@ export default class MsgLeftItem extends Vue {
8485 @Prop ({ required: false , default: false }) public retain! : boolean
8586 @Prop ({ required: false , default : () => ({}) }) public properties! : PushPropertiesModel
8687 @Prop ({ required: false , default: ' ' }) public color! : string
88+ @Prop ({ required: false , default : () => ({ topic: ' ' , payload: ' ' }) }) public searchParams! : {
89+ topic: string
90+ payload: string
91+ }
8792
8893 @Getter (' jsonHighlight' ) private jsonHighlight! : boolean
8994 @Getter (' currentTheme' ) private theme! : Theme
@@ -92,6 +97,35 @@ export default class MsgLeftItem extends Vue {
9297
9398 private showFullMsg: boolean = false
9499
100+ @Watch (' searchParams' , { deep: true })
101+ private onSearchParamsChanged() {
102+ this .$nextTick (() => {
103+ this .applyHighlighting ()
104+ })
105+ }
106+
107+ get highlightedTopic(): string {
108+ if (this .searchParams .topic ) {
109+ return highlightSearchTerm (this .topic , this .searchParams .topic , ' search-highlight' )
110+ }
111+ return this .topic
112+ }
113+
114+ get highlightedPayload(): string {
115+ if (this .searchParams .payload ) {
116+ return highlightSearchTerm (this .payload , this .searchParams .payload , ' search-highlight' )
117+ }
118+ return this .payload
119+ }
120+
121+ get highlightedPayloadPreview(): string {
122+ const preview = this .payload .substr (0 , this .showMaxLen )
123+ if (this .searchParams .payload ) {
124+ return highlightSearchTerm (preview , this .searchParams .payload , ' search-highlight' )
125+ }
126+ return preview
127+ }
128+
95129 public customMenu(event : MouseEvent ) {
96130 this .$emit (' showmenu' , this .payload , event )
97131 }
@@ -131,6 +165,27 @@ export default class MsgLeftItem extends Vue {
131165 return SHOW_MAX_LENGTH
132166 }
133167
168+ private applyHighlighting() {
169+ if (this .hightlight && this .searchParams .payload ) {
170+ const codeElement = this .$refs .highlightedCode as HTMLElement
171+ if (codeElement ) {
172+ this .clearHighlights (codeElement )
173+ highlightInPrismCode (codeElement , this .searchParams .payload , ' search-highlight' )
174+ }
175+ }
176+ }
177+
178+ private clearHighlights(element : HTMLElement ) {
179+ const highlights = element .querySelectorAll (' .search-highlight' )
180+ highlights .forEach ((highlight ) => {
181+ const parent = highlight .parentNode
182+ if (parent ) {
183+ parent .replaceChild (document .createTextNode (highlight .textContent || ' ' ), highlight )
184+ parent .normalize ()
185+ }
186+ })
187+ }
188+
134189 private hightlightJSON() {
135190 if (this .jsonHighlight === false ) {
136191 return
@@ -140,6 +195,7 @@ export default class MsgLeftItem extends Vue {
140195 this .hightlight = true
141196 this .$nextTick (() => {
142197 Prism .highlightAllUnder (this .$refs .msgLeftItem as HTMLElement )
198+ this .applyHighlighting ()
143199 })
144200 }
145201 } catch (e ) {
@@ -212,5 +268,12 @@ body.night {
212268 }
213269 }
214270 }
271+ .search-highlight {
272+ background-color : #ffeb3b !important ;
273+ color : #000 !important ;
274+ padding : 1px 2px ;
275+ border-radius : 2px ;
276+ font-weight : bold ;
277+ }
215278}
216279 </style >
0 commit comments