go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/milo/ui/src/common/components/result_entry/text_diff_artifact.ts (about) 1 // Copyright 2020 The LUCI Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 import '@material/mwc-icon'; 16 import { MobxLitElement } from '@adobe/lit-mobx'; 17 import * as Diff2Html from 'diff2html'; 18 import { css, html } from 'lit'; 19 import { customElement } from 'lit/decorators.js'; 20 import { unsafeHTML } from 'lit/directives/unsafe-html.js'; 21 import { computed, makeObservable, observable } from 'mobx'; 22 import { fromPromise, IPromiseBasedObservable } from 'mobx-utils'; 23 24 import '@/generic_libs/components/expandable_entry'; 25 import { ARTIFACT_LENGTH_LIMIT } from '@/common/constants/test'; 26 import { Artifact } from '@/common/services/resultdb'; 27 import { commonStyles } from '@/common/styles/stylesheets'; 28 import { 29 getRawArtifactURLPath, 30 getTextDiffArtifactURLPath, 31 } from '@/common/tools/url_utils'; 32 import { reportRenderError } from '@/generic_libs/tools/error_handler'; 33 import { unwrapObservable } from '@/generic_libs/tools/mobx_utils'; 34 import { urlSetSearchQueryParam } from '@/generic_libs/tools/utils'; 35 36 /** 37 * Renders a text diff artifact. 38 */ 39 @customElement('milo-text-diff-artifact') 40 export class TextDiffArtifactElement extends MobxLitElement { 41 @observable.ref artifact!: Artifact; 42 43 @computed 44 private get content$(): IPromiseBasedObservable<string> { 45 return fromPromise( 46 // TODO(crbug/1206109): use permanent raw artifact URL. 47 fetch( 48 urlSetSearchQueryParam( 49 this.artifact.fetchUrl, 50 'n', 51 ARTIFACT_LENGTH_LIMIT, 52 ), 53 ).then((res) => res.text()), 54 ); 55 } 56 57 @computed 58 private get content() { 59 return unwrapObservable(this.content$, null); 60 } 61 62 constructor() { 63 super(); 64 makeObservable(this); 65 } 66 67 protected render = reportRenderError(this, () => { 68 return html` 69 <link 70 rel="stylesheet" 71 type="text/css" 72 href="https://cdn.jsdelivr.net/npm/diff2html/bundles/css/diff2html.min.css" 73 /> 74 <milo-expandable-entry .expanded=${true} .contentRuler="invisible"> 75 <span id="header" slot="header"> 76 Unexpected text output from 77 <a 78 href=${getTextDiffArtifactURLPath(this.artifact.name)} 79 target="_blank" 80 > 81 ${this.artifact.artifactId} 82 </a> 83 (<a href=${getRawArtifactURLPath(this.artifact.name)} target="_blank" 84 >view raw</a 85 >) 86 </span> 87 <div id="content" slot="content"> 88 ${unsafeHTML( 89 Diff2Html.html(this.content || '', { drawFileList: false }), 90 )} 91 </div> 92 </milo-expandable-entry> 93 `; 94 }); 95 96 static styles = [ 97 commonStyles, 98 css` 99 #content { 100 padding-top: 5px; 101 position: relative; 102 } 103 .d2h-code-linenumber { 104 cursor: default; 105 } 106 .d2h-moved-tag { 107 display: none; 108 } 109 `, 110 ]; 111 }