diff options
author | Dhruv Srivastava <dhruvsri@google.com> | 2022-04-12 09:16:30 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2022-04-12 09:16:30 +0000 |
commit | ccc66ddf47818c158d2c931d14773faa9f930ada (patch) | |
tree | 87035ca54d93573de4f5b4c8ec041b2d2563ef12 | |
parent | 508d3ebaa3ecea84ae0ca2e435d0fb738c75dbf5 (diff) | |
parent | 4badebf5cf94f345c28c63f90cca5c598d7065c8 (diff) |
Merge "Revert "Add lit element based gr-diff elements""
19 files changed, 146 insertions, 1907 deletions
diff --git a/polygerrit-ui/app/embed/diff/gr-context-controls/gr-context-controls-section.ts b/polygerrit-ui/app/embed/diff/gr-context-controls/gr-context-controls-section.ts deleted file mode 100644 index 77ba8cde25..0000000000 --- a/polygerrit-ui/app/embed/diff/gr-context-controls/gr-context-controls-section.ts +++ /dev/null @@ -1,113 +0,0 @@ -/** - * @license - * Copyright 2022 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ -import '../../../elements/shared/gr-button/gr-button'; -import {html, LitElement} from 'lit'; -import {customElement, property, state} from 'lit/decorators'; -import {DiffInfo, DiffViewMode, RenderPreferences} from '../../../api/diff'; -import {GrDiffGroup, GrDiffGroupType} from '../gr-diff/gr-diff-group'; -import {diffClasses} from '../gr-diff/gr-diff-utils'; -import {getShowConfig} from './gr-context-controls'; -import {ifDefined} from 'lit/directives/if-defined'; - -@customElement('gr-context-controls-section') -export class GrContextControlsSection extends LitElement { - /** Should context controls be rendered for expanding above the section? */ - @property({type: Boolean}) showAbove = false; - - /** Should context controls be rendered for expanding below the section? */ - @property({type: Boolean}) showBelow = false; - - @property({type: Object}) viewMode = DiffViewMode.SIDE_BY_SIDE; - - /** Must be of type GrDiffGroupType.CONTEXT_CONTROL. */ - @property({type: Object}) - group?: GrDiffGroup; - - @property({type: Object}) - diff?: DiffInfo; - - @property({type: Object}) - renderPrefs?: RenderPreferences; - - /** - * Semantic DOM diff testing does not work with just table fragments, so when - * running such tests the render() method has to wrap the DOM in a proper - * <table> element. - */ - @state() - addTableWrapperForTesting = false; - - /** - * The browser API for handling selection does not (yet) work for selection - * across multiple shadow DOM elements. So we are rendering gr-diff components - * into the light DOM instead of the shadow DOM by overriding this method, - * which was the recommended workaround by the lit team. - * See also https://github.com/WICG/webcomponents/issues/79. - */ - override createRenderRoot() { - return this; - } - - private renderPaddingRow(whereClass: 'above' | 'below') { - if (!this.showAbove && whereClass === 'above') return; - if (!this.showBelow && whereClass === 'below') return; - const sideBySide = this.viewMode === DiffViewMode.SIDE_BY_SIDE; - const modeClass = sideBySide ? 'side-by-side' : 'unified'; - const type = sideBySide ? GrDiffGroupType.CONTEXT_CONTROL : undefined; - return html` - <tr - class=${diffClasses('contextBackground', modeClass, whereClass)} - left-type=${ifDefined(type)} - right-type=${ifDefined(type)} - > - <td class=${diffClasses('blame')} data-line-number="0"></td> - <td class=${diffClasses('contextLineNum')}></td> - ${sideBySide ? html`<td class=${diffClasses()}></td>` : ''} - <td class=${diffClasses('contextLineNum')}></td> - <td class=${diffClasses()}></td> - </tr> - `; - } - - private createContextControlRow() { - const sideBySide = this.viewMode === DiffViewMode.SIDE_BY_SIDE; - const showConfig = getShowConfig(this.showAbove, this.showBelow); - return html` - <tr class=${diffClasses('dividerRow', `show-${showConfig}`)}> - <td class=${diffClasses('blame')} data-line-number="0"></td> - ${sideBySide ? html`<td class=${diffClasses()}></td>` : ''} - <td class=${diffClasses('dividerCell')} colspan="3"> - <gr-context-controls - .diff=${this.diff} - .renderPreferences=${this.renderPrefs} - .group=${this.group} - .showConfig=${showConfig} - > - </gr-context-controls> - </td> - </tr> - `; - } - - override render() { - const rows = html` - ${this.renderPaddingRow('above')} ${this.createContextControlRow()} - ${this.renderPaddingRow('below')} - `; - if (this.addTableWrapperForTesting) { - return html`<table> - ${rows} - </table>`; - } - return rows; - } -} - -declare global { - interface HTMLElementTagNameMap { - 'gr-context-controls-section': GrContextControlsSection; - } -} diff --git a/polygerrit-ui/app/embed/diff/gr-context-controls/gr-context-controls-section_test.ts b/polygerrit-ui/app/embed/diff/gr-context-controls/gr-context-controls-section_test.ts deleted file mode 100644 index 2c1043d355..0000000000 --- a/polygerrit-ui/app/embed/diff/gr-context-controls/gr-context-controls-section_test.ts +++ /dev/null @@ -1,63 +0,0 @@ -/** - * @license - * Copyright 2022 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ -import '../../../test/common-test-setup-karma'; -import './gr-context-controls-section'; -import {GrContextControlsSection} from './gr-context-controls-section'; -import {html} from 'lit'; -import {fixture} from '@open-wc/testing-helpers'; - -suite('gr-context-controls-section test', () => { - let element: GrContextControlsSection; - - setup(async () => { - element = await fixture<GrContextControlsSection>( - html`<gr-context-controls-section></gr-context-controls-section>` - ); - element.addTableWrapperForTesting = true; - await element.updateComplete; - }); - - test('render: normal with showAbove and showBelow', async () => { - element.showAbove = true; - element.showBelow = true; - await element.updateComplete; - expect(element).lightDom.to.equal(/* HTML */ ` - <table> - <tbody> - <tr - class="above contextBackground gr-diff side-by-side style-scope" - left-type="contextControl" - right-type="contextControl" - > - <td class="blame gr-diff style-scope" data-line-number="0"></td> - <td class="contextLineNum gr-diff style-scope"></td> - <td class="gr-diff style-scope"></td> - <td class="contextLineNum gr-diff style-scope"></td> - <td class="gr-diff style-scope"></td> - </tr> - <tr class="dividerRow gr-diff show-both style-scope"> - <td class="blame gr-diff style-scope" data-line-number="0"></td> - <td class="gr-diff style-scope"></td> - <td class="dividerCell gr-diff style-scope" colspan="3"> - <gr-context-controls showconfig="both"> </gr-context-controls> - </td> - </tr> - <tr - class="below contextBackground gr-diff side-by-side style-scope" - left-type="contextControl" - right-type="contextControl" - > - <td class="blame gr-diff style-scope" data-line-number="0"></td> - <td class="contextLineNum gr-diff style-scope"></td> - <td class="gr-diff style-scope"></td> - <td class="contextLineNum gr-diff style-scope"></td> - <td class="gr-diff style-scope"></td> - </tr> - </tbody> - </table> - `); - }); -}); diff --git a/polygerrit-ui/app/embed/diff/gr-context-controls/gr-context-controls.ts b/polygerrit-ui/app/embed/diff/gr-context-controls/gr-context-controls.ts index a451700c20..77a5dfba08 100644 --- a/polygerrit-ui/app/embed/diff/gr-context-controls/gr-context-controls.ts +++ b/polygerrit-ui/app/embed/diff/gr-context-controls/gr-context-controls.ts @@ -80,19 +80,6 @@ function findBlockTreePathForLine( export type GrContextControlsShowConfig = 'above' | 'below' | 'both'; -export function getShowConfig( - showAbove: boolean, - showBelow: boolean -): GrContextControlsShowConfig { - if (showAbove && !showBelow) return 'above'; - if (!showAbove && showBelow) return 'below'; - - // Note that !showAbove && !showBelow also intentionally returns 'both'. - // This means the file is completely collapsed, which is unusual, but at least - // happens in one test. - return 'both'; -} - @customElement('gr-context-controls') export class GrContextControls extends LitElement { @property({type: Object}) renderPreferences?: RenderPreferences; diff --git a/polygerrit-ui/app/embed/diff/gr-diff-builder/gr-diff-builder-element.ts b/polygerrit-ui/app/embed/diff/gr-diff-builder/gr-diff-builder-element.ts index 27ebe4ea59..aabdf57d93 100644 --- a/polygerrit-ui/app/embed/diff/gr-diff-builder/gr-diff-builder-element.ts +++ b/polygerrit-ui/app/embed/diff/gr-diff-builder/gr-diff-builder-element.ts @@ -25,7 +25,6 @@ import {GrDiffBuilderSideBySide} from './gr-diff-builder-side-by-side'; import {GrDiffBuilderImage} from './gr-diff-builder-image'; import {GrDiffBuilderUnified} from './gr-diff-builder-unified'; import {GrDiffBuilderBinary} from './gr-diff-builder-binary'; -import {GrDiffBuilderLit} from './gr-diff-builder-lit'; import {CancelablePromise, util} from '../../../scripts/util'; import {customElement, property, observe} from '@polymer/decorators'; import {BlameInfo, ImageInfo} from '../../../types/common'; @@ -464,24 +463,13 @@ export class GrDiffBuilderElement extends PolymerElement { // If the diff is binary, but not an image. return new GrDiffBuilderBinary(this.diff, localPrefs, this.diffElement); } else if (this.viewMode === DiffViewMode.SIDE_BY_SIDE) { - const useLit = this.renderPrefs?.use_lit_components; - if (useLit) { - builder = new GrDiffBuilderLit( - this.diff, - localPrefs, - this.diffElement, - this._layers, - this.renderPrefs - ); - } else { - builder = new GrDiffBuilderSideBySide( - this.diff, - localPrefs, - this.diffElement, - this._layers, - this.renderPrefs - ); - } + builder = new GrDiffBuilderSideBySide( + this.diff, + localPrefs, + this.diffElement, + this._layers, + this.renderPrefs + ); } else if (this.viewMode === DiffViewMode.UNIFIED) { builder = new GrDiffBuilderUnified( this.diff, diff --git a/polygerrit-ui/app/embed/diff/gr-diff-builder/gr-diff-builder-lit.ts b/polygerrit-ui/app/embed/diff/gr-diff-builder/gr-diff-builder-lit.ts deleted file mode 100644 index 368774775b..0000000000 --- a/polygerrit-ui/app/embed/diff/gr-diff-builder/gr-diff-builder-lit.ts +++ /dev/null @@ -1,185 +0,0 @@ -/** - * @license - * Copyright 2022 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ -import {RenderPreferences} from '../../../api/diff'; -import {LineNumber} from '../gr-diff/gr-diff-line'; -import {GrDiffGroup} from '../gr-diff/gr-diff-group'; -import {DiffInfo, DiffPreferencesInfo} from '../../../types/diff'; -import {Side} from '../../../constants/constants'; -import {DiffLayer, notUndefined} from '../../../types/types'; -import {diffClasses} from '../gr-diff/gr-diff-utils'; -import {GrDiffBuilder} from './gr-diff-builder'; -import {BlameInfo} from '../../../types/common'; -import {html, render} from 'lit'; -import {GrDiffSection} from './gr-diff-section'; -import '../gr-context-controls/gr-context-controls'; -import './gr-diff-section'; -import {GrDiffRow} from './gr-diff-row'; - -/** - * Base class for builders that are creating the diff using Lit elements. - */ -export class GrDiffBuilderLit extends GrDiffBuilder { - constructor( - diff: DiffInfo, - prefs: DiffPreferencesInfo, - outputEl: HTMLElement, - layers: DiffLayer[] = [], - renderPrefs?: RenderPreferences - ) { - super(diff, prefs, outputEl, layers, renderPrefs); - } - - override getContentTdByLine( - lineNumber: LineNumber, - side?: Side, - _root: Element = this.outputEl - ): HTMLTableCellElement | null { - if (!side) return null; - const row = this.findRow(lineNumber, side); - return row?.getContentCell(side) ?? null; - } - - override getLineElByNumber(lineNumber: LineNumber, side: Side) { - const row = this.findRow(lineNumber, side); - return row?.getLineNumberCell(side) ?? null; - } - - private findRow(lineNumber?: LineNumber, side?: Side): GrDiffRow | undefined { - if (!side || !lineNumber) return undefined; - const group = this.findGroup(side, lineNumber); - if (!group) return undefined; - const section = this.findSection(group); - if (!section) return undefined; - return section.findRow(side, lineNumber); - } - - private getDiffRows() { - const sections = [ - ...this.outputEl.querySelectorAll<GrDiffSection>('gr-diff-section'), - ]; - return sections.map(s => s.getDiffRows()).flat(); - } - - override getLineNumberRows(): HTMLTableRowElement[] { - const rows = this.getDiffRows(); - return rows.map(r => r.getTableRow()).filter(notUndefined); - } - - override getLineNumEls(side: Side): HTMLTableCellElement[] { - const rows = this.getDiffRows(); - return rows.map(r => r.getLineNumberCell(side)).filter(notUndefined); - } - - override getBlameTdByLine(lineNumber: number): Element | undefined { - return this.findRow(lineNumber, Side.LEFT)?.getBlameCell(); - } - - override getContentByLine( - lineNumber: LineNumber, - side?: Side, - _root?: HTMLElement - ): HTMLElement | null { - const cell = this.getContentTdByLine(lineNumber, side); - return (cell?.firstChild ?? null) as HTMLElement | null; - } - - override renderContentByRange( - start: LineNumber, - end: LineNumber, - side: Side - ) { - // TODO: Revisit whether there is maybe a more efficient and reliable - // approach. renderContentByRange() is only used when layers announce - // updates. We have to look deeper into the design of layers anyway. So - // let's defer optimizing this code until a refactor of layers in general. - const groups = this.getGroupsByLineRange(start, end, side); - for (const group of groups) { - const section = this.findSection(group); - for (const row of section?.getDiffRows() ?? []) { - row.requestUpdate(); - } - } - } - - private findSection(group?: GrDiffGroup): GrDiffSection | undefined { - if (!group) return undefined; - const leftClass = `left-${group.lineRange.left.start_line}`; - const rightClass = `right-${group.lineRange.right.start_line}`; - return ( - this.outputEl.querySelector<GrDiffSection>( - `gr-diff-section.${leftClass}.${rightClass}` - ) ?? undefined - ); - } - - override renderBlameByRange( - blameInfo: BlameInfo, - start: number, - end: number - ) { - for (let lineNumber = start; lineNumber <= end; lineNumber++) { - const row = this.findRow(lineNumber, Side.LEFT); - if (!row) continue; - row.blameInfo = blameInfo; - } - } - - // TODO: Refactor this such that adding the move controls becomes part of the - // lit element. - protected override getMoveControlsConfig() { - return { - numberOfCells: 4, // How many cells does the diff table have? - movedOutIndex: 1, // Index of left content column in diff table. - movedInIndex: 3, // Index of right content column in diff table. - lineNumberCols: [0, 2], // Indices of line number columns in diff table. - }; - } - - protected override buildSectionElement(group: GrDiffGroup) { - const leftCl = `left-${group.lineRange.left.start_line}`; - const rightCl = `right-${group.lineRange.right.start_line}`; - const section = html` - <gr-diff-section - class="${leftCl} ${rightCl}" - .group=${group} - .diff=${this._diff} - .layers=${this.layers} - .diffPrefs=${this._prefs} - .renderPrefs=${this.renderPrefs} - ></gr-diff-section> - `; - // TODO: Refactor GrDiffBuilder.emitGroup() and buildSectionElement() - // such that we can render directly into the correct container. - const tempContainer = document.createElement('div'); - render(section, tempContainer); - return tempContainer.firstElementChild as GrDiffSection; - } - - override addColumns(outputEl: HTMLElement, lineNumberWidth: number): void { - render( - html` - <colgroup> - <col class=${diffClasses('blame')}></col> - <col class=${diffClasses(Side.LEFT)} width=${lineNumberWidth}></col> - <col class=${diffClasses(Side.LEFT)}></col> - <col class=${diffClasses(Side.RIGHT)} width=${lineNumberWidth}></col> - <col class=${diffClasses(Side.RIGHT)}></col> - </colgroup> - `, - outputEl - ); - } - - protected override getNextContentOnSide( - _content: HTMLElement, - _side: Side - ): HTMLElement | null { - // TODO: getNextContentOnSide() is not required by lit based rendering. - // So let's refactor it to be moved into gr-diff-builder-legacy. - console.warn('unimplemented method getNextContentOnSide() called'); - return null; - } -} diff --git a/polygerrit-ui/app/embed/diff/gr-diff-builder/gr-diff-builder.ts b/polygerrit-ui/app/embed/diff/gr-diff-builder/gr-diff-builder.ts index 4efa238426..add7ffae85 100644 --- a/polygerrit-ui/app/embed/diff/gr-diff-builder/gr-diff-builder.ts +++ b/polygerrit-ui/app/embed/diff/gr-diff-builder/gr-diff-builder.ts @@ -194,7 +194,7 @@ export abstract class GrDiffBuilder implements DiffBuilder { group.element = element; } - protected getGroupsByLineRange( + private getGroupsByLineRange( startLine: LineNumber, endLine: LineNumber, side: Side diff --git a/polygerrit-ui/app/embed/diff/gr-diff-builder/gr-diff-row.ts b/polygerrit-ui/app/embed/diff/gr-diff-builder/gr-diff-row.ts deleted file mode 100644 index ae18e592ac..0000000000 --- a/polygerrit-ui/app/embed/diff/gr-diff-builder/gr-diff-row.ts +++ /dev/null @@ -1,368 +0,0 @@ -/** - * @license - * Copyright 2022 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ -import {html, LitElement, TemplateResult} from 'lit'; -import {customElement, property, state} from 'lit/decorators'; -import {ifDefined} from 'lit/directives/if-defined'; -import {createRef, Ref, ref} from 'lit/directives/ref'; -import { - DiffResponsiveMode, - Side, - LineNumber, - DiffLayer, -} from '../../../api/diff'; -import {BlameInfo} from '../../../types/common'; -import {assertIsDefined} from '../../../utils/common-util'; -import {fire} from '../../../utils/event-util'; -import {getBaseUrl} from '../../../utils/url-util'; -import './gr-diff-text'; -import {GrDiffLine, GrDiffLineType} from '../gr-diff/gr-diff-line'; -import {diffClasses, isResponsive} from '../gr-diff/gr-diff-utils'; - -@customElement('gr-diff-row') -export class GrDiffRow extends LitElement { - contentLeftRef: Ref<HTMLDivElement> = createRef(); - - contentRightRef: Ref<HTMLDivElement> = createRef(); - - lineNumberLeftRef: Ref<HTMLTableCellElement> = createRef(); - - lineNumberRightRef: Ref<HTMLTableCellElement> = createRef(); - - blameCellRef: Ref<HTMLTableCellElement> = createRef(); - - tableRowRef: Ref<HTMLTableRowElement> = createRef(); - - @property({type: Object}) - left?: GrDiffLine; - - @property({type: Object}) - right?: GrDiffLine; - - @property({type: Object}) - blameInfo?: BlameInfo; - - @property({type: Object}) - responsiveMode?: DiffResponsiveMode; - - @property({type: Number}) - tabSize = 2; - - @property({type: Number}) - lineLength = 80; - - @property({type: Boolean}) - hideFileCommentButton = false; - - @property({type: Object}) - layers: DiffLayer[] = []; - - /** - * While not visible we are trying to optimize rendering performance by - * rendering a simpler version of the diff. Once this has become true it - * cannot be set back to false. - */ - @state() - isVisible = false; - - /** - * Semantic DOM diff testing does not work with just table fragments, so when - * running such tests the render() method has to wrap the DOM in a proper - * <table> element. - */ - @state() - addTableWrapperForTesting = false; - - /** - * The browser API for handling selection does not (yet) work for selection - * across multiple shadow DOM elements. So we are rendering gr-diff components - * into the light DOM instead of the shadow DOM by overriding this method, - * which was the recommended workaround by the lit team. - * See also https://github.com/WICG/webcomponents/issues/79. - */ - override createRenderRoot() { - return this; - } - - override updated() { - this.updateLayers(Side.LEFT); - this.updateLayers(Side.RIGHT); - } - - /** - * TODO: This needs some refinement, because layers do not detect whether they - * have already applied their information, so at the moment all layers would - * constantly re-apply their information to the diff in each lit rendering - * pass. - */ - private updateLayers(side: Side) { - if (!this.isVisible) return; - const line = this.line(side); - const contentEl = this.contentRef(side).value; - const lineNumberEl = this.lineNumberRef(side).value; - if (!line || !contentEl || !lineNumberEl) return; - for (const layer of this.layers) { - if (typeof layer.annotate === 'function') { - layer.annotate(contentEl, lineNumberEl, line, side); - } - } - } - - private renderInvisible() { - return html` - <tr> - <td class="style-scope gr-diff blame"></td> - <td class="style-scope gr-diff left"></td> - <td class="style-scope gr-diff left content"> - <div>${this.left?.text ?? ''}</div> - </td> - <td class="style-scope gr-diff right"></td> - <td class="style-scope gr-diff right content"> - <div>${this.right?.text ?? ''}</div> - </td> - </tr> - `; - } - - override render() { - if (!this.left || !this.right) return; - if (!this.isVisible) return this.renderInvisible(); - const row = html` - <tr - ${ref(this.tableRowRef)} - class=${diffClasses('diff-row', 'side-by-side')} - left-type=${this.left.type} - right-type=${this.right.type} - tabindex="-1" - > - ${this.renderBlameCell()} ${this.renderLineNumberCell(Side.LEFT)} - ${this.renderContentCell(Side.LEFT)} - ${this.renderLineNumberCell(Side.RIGHT)} - ${this.renderContentCell(Side.RIGHT)} - </tr> - `; - if (this.addTableWrapperForTesting) { - return html`<table> - ${row} - </table>`; - } - return row; - } - - getTableRow(): HTMLTableRowElement | undefined { - return this.tableRowRef.value; - } - - getLineNumberCell(side: Side): HTMLTableCellElement | undefined { - return this.lineNumberRef(side).value; - } - - getContentCell(side: Side) { - const div = this.contentRef(side)?.value; - if (!div) return undefined; - return div.parentElement as HTMLTableCellElement; - } - - getBlameCell() { - return this.blameCellRef.value; - } - - private renderBlameCell() { - // td.blame has `white-space: pre`, so prettier must not add spaces. - // prettier-ignore - return html` - <td - ${ref(this.blameCellRef)} - class=${diffClasses('blame')} - data-line-number=${this.left?.beforeNumber ?? 0} - >${this.renderBlameElement()}</td> - `; - } - - private renderBlameElement() { - const lineNum = this.left?.beforeNumber; - const commit = this.blameInfo; - if (!lineNum || !commit) return; - - const isStartOfRange = commit.ranges.some(r => r.start === lineNum); - const extras: string[] = []; - if (isStartOfRange) extras.push('startOfRange'); - const date = new Date(commit.time * 1000).toLocaleDateString(); - const shortName = commit.author.split(' ')[0]; - const url = `${getBaseUrl()}/q/${commit.id}`; - - // td.blame has `white-space: pre`, so prettier must not add spaces. - // prettier-ignore - return html`<span class=${diffClasses(...extras)} - ><a href=${url} class=${diffClasses('blameDate')}>${date}</a - ><span class=${diffClasses('blameAuthor')}> ${shortName}</span - ><gr-hovercard class=${diffClasses()}> - <span class=${diffClasses('blameHoverCard')}> - Commit ${commit.id}<br /> - Author: ${commit.author}<br /> - Date: ${date}<br /> - <br /> - ${commit.commit_msg} - </span> - </gr-hovercard - ></span>`; - } - - private renderLineNumberCell(side: Side): TemplateResult { - const line = this.line(side); - const lineNumber = this.lineNumber(side); - if (!line || !lineNumber || line.type === GrDiffLineType.BLANK) { - return html`<td - ${ref(this.lineNumberRef(side))} - class=${diffClasses(side)} - ></td>`; - } - - return html`<td - ${ref(this.lineNumberRef(side))} - class=${diffClasses(side, 'lineNum')} - data-value=${lineNumber} - > - ${this.renderLineNumberButton(line, lineNumber, side)} - </td>`; - } - - private renderLineNumberButton( - line: GrDiffLine, - lineNumber: LineNumber, - side: Side - ) { - if (this.hideFileCommentButton && lineNumber === 'FILE') return; - if (lineNumber === 'LOST') return; - // .lineNumButton has `white-space: pre`, so prettier must not add spaces. - // prettier-ignore - return html` - <button - class=${diffClasses('lineNumButton', side)} - tabindex="-1" - data-value=${lineNumber} - aria-label=${ifDefined( - this.computeLineNumberAriaLabel(line, lineNumber) - )} - @mouseenter=${() => - fire(this, 'line-mouse-enter', {lineNum: lineNumber, side})} - @mouseleave=${() => - fire(this, 'line-mouse-leave', {lineNum: lineNumber, side})} - >${lineNumber === 'FILE' ? 'File' : lineNumber.toString()}</button> - `; - } - - private computeLineNumberAriaLabel(line: GrDiffLine, lineNumber: LineNumber) { - if (lineNumber === 'FILE') return 'Add file comment'; - - // Add aria-labels for valid line numbers. - // For unified diff, this method will be called with number set to 0 for - // the empty line number column for added/removed lines. This should not - // be announced to the screenreader. - if (lineNumber <= 0) return undefined; - - switch (line.type) { - case GrDiffLineType.REMOVE: - return `${lineNumber} removed`; - case GrDiffLineType.ADD: - return `${lineNumber} added`; - case GrDiffLineType.BOTH: - case GrDiffLineType.BLANK: - return undefined; - } - } - - private renderContentCell(side: Side): TemplateResult { - const line = this.line(side); - const lineNumber = this.lineNumber(side); - assertIsDefined(line, 'line'); - const extras: string[] = [line.type, side]; - if (line.type !== GrDiffLineType.BLANK) extras.push('content'); - if (!line.hasIntralineInfo) extras.push('no-intraline-info'); - if (line.beforeNumber === 'FILE') extras.push('file'); - if (line.beforeNumber === 'LOST') extras.push('lost'); - - // .content has `white-space: pre`, so prettier must not add spaces. - // prettier-ignore - return html` - <td - class=${diffClasses(...extras)} - @mouseenter=${() => { - if (lineNumber) - fire(this, 'line-mouse-enter', {lineNum: lineNumber, side}); - }} - @mouseleave=${() => { - if (lineNumber) - fire(this, 'line-mouse-leave', {lineNum: lineNumber, side}); - }} - >${this.renderText(side)}${this.renderThreadGroup(side, lineNumber)}</td> - `; - } - - private renderThreadGroup(side: Side, lineNumber?: LineNumber) { - if (!lineNumber) return; - // TODO: For the LOST line number the convention is that a <tr> will always - // be rendered, but it will not be visible, because of all cells being - // empty. For this to work with lit-based rendering we may only render a - // thread-group and a <slot> when there is a thread using that slot. The - // cleanest solution for that is probably introducing a gr-diff-model, where - // each diff row can look up or observe comment threads. - // .content has `white-space: pre`, so prettier must not add spaces. - // prettier-ignore - return html`<div class="thread-group" data-side=${side}><slot name="${side}-${lineNumber}"></slot></div>`; - } - - private contentRef(side: Side) { - return side === Side.LEFT ? this.contentLeftRef : this.contentRightRef; - } - - private lineNumberRef(side: Side) { - return side === Side.LEFT - ? this.lineNumberLeftRef - : this.lineNumberRightRef; - } - - private lineNumber(side: Side) { - return this.line(side)?.lineNumber(side); - } - - private line(side: Side) { - return side === Side.LEFT ? this.left : this.right; - } - - /** - * Returns a 'div' element containing the supplied |text| as its innerText, - * with '\t' characters expanded to a width determined by |tabSize|, and the - * text wrapped at column |lineLimit|, which may be Infinity if no wrapping is - * desired. - */ - private renderText(side: Side) { - const line = this.line(side); - const lineNumber = this.lineNumber(side); - if (lineNumber === 'FILE' || lineNumber === 'LOST') return; - // prettier-ignore - const textElement = line?.text - ? html`<gr-diff-text - ${ref(this.contentRef(side))} - .text=${line?.text} - .tabSize=${this.tabSize} - .lineLimit=${this.lineLength} - .isResponsive=${isResponsive(this.responsiveMode)} - ></gr-diff-text>` : ''; - // .content has `white-space: pre`, so prettier must not add spaces. - // prettier-ignore - return html`<div - class=${diffClasses('contentText', side)} - .ariaLabel=${line?.text ?? ''} - data-side=${ifDefined(side)} - >${textElement}</div>`; - } -} - -declare global { - interface HTMLElementTagNameMap { - 'gr-diff-row': GrDiffRow; - } -} diff --git a/polygerrit-ui/app/embed/diff/gr-diff-builder/gr-diff-row_test.ts b/polygerrit-ui/app/embed/diff/gr-diff-builder/gr-diff-row_test.ts deleted file mode 100644 index 757d906f61..0000000000 --- a/polygerrit-ui/app/embed/diff/gr-diff-builder/gr-diff-row_test.ts +++ /dev/null @@ -1,195 +0,0 @@ -/** - * @license - * Copyright 2022 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ -import '../../../test/common-test-setup-karma'; -import './gr-diff-row'; -import {GrDiffRow} from './gr-diff-row'; -import {html} from 'lit'; -import {fixture} from '@open-wc/testing-helpers'; -import {GrDiffLine} from '../gr-diff/gr-diff-line'; -import {GrDiffLineType} from '../../../api/diff'; - -suite('gr-diff-row test', () => { - let element: GrDiffRow; - - setup(async () => { - element = await fixture<GrDiffRow>(html`<gr-diff-row></gr-diff-row>`); - element.isVisible = true; - element.addTableWrapperForTesting = true; - await element.updateComplete; - }); - - test('both', async () => { - const line = new GrDiffLine(GrDiffLineType.BOTH, 1, 1); - line.text = 'lorem ipsum'; - element.left = line; - element.right = line; - await element.updateComplete; - expect(element).lightDom.to.equal(/* HTML */ ` - <table> - <tbody> - <tr - class="diff-row gr-diff side-by-side style-scope" - left-type="both" - right-type="both" - tabindex="-1" - > - <td class="blame gr-diff style-scope" data-line-number="1"></td> - <td class="gr-diff left lineNum style-scope" data-value="1"> - <button - class="gr-diff left lineNumButton style-scope" - data-value="1" - tabindex="-1" - > - 1 - </button> - </td> - <td class="both content gr-diff left no-intraline-info style-scope"> - <div - aria-label="lorem ipsum" - class="contentText gr-diff left style-scope" - data-side="left" - > - <gr-diff-text>lorem ipsum</gr-diff-text> - </div> - <div class="thread-group" data-side="left"> - <slot name="left-1"> </slot> - </div> - </td> - <td class="gr-diff lineNum right style-scope" data-value="1"> - <button - class="gr-diff lineNumButton right style-scope" - data-value="1" - tabindex="-1" - > - 1 - </button> - </td> - <td - class="both content gr-diff no-intraline-info right style-scope" - > - <div - aria-label="lorem ipsum" - class="contentText gr-diff right style-scope" - data-side="right" - > - <gr-diff-text>lorem ipsum</gr-diff-text> - </div> - <div class="thread-group" data-side="right"> - <slot name="right-1"> </slot> - </div> - </td> - </tr> - </tbody> - </table> - `); - }); - - test('add', async () => { - const line = new GrDiffLine(GrDiffLineType.ADD, 0, 1); - line.text = 'lorem ipsum'; - element.left = new GrDiffLine(GrDiffLineType.BLANK); - element.right = line; - await element.updateComplete; - expect(element).lightDom.to.equal(/* HTML */ ` - <table> - <tbody> - <tr - class="diff-row gr-diff side-by-side style-scope" - left-type="blank" - right-type="add" - tabindex="-1" - > - <td class="blame gr-diff style-scope" data-line-number="0"></td> - <td class="gr-diff left style-scope"></td> - <td class="blank gr-diff left no-intraline-info style-scope"> - <div - aria-label="" - class="contentText gr-diff left style-scope" - data-side="left" - ></div> - </td> - <td class="gr-diff lineNum right style-scope" data-value="1"> - <button - aria-label="1 added" - class="gr-diff lineNumButton right style-scope" - data-value="1" - tabindex="-1" - > - 1 - </button> - </td> - <td class="add content gr-diff no-intraline-info right style-scope"> - <div - aria-label="lorem ipsum" - class="contentText gr-diff right style-scope" - data-side="right" - > - <gr-diff-text>lorem ipsum</gr-diff-text> - </div> - <div class="thread-group" data-side="right"> - <slot name="right-1"> </slot> - </div> - </td> - </tr> - </tbody> - </table> - `); - }); - - test('remove', async () => { - const line = new GrDiffLine(GrDiffLineType.REMOVE, 1, 0); - line.text = 'lorem ipsum'; - element.left = line; - element.right = new GrDiffLine(GrDiffLineType.BLANK); - await element.updateComplete; - expect(element).lightDom.to.equal(/* HTML */ ` - <table> - <tbody> - <tr - class="diff-row gr-diff side-by-side style-scope" - left-type="remove" - right-type="blank" - tabindex="-1" - > - <td class="blame gr-diff style-scope" data-line-number="1"></td> - <td class="gr-diff left lineNum style-scope" data-value="1"> - <button - aria-label="1 removed" - class="gr-diff left lineNumButton style-scope" - data-value="1" - tabindex="-1" - > - 1 - </button> - </td> - <td - class="content gr-diff left no-intraline-info remove style-scope" - > - <div - aria-label="lorem ipsum" - class="contentText gr-diff left style-scope" - data-side="left" - > - <gr-diff-text>lorem ipsum</gr-diff-text> - </div> - <div class="thread-group" data-side="left"> - <slot name="left-1"> </slot> - </div> - </td> - <td class="gr-diff right style-scope"></td> - <td class="blank gr-diff no-intraline-info right style-scope"> - <div - aria-label="" - class="contentText gr-diff right style-scope" - data-side="right" - ></div> - </td> - </tr> - </tbody> - </table> - `); - }); -}); diff --git a/polygerrit-ui/app/embed/diff/gr-diff-builder/gr-diff-section.ts b/polygerrit-ui/app/embed/diff/gr-diff-builder/gr-diff-section.ts deleted file mode 100644 index b11d767558..0000000000 --- a/polygerrit-ui/app/embed/diff/gr-diff-builder/gr-diff-section.ts +++ /dev/null @@ -1,240 +0,0 @@ -/** - * @license - * Copyright 2022 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ -import {html, LitElement} from 'lit'; -import {customElement, property, state} from 'lit/decorators'; -import { - DiffInfo, - DiffLayer, - DiffViewMode, - MovedLinkClickedEventDetail, - RenderPreferences, - Side, - LineNumber, - DiffPreferencesInfo, -} from '../../../api/diff'; -import {GrDiffGroup, GrDiffGroupType} from '../gr-diff/gr-diff-group'; -import {countLines, diffClasses} from '../gr-diff/gr-diff-utils'; -import {GrDiffRow} from './gr-diff-row'; -import '../gr-context-controls/gr-context-controls-section'; -import '../gr-context-controls/gr-context-controls'; -import '../gr-range-header/gr-range-header'; -import './gr-diff-row'; -import {whenVisible} from '../../../utils/dom-util'; - -@customElement('gr-diff-section') -export class GrDiffSection extends LitElement { - @property({type: Object}) - group?: GrDiffGroup; - - @property({type: Object}) - diff?: DiffInfo; - - @property({type: Object}) - renderPrefs?: RenderPreferences; - - @property({type: Object}) - diffPrefs?: DiffPreferencesInfo; - - @property({type: Object}) - layers: DiffLayer[] = []; - - /** - * While not visible we are trying to optimize rendering performance by - * rendering a simpler version of the diff. - */ - @state() - isVisible = false; - - /** - * Semantic DOM diff testing does not work with just table fragments, so when - * running such tests the render() method has to wrap the DOM in a proper - * <table> element. - */ - @state() - addTableWrapperForTesting = false; - - /** - * The browser API for handling selection does not (yet) work for selection - * across multiple shadow DOM elements. So we are rendering gr-diff components - * into the light DOM instead of the shadow DOM by overriding this method, - * which was the recommended workaround by the lit team. - * See also https://github.com/WICG/webcomponents/issues/79. - */ - override createRenderRoot() { - return this; - } - - override connectedCallback() { - super.connectedCallback(); - // TODO: Refine this obviously simplistic approach to optimized rendering. - whenVisible(this.parentElement!, () => (this.isVisible = true), 1000); - } - - override render() { - if (!this.group) return; - const extras: string[] = []; - extras.push('section'); - extras.push(this.group.type); - if (this.group.isTotal()) extras.push('total'); - if (this.group.dueToRebase) extras.push('dueToRebase'); - if (this.group.moveDetails) extras.push('dueToMove'); - if (this.group.ignoredWhitespaceOnly) extras.push('ignoredWhitespaceOnly'); - - const isControl = this.group.type === GrDiffGroupType.CONTEXT_CONTROL; - const pairs = isControl ? [] : this.group.getSideBySidePairs(); - const body = html` - <tbody class=${diffClasses(...extras)}> - ${this.renderContextControls()} ${this.renderMoveControls()} - ${pairs.map(pair => { - const leftCl = `left-${pair.left.lineNumber(Side.LEFT)}`; - const rightCl = `right-${pair.right.lineNumber(Side.RIGHT)}`; - return html` - <gr-diff-row - class="${leftCl} ${rightCl}" - .left=${pair.left} - .right=${pair.right} - .layers=${this.layers} - .lineLength=${this.diffPrefs?.line_length ?? 80} - .tabSize=${this.diffPrefs?.tab_size ?? 2} - .isVisible=${this.isVisible} - > - </gr-diff-row> - `; - })} - </tbody> - `; - if (this.addTableWrapperForTesting) { - return html`<table> - ${body} - </table>`; - } - return body; - } - - getDiffRows(): GrDiffRow[] { - return [...this.querySelectorAll<GrDiffRow>('gr-diff-row')]; - } - - private renderContextControls() { - if (this.group?.type !== GrDiffGroupType.CONTEXT_CONTROL) return; - - const leftStart = this.group.lineRange.left.start_line; - const leftEnd = this.group.lineRange.left.end_line; - const firstGroupIsSkipped = !!this.group.contextGroups[0].skip; - const lastGroupIsSkipped = - !!this.group.contextGroups[this.group.contextGroups.length - 1].skip; - const lineCountLeft = countLines(this.diff, Side.LEFT); - const containsWholeFile = lineCountLeft === leftEnd - leftStart + 1; - const showAbove = - (leftStart > 1 && !firstGroupIsSkipped) || containsWholeFile; - const showBelow = leftEnd < lineCountLeft && !lastGroupIsSkipped; - - return html` - <gr-context-controls-section - .showAbove=${showAbove} - .showBelow=${showBelow} - .group=${this.group} - .diff=${this.diff} - .renderPrefs=${this.renderPrefs} - .viewMode=${DiffViewMode.SIDE_BY_SIDE} - > - </gr-context-controls-section> - `; - } - - findRow(side: Side, lineNumber: LineNumber): GrDiffRow | undefined { - return ( - this.querySelector<GrDiffRow>(`gr-diff-row.${side}-${lineNumber}`) ?? - undefined - ); - } - - private renderMoveControls() { - if (!this.group?.moveDetails) return; - const movedIn = this.group.adds.length > 0; - const plainCell = html`<td class=${diffClasses()}></td>`; - const lineNumberCell = html` - <td class=${diffClasses('moveControlsLineNumCol')}></td> - `; - const moveCell = html` - <td class=${diffClasses('moveHeader')}> - <gr-range-header class=${diffClasses()} icon="gr-icons:move-item"> - ${this.renderMoveDescription(movedIn)} - </gr-range-header> - </td> - `; - return html` - <tr - class=${diffClasses('moveControls', movedIn ? 'movedIn' : 'movedOut')} - > - ${lineNumberCell} ${movedIn ? plainCell : moveCell} ${lineNumberCell} - ${movedIn ? moveCell : plainCell} - </tr> - `; - } - - private renderMoveDescription(movedIn: boolean) { - if (this.group?.moveDetails?.range) { - const {changed, range} = this.group.moveDetails; - const otherSide = movedIn ? Side.LEFT : Side.RIGHT; - const andChangedLabel = changed ? 'and changed ' : ''; - const direction = movedIn ? 'from' : 'to'; - const textLabel = `Moved ${andChangedLabel}${direction} lines `; - return html` - <div class=${diffClasses()}> - <span class=${diffClasses()}>${textLabel}</span> - ${this.renderMovedLineAnchor(range.start, otherSide)} - <span class=${diffClasses()}> - </span> - ${this.renderMovedLineAnchor(range.end, otherSide)} - </div> - `; - } - - return html` - <div class=${diffClasses()}> - <span class=${diffClasses()} - >${movedIn ? 'Moved in' : 'Moved out'}</span - > - </div> - `; - } - - private renderMovedLineAnchor(line: number, side: Side) { - const listener = (e: MouseEvent) => { - e.preventDefault(); - this.handleMovedLineAnchorClick(e.target, side, line); - }; - // `href` is not actually used but important for Screen Readers - return html` - <a class=${diffClasses()} href=${`#${line}`} @click=${listener} - >${line}</a - > - `; - } - - private handleMovedLineAnchorClick( - anchor: EventTarget | null, - side: Side, - line: number - ) { - anchor?.dispatchEvent( - new CustomEvent<MovedLinkClickedEventDetail>('moved-link-clicked', { - detail: { - lineNum: line, - side, - }, - composed: true, - bubbles: true, - }) - ); - } -} - -declare global { - interface HTMLElementTagNameMap { - 'gr-diff-section': GrDiffSection; - } -} diff --git a/polygerrit-ui/app/embed/diff/gr-diff-builder/gr-diff-section_test.ts b/polygerrit-ui/app/embed/diff/gr-diff-builder/gr-diff-section_test.ts deleted file mode 100644 index 88c0e8386e..0000000000 --- a/polygerrit-ui/app/embed/diff/gr-diff-builder/gr-diff-section_test.ts +++ /dev/null @@ -1,213 +0,0 @@ -/** - * @license - * Copyright 2022 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ -import '../../../test/common-test-setup-karma'; -import './gr-diff-section'; -import {GrDiffSection} from './gr-diff-section'; -import {html} from 'lit'; -import {fixture} from '@open-wc/testing-helpers'; -import {GrDiffGroup, GrDiffGroupType} from '../gr-diff/gr-diff-group'; -import {GrDiffLine} from '../gr-diff/gr-diff-line'; -import {GrDiffLineType} from '../../../api/diff'; - -suite('gr-diff-section test', () => { - let element: GrDiffSection; - - setup(async () => { - element = await fixture<GrDiffSection>( - html`<gr-diff-section></gr-diff-section>` - ); - element.addTableWrapperForTesting = true; - element.isVisible = true; - await element.updateComplete; - }); - - test('3 normal unchanged rows', async () => { - const lines = [ - new GrDiffLine(GrDiffLineType.BOTH, 1, 1), - new GrDiffLine(GrDiffLineType.BOTH, 1, 1), - new GrDiffLine(GrDiffLineType.BOTH, 1, 1), - ]; - lines[0].text = 'asdf'; - lines[1].text = 'qwer'; - lines[2].text = 'zxcv'; - const group = new GrDiffGroup({type: GrDiffGroupType.BOTH, lines}); - element.group = group; - await element.updateComplete; - expect(element).dom.to.equal(/* HTML */ ` - <gr-diff-section> - <gr-diff-row class="left-1 right-1"> </gr-diff-row> - <gr-diff-row class="left-1 right-1"> </gr-diff-row> - <gr-diff-row class="left-1 right-1"> </gr-diff-row> - <table> - <tbody class="both gr-diff section style-scope"> - <tr - class="diff-row gr-diff side-by-side style-scope" - left-type="both" - right-type="both" - tabindex="-1" - > - <td class="blame gr-diff style-scope" data-line-number="1"></td> - <td class="gr-diff left lineNum style-scope" data-value="1"> - <button - class="gr-diff left lineNumButton style-scope" - data-value="1" - tabindex="-1" - > - 1 - </button> - </td> - <td - class="both content gr-diff left no-intraline-info style-scope" - > - <div - aria-label="asdf" - class="contentText gr-diff left style-scope" - data-side="left" - > - <gr-diff-text></gr-diff-text> - </div> - <div class="thread-group" data-side="left"> - <slot name="left-1"> </slot> - </div> - </td> - <td class="gr-diff lineNum right style-scope" data-value="1"> - <button - class="gr-diff lineNumButton right style-scope" - data-value="1" - tabindex="-1" - > - 1 - </button> - </td> - <td - class="both content gr-diff no-intraline-info right style-scope" - > - <div - aria-label="asdf" - class="contentText gr-diff right style-scope" - data-side="right" - > - <gr-diff-text></gr-diff-text> - </div> - <div class="thread-group" data-side="right"> - <slot name="right-1"> </slot> - </div> - </td> - </tr> - <tr - class="diff-row gr-diff side-by-side style-scope" - left-type="both" - right-type="both" - tabindex="-1" - > - <td class="blame gr-diff style-scope" data-line-number="1"></td> - <td class="gr-diff left lineNum style-scope" data-value="1"> - <button - class="gr-diff left lineNumButton style-scope" - data-value="1" - tabindex="-1" - > - 1 - </button> - </td> - <td - class="both content gr-diff left no-intraline-info style-scope" - > - <div - aria-label="qwer" - class="contentText gr-diff left style-scope" - data-side="left" - > - <gr-diff-text></gr-diff-text> - </div> - <div class="thread-group" data-side="left"> - <slot name="left-1"> </slot> - </div> - </td> - <td class="gr-diff lineNum right style-scope" data-value="1"> - <button - class="gr-diff lineNumButton right style-scope" - data-value="1" - tabindex="-1" - > - 1 - </button> - </td> - <td - class="both content gr-diff no-intraline-info right style-scope" - > - <div - aria-label="qwer" - class="contentText gr-diff right style-scope" - data-side="right" - > - <gr-diff-text></gr-diff-text> - </div> - <div class="thread-group" data-side="right"> - <slot name="right-1"> </slot> - </div> - </td> - </tr> - <tr - class="diff-row gr-diff side-by-side style-scope" - left-type="both" - right-type="both" - tabindex="-1" - > - <td class="blame gr-diff style-scope" data-line-number="1"></td> - <td class="gr-diff left lineNum style-scope" data-value="1"> - <button - class="gr-diff left lineNumButton style-scope" - data-value="1" - tabindex="-1" - > - 1 - </button> - </td> - <td - class="both content gr-diff left no-intraline-info style-scope" - > - <div - aria-label="zxcv" - class="contentText gr-diff left style-scope" - data-side="left" - > - <gr-diff-text></gr-diff-text> - </div> - <div class="thread-group" data-side="left"> - <slot name="left-1"> </slot> - </div> - </td> - <td class="gr-diff lineNum right style-scope" data-value="1"> - <button - class="gr-diff lineNumButton right style-scope" - data-value="1" - tabindex="-1" - > - 1 - </button> - </td> - <td - class="both content gr-diff no-intraline-info right style-scope" - > - <div - aria-label="zxcv" - class="contentText gr-diff right style-scope" - data-side="right" - > - <gr-diff-text></gr-diff-text> - </div> - <div class="thread-group" data-side="right"> - <slot name="right-1"> </slot> - </div> - </td> - </tr> - </tbody> - </table> - </gr-diff-section> - `); - }); -}); diff --git a/polygerrit-ui/app/embed/diff/gr-diff-builder/gr-diff-text.ts b/polygerrit-ui/app/embed/diff/gr-diff-builder/gr-diff-text.ts deleted file mode 100644 index bb37c43f55..0000000000 --- a/polygerrit-ui/app/embed/diff/gr-diff-builder/gr-diff-text.ts +++ /dev/null @@ -1,138 +0,0 @@ -/** - * @license - * Copyright 2022 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ -import {LitElement, html, TemplateResult} from 'lit'; -import {customElement, property} from 'lit/decorators'; -import {diffClasses} from '../gr-diff/gr-diff-utils'; - -const SURROGATE_PAIR = /[\uD800-\uDBFF][\uDC00-\uDFFF]/; - -const TAB = '\t'; - -@customElement('gr-diff-text') -export class GrDiffText extends LitElement { - /** - * The browser API for handling selection does not (yet) work for selection - * across multiple shadow DOM elements. So we are rendering gr-diff components - * into the light DOM instead of the shadow DOM by overriding this method, - * which was the recommended workaround by the lit team. - * See also https://github.com/WICG/webcomponents/issues/79. - */ - override createRenderRoot() { - return this; - } - - @property({type: String}) - text = ''; - - @property({type: Boolean}) - isResponsive = false; - - @property({type: Number}) - tabSize = 2; - - @property({type: Number}) - lineLimit = 80; - - /** Temporary state while rendering. */ - private textOffset = 0; - - /** Temporary state while rendering. */ - private columnPos = 0; - - /** Temporary state while rendering. */ - private pieces: (string | TemplateResult)[] = []; - - /** Split up the string into tabs, surrogate pairs and regular segments. */ - override render() { - this.textOffset = 0; - this.columnPos = 0; - this.pieces = []; - const splitByTab = this.text.split('\t'); - for (let i = 0; i < splitByTab.length; i++) { - const splitBySurrogate = splitByTab[i].split(SURROGATE_PAIR); - for (let j = 0; j < splitBySurrogate.length; j++) { - this.renderSegment(splitBySurrogate[j]); - if (j < splitBySurrogate.length - 1) { - this.renderSurrogatePair(); - } - } - if (i < splitByTab.length - 1) { - this.renderTab(); - } - } - if (this.textOffset !== this.text.length) throw new Error('unfinished'); - return this.pieces; - } - - /** Render regular characters, but insert line breaks appropriately. */ - private renderSegment(segment: string) { - let segmentOffset = 0; - while (segmentOffset < segment.length) { - const newOffset = Math.min( - segment.length, - segmentOffset + this.lineLimit - this.columnPos - ); - this.renderString(segment.substring(segmentOffset, newOffset)); - segmentOffset = newOffset; - if (segmentOffset < segment.length && this.columnPos === this.lineLimit) { - this.renderLineBreak(); - } - } - } - - /** Render regular characters. */ - private renderString(s: string) { - if (s.length === 0) return; - this.pieces.push(s); - this.textOffset += s.length; - this.columnPos += s.length; - if (this.columnPos > this.lineLimit) throw new Error('over line limit'); - } - - /** Render a tab character. */ - private renderTab() { - let tabSize = this.tabSize - (this.columnPos % this.tabSize); - if (this.columnPos + tabSize > this.lineLimit) { - this.renderLineBreak(); - tabSize = this.tabSize; - } - const piece = html`<span - class=${diffClasses('tab')} - style="tab-size: ${tabSize}; -moz-tab-size: ${tabSize};" - >${TAB}</span - >`; - this.pieces.push(piece); - this.textOffset += 1; - this.columnPos += tabSize; - } - - /** Render a surrogate pair: string length is 2, but is just 1 char. */ - private renderSurrogatePair() { - if (this.columnPos === this.lineLimit) { - this.renderLineBreak(); - } - this.pieces.push(this.text.substring(this.textOffset, this.textOffset + 2)); - this.textOffset += 2; - this.columnPos += 1; - } - - /** Render a line break, don't advance text offset, reset col position. */ - private renderLineBreak() { - if (this.isResponsive) { - this.pieces.push(html`<wbr class=${diffClasses()}></wbr>`); - } else { - this.pieces.push(html`<span class=${diffClasses('br')}></span>`); - } - // this.textOffset += 0; - this.columnPos = 0; - } -} - -declare global { - interface HTMLElementTagNameMap { - 'gr-diff-text': GrDiffText; - } -} diff --git a/polygerrit-ui/app/embed/diff/gr-diff-builder/gr-diff-text_test.ts b/polygerrit-ui/app/embed/diff/gr-diff-builder/gr-diff-text_test.ts deleted file mode 100644 index 21c0936cef..0000000000 --- a/polygerrit-ui/app/embed/diff/gr-diff-builder/gr-diff-text_test.ts +++ /dev/null @@ -1,154 +0,0 @@ -/** - * @license - * Copyright 2022 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ -import '../../../test/common-test-setup-karma'; -import './gr-diff-text'; -import {GrDiffText} from './gr-diff-text'; -import {html} from 'lit'; -import {fixture} from '@open-wc/testing-helpers'; - -const LINE_BREAK = '<span class="style-scope gr-diff br"></span>'; - -const TAB = '<span class="" style=""></span>'; - -const TAB_IGNORE = ['class', 'style']; - -suite('gr-diff-text test', () => { - let element: GrDiffText; - - setup(async () => { - element = await fixture<GrDiffText>(html`<gr-diff-text></gr-diff-text>`); - await element.updateComplete; - }); - - const check = async ( - text: string, - html: string, - ignoreAttributes: string[] = [] - ) => { - element.text = text; - element.tabSize = 4; - element.lineLimit = 10; - await element.updateComplete; - expect(element).lightDom.to.equal(html, {ignoreAttributes}); - }; - - suite('lit rendering', () => { - test('renderText newlines 1', () => { - check('abcdef', 'abcdef'); - check('a'.repeat(20), `aaaaaaaaaa${LINE_BREAK}aaaaaaaaaa`); - }); - - test('renderText newlines 2', () => { - check( - '<span class="thumbsup">👍</span>', - '<span clas' + - LINE_BREAK + - 's="thumbsu' + - LINE_BREAK + - 'p">👍</span' + - LINE_BREAK + - '>' - ); - }); - - test('renderText newlines 3', () => { - check( - '01234\t56789', - '01234' + TAB + '56' + LINE_BREAK + '789', - TAB_IGNORE - ); - }); - - test('renderText newlines 4', async () => { - element.lineLimit = 20; - await element.updateComplete; - check( - '👍'.repeat(58), - '👍'.repeat(20) + - LINE_BREAK + - '👍'.repeat(20) + - LINE_BREAK + - '👍'.repeat(18) - ); - }); - - test('tab wrapper style', async () => { - for (const size of [1, 3, 8, 55]) { - element.tabSize = size; - await element.updateComplete; - check( - '\t', - /* HTML */ ` - <span - class="style-scope gr-diff tab" - style="tab-size: ${size}; -moz-tab-size: ${size};" - > - </span> - ` - ); - } - }); - - test('tab wrapper insertion', () => { - check('abc\tdef', 'abc' + TAB + 'def', TAB_IGNORE); - }); - - test('escaping HTML', async () => { - element.lineLimit = 100; - await element.updateComplete; - check( - '<script>alert("XSS");<' + '/script>', - '<script>alert("XSS");</script>' - ); - check('& < > " \' / `', '& < > " \' / `'); - }); - - test('text length with tabs and unicode', async () => { - async function expectTextLength( - text: string, - tabSize: number, - expected: number - ) { - element.text = text; - element.tabSize = tabSize; - element.lineLimit = expected; - await element.updateComplete; - const result = element.innerHTML; - - // Must not contain a line break. - assert.isNotOk(element.querySelector('span.br')); - - // Increasing the line limit by 1 should not change anything. - element.lineLimit = expected + 1; - await element.updateComplete; - const resultPlusOne = element.innerHTML; - assert.equal(resultPlusOne, result); - - // Increasing the line limit to infinity should not change anything. - element.lineLimit = Infinity; - await element.updateComplete; - const resultInf = element.innerHTML; - assert.equal(resultInf, result); - - // Decreasing the line limit by 1 should introduce a line break. - element.lineLimit = expected + 1; - await element.updateComplete; - assert.isNotOk(element.querySelector('span.br')); - } - expectTextLength('12345', 4, 5); - expectTextLength('\t\t12', 4, 10); - expectTextLength('abc💢123', 4, 7); - expectTextLength('abc\t', 8, 8); - expectTextLength('abc\t\t', 10, 20); - expectTextLength('', 10, 0); - // 17 Thai combining chars. - expectTextLength('ก้้้้้้้้้้้้้้้้', 4, 17); - expectTextLength('abc\tde', 10, 12); - expectTextLength('abc\tde\t', 10, 20); - expectTextLength('\t\t\t\t\t', 20, 100); - }); - }); -}); diff --git a/polygerrit-ui/app/embed/diff/gr-diff-cursor/gr-diff-cursor.ts b/polygerrit-ui/app/embed/diff/gr-diff-cursor/gr-diff-cursor.ts index 4ecdcb0a78..dfe8a15d69 100644 --- a/polygerrit-ui/app/embed/diff/gr-diff-cursor/gr-diff-cursor.ts +++ b/polygerrit-ui/app/embed/diff/gr-diff-cursor/gr-diff-cursor.ts @@ -228,7 +228,6 @@ export class GrDiffCursor implements GrDiffCursorApi { path?: string, intentionalMove?: boolean ) { - this._updateStops(); const row = this._findRowByNumberAndFile(number, side, path); if (row) { this.side = side; diff --git a/polygerrit-ui/app/embed/diff/gr-diff-selection/gr-diff-selection.ts b/polygerrit-ui/app/embed/diff/gr-diff-selection/gr-diff-selection.ts index 22af7e3e45..2665ef0cdd 100644 --- a/polygerrit-ui/app/embed/diff/gr-diff-selection/gr-diff-selection.ts +++ b/polygerrit-ui/app/embed/diff/gr-diff-selection/gr-diff-selection.ts @@ -23,11 +23,7 @@ import { normalize, NormalizedRange, } from '../gr-diff-highlight/gr-range-normalizer'; -import { - descendedFromClass, - isElementTarget, - querySelectorAll, -} from '../../../utils/dom-util'; +import {descendedFromClass, querySelectorAll} from '../../../utils/dom-util'; import {customElement, property, observe} from '@polymer/decorators'; import {DiffInfo} from '../../../types/diff'; import {Side} from '../../../constants/constants'; @@ -113,9 +109,8 @@ export class GrDiffSelection extends PolymerElement { } _handleDown(e: Event) { - const target = e.composedPath()[0]; - if (!isElementTarget(target)) return; - + const target = e.target; + if (!(target instanceof Element)) return; // Handle the down event on comment thread in Polymer 2 const handled = this._handleDownOnRangeComment(target); if (handled) return; diff --git a/polygerrit-ui/app/embed/diff/gr-diff/gr-diff-line.ts b/polygerrit-ui/app/embed/diff/gr-diff/gr-diff-line.ts index 8593e1b30d..29271018e6 100644 --- a/polygerrit-ui/app/embed/diff/gr-diff/gr-diff-line.ts +++ b/polygerrit-ui/app/embed/diff/gr-diff/gr-diff-line.ts @@ -19,7 +19,6 @@ import { GrDiffLine as GrDiffLineApi, GrDiffLineType, LineNumber, - Side, } from '../../../api/diff'; export {GrDiffLineType, LineNumber}; @@ -39,10 +38,6 @@ export class GrDiffLine implements GrDiffLineApi { text = ''; - lineNumber(side: Side) { - return side === Side.LEFT ? this.beforeNumber : this.afterNumber; - } - // TODO(TS): remove this properties static readonly Type = GrDiffLineType; diff --git a/polygerrit-ui/app/embed/diff/gr-diff/gr-diff-utils.ts b/polygerrit-ui/app/embed/diff/gr-diff/gr-diff-utils.ts index a12867f9c7..182d48e490 100644 --- a/polygerrit-ui/app/embed/diff/gr-diff/gr-diff-utils.ts +++ b/polygerrit-ui/app/embed/diff/gr-diff/gr-diff-utils.ts @@ -45,20 +45,12 @@ import {getBaseUrl} from '../../../utils/url-util'; * Graphemes: http://unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries * A proposed JS API: https://github.com/tc39/proposal-intl-segmenter */ -export const REGEX_TAB_OR_SURROGATE_PAIR = /\t|[\uD800-\uDBFF][\uDC00-\uDFFF]/; +const REGEX_TAB_OR_SURROGATE_PAIR = /\t|[\uD800-\uDBFF][\uDC00-\uDFFF]/; // If any line of the diff is more than the character limit, then disable // syntax highlighting for the entire file. export const SYNTAX_MAX_LINE_LENGTH = 500; -export function countLines(diff?: DiffInfo, side?: Side) { - if (!diff?.content || !side) return 0; - return diff.content.reduce((sum, chunk) => { - const sideChunk = side === Side.LEFT ? chunk.a : chunk.b; - return sum + (sideChunk?.length ?? chunk.ab?.length ?? chunk.skip ?? 0); - }, 0); -} - export function getResponsiveMode( prefs: DiffPreferencesInfo, renderPrefs?: RenderPreferences @@ -73,7 +65,7 @@ export function getResponsiveMode( return 'NONE'; } -export function isResponsive(responsiveMode?: DiffResponsiveMode) { +export function isResponsive(responsiveMode: DiffResponsiveMode) { return ( responsiveMode === 'FULL_RESPONSIVE' || responsiveMode === 'SHRINK_ONLY' ); @@ -124,12 +116,7 @@ export function getLineElByChild(node?: Node): HTMLElement | null { return null; } } - node = - (node as Element).assignedSlot ?? - (node as ShadowRoot).host ?? - node.previousSibling ?? - node.parentNode ?? - undefined; + node = node.previousSibling ?? node.parentElement ?? undefined; } return null; } @@ -208,19 +195,6 @@ export function anyLineTooLong(diff?: DiffInfo) { } /** - * Simple helper method for creating element classes in the context of - * gr-diff. - * - * We are adding 'style-scope', 'gr-diff' classes for compatibility with - * Shady DOM. TODO: Is that still required?? - * - * Otherwise this is just a super simple convenience function. - */ -export function diffClasses(...additionalClasses: string[]) { - return ['style-scope', 'gr-diff', ...additionalClasses].join(' '); -} - -/** * Simple helper method for creating elements in the context of gr-diff. * * We are adding 'style-scope', 'gr-diff' classes for compatibility with @@ -281,8 +255,6 @@ export function createTabWrapper(tabSize: number): HTMLElement { } /** - * Deprecated: Lit based rendering uses the textToPieces() function above. - * * Returns a 'div' element containing the supplied |text| as its innerText, * with '\t' characters expanded to a width determined by |tabSize|, and the * text wrapped at column |lineLimit|, which may be Infinity if no wrapping is diff --git a/polygerrit-ui/app/embed/diff/gr-diff/gr-diff-utils_test.ts b/polygerrit-ui/app/embed/diff/gr-diff/gr-diff-utils_test.ts index 793b0efa95..600913e57a 100644 --- a/polygerrit-ui/app/embed/diff/gr-diff/gr-diff-utils_test.ts +++ b/polygerrit-ui/app/embed/diff/gr-diff/gr-diff-utils_test.ts @@ -4,171 +4,150 @@ * SPDX-License-Identifier: Apache-2.0 */ import '../../../test/common-test-setup-karma'; -import { - createElementDiff, - formatText, - createTabWrapper, - diffClasses, -} from './gr-diff-utils'; +import {createElementDiff, formatText, createTabWrapper} from './gr-diff-utils'; const LINE_BREAK_HTML = '<span class="style-scope gr-diff br"></span>'; suite('gr-diff-utils tests', () => { - suite('legacy rendering', () => { - test('createElementDiff classStr applies all classes', () => { - const node = createElementDiff('div', 'test classes'); - assert.isTrue(node.classList.contains('gr-diff')); - assert.isTrue(node.classList.contains('test')); - assert.isTrue(node.classList.contains('classes')); - }); - - test('formatText newlines 1', () => { - let text = 'abcdef'; - - assert.equal(formatText(text, 'NONE', 4, 10).innerHTML, text); - text = 'a'.repeat(20); - assert.equal( - formatText(text, 'NONE', 4, 10).innerHTML, - 'a'.repeat(10) + LINE_BREAK_HTML + 'a'.repeat(10) - ); - }); + test('createElementDiff classStr applies all classes', () => { + const node = createElementDiff('div', 'test classes'); + assert.isTrue(node.classList.contains('gr-diff')); + assert.isTrue(node.classList.contains('test')); + assert.isTrue(node.classList.contains('classes')); + }); - test('formatText newlines 2', () => { - const text = '<span class="thumbsup">👍</span>'; - assert.equal( - formatText(text, 'NONE', 4, 10).innerHTML, - '<span clas' + - LINE_BREAK_HTML + - 's="thumbsu' + - LINE_BREAK_HTML + - 'p">👍</span' + - LINE_BREAK_HTML + - '>' - ); - }); + test('formatText newlines 1', () => { + let text = 'abcdef'; - test('formatText newlines 3', () => { - const text = '01234\t56789'; - assert.equal( - formatText(text, 'NONE', 4, 10).innerHTML, - '01234' + createTabWrapper(3).outerHTML + '56' + LINE_BREAK_HTML + '789' - ); - }); + assert.equal(formatText(text, 'NONE', 4, 10).innerHTML, text); + text = 'a'.repeat(20); + assert.equal( + formatText(text, 'NONE', 4, 10).innerHTML, + 'a'.repeat(10) + LINE_BREAK_HTML + 'a'.repeat(10) + ); + }); - test('formatText newlines 4', () => { - const text = '👍'.repeat(58); - assert.equal( - formatText(text, 'NONE', 4, 20).innerHTML, + test('formatText newlines 2', () => { + const text = '<span class="thumbsup">👍</span>'; + assert.equal( + formatText(text, 'NONE', 4, 10).innerHTML, + '<span clas' + + LINE_BREAK_HTML + + 's="thumbsu' + + LINE_BREAK_HTML + + 'p">👍</span' + + LINE_BREAK_HTML + + '>' + ); + }); + + test('formatText newlines 3', () => { + const text = '01234\t56789'; + assert.equal( + formatText(text, 'NONE', 4, 10).innerHTML, + '01234' + createTabWrapper(3).outerHTML + '56' + LINE_BREAK_HTML + '789' + ); + }); + + test('formatText newlines 4', () => { + const text = '👍'.repeat(58); + assert.equal( + formatText(text, 'NONE', 4, 20).innerHTML, + '👍'.repeat(20) + + LINE_BREAK_HTML + '👍'.repeat(20) + - LINE_BREAK_HTML + - '👍'.repeat(20) + - LINE_BREAK_HTML + - '👍'.repeat(18) - ); - }); + LINE_BREAK_HTML + + '👍'.repeat(18) + ); + }); - test('tab wrapper style', () => { - const pattern = new RegExp( - '^<span class="style-scope gr-diff tab" ' + - 'style="((?:-moz-)?tab-size: (\\d+);.?)+">\\t<\\/span>$' + test('tab wrapper style', () => { + const pattern = new RegExp( + '^<span class="style-scope gr-diff tab" ' + + 'style="((?:-moz-)?tab-size: (\\d+);.?)+">\\t<\\/span>$' + ); + + for (const size of [1, 3, 8, 55]) { + const html = createTabWrapper(size).outerHTML; + expect(html).to.match(pattern); + assert.equal(html.match(pattern)?.[2], size.toString()); + } + }); + + test('tab wrapper insertion', () => { + const html = 'abc\tdef'; + const tabSize = 8; + const wrapper = createTabWrapper(tabSize - 3); + assert.ok(wrapper); + assert.equal(wrapper.innerText, '\t'); + assert.equal( + formatText(html, 'NONE', tabSize, Infinity).innerHTML, + 'abc' + wrapper.outerHTML + 'def' + ); + }); + + test('escaping HTML', () => { + let input = '<script>alert("XSS");<' + '/script>'; + let expected = '<script>alert("XSS");</script>'; + + let result = formatText( + input, + 'NONE', + 1, + Number.POSITIVE_INFINITY + ).innerHTML; + assert.equal(result, expected); + + input = '& < > " \' / `'; + expected = '& < > " \' / `'; + result = formatText(input, 'NONE', 1, Number.POSITIVE_INFINITY).innerHTML; + assert.equal(result, expected); + }); + + test('text length with tabs and unicode', () => { + function expectTextLength(text: string, tabSize: number, expected: number) { + // Formatting to |expected| columns should not introduce line breaks. + const result = formatText(text, 'NONE', tabSize, expected); + assert.isNotOk( + result.querySelector('.contentText > .br'), + ' Expected the result of: \n' + + ` _formatText(${text}', 'NONE', ${tabSize}, ${expected})\n` + + ' to not contain a br. But the actual result HTML was:\n' + + ` '${result.innerHTML}'\nwhereupon` ); - for (const size of [1, 3, 8, 55]) { - const html = createTabWrapper(size).outerHTML; - expect(html).to.match(pattern); - assert.equal(html.match(pattern)?.[2], size.toString()); - } - }); - - test('tab wrapper insertion', () => { - const html = 'abc\tdef'; - const tabSize = 8; - const wrapper = createTabWrapper(tabSize - 3); - assert.ok(wrapper); - assert.equal(wrapper.innerText, '\t'); + // Increasing the line limit should produce the same markup. assert.equal( - formatText(html, 'NONE', tabSize, Infinity).innerHTML, - 'abc' + wrapper.outerHTML + 'def' + formatText(text, 'NONE', tabSize, Infinity).innerHTML, + result.innerHTML + ); + assert.equal( + formatText(text, 'NONE', tabSize, expected + 1).innerHTML, + result.innerHTML ); - }); - - test('escaping HTML', () => { - let input = '<script>alert("XSS");<' + '/script>'; - let expected = '<script>alert("XSS");</script>'; - - let result = formatText( - input, - 'NONE', - 1, - Number.POSITIVE_INFINITY - ).innerHTML; - assert.equal(result, expected); - - input = '& < > " \' / `'; - expected = '& < > " \' / `'; - result = formatText(input, 'NONE', 1, Number.POSITIVE_INFINITY).innerHTML; - assert.equal(result, expected); - }); - - test('text length with tabs and unicode', () => { - function expectTextLength( - text: string, - tabSize: number, - expected: number - ) { - // Formatting to |expected| columns should not introduce line breaks. - const result = formatText(text, 'NONE', tabSize, expected); - assert.isNotOk( - result.querySelector('.contentText > .br'), - ' Expected the result of: \n' + - ` _formatText(${text}', 'NONE', ${tabSize}, ${expected})\n` + - ' to not contain a br. But the actual result HTML was:\n' + - ` '${result.innerHTML}'\nwhereupon` - ); - // Increasing the line limit should produce the same markup. - assert.equal( - formatText(text, 'NONE', tabSize, Infinity).innerHTML, - result.innerHTML - ); - assert.equal( - formatText(text, 'NONE', tabSize, expected + 1).innerHTML, - result.innerHTML + // Decreasing the line limit should introduce line breaks. + if (expected > 0) { + const tooSmall = formatText(text, 'NONE', tabSize, expected - 1); + assert.isOk( + tooSmall.querySelector('.contentText > .br'), + ' Expected the result of: \n' + + ` _formatText(${text}', ${tabSize}, ${expected - 1})\n` + + ' to contain a br. But the actual result HTML was:\n' + + ` '${tooSmall.innerHTML}'\nwhereupon` ); - - // Decreasing the line limit should introduce line breaks. - if (expected > 0) { - const tooSmall = formatText(text, 'NONE', tabSize, expected - 1); - assert.isOk( - tooSmall.querySelector('.contentText > .br'), - ' Expected the result of: \n' + - ` _formatText(${text}', ${tabSize}, ${expected - 1})\n` + - ' to contain a br. But the actual result HTML was:\n' + - ` '${tooSmall.innerHTML}'\nwhereupon` - ); - } } - expectTextLength('12345', 4, 5); - expectTextLength('\t\t12', 4, 10); - expectTextLength('abc💢123', 4, 7); - expectTextLength('abc\t', 8, 8); - expectTextLength('abc\t\t', 10, 20); - expectTextLength('', 10, 0); - // 17 Thai combining chars. - expectTextLength('ก้้้้้้้้้้้้้้้้', 4, 17); - expectTextLength('abc\tde', 10, 12); - expectTextLength('abc\tde\t', 10, 20); - expectTextLength('\t\t\t\t\t', 20, 100); - }); - }); - - suite('lit rendering', () => { - test('diffClasses', () => { - const c = diffClasses('div', 'test classes').split(' '); - assert.include(c, 'gr-diff'); - assert.include(c, 'style-scope'); - assert.include(c, 'test'); - assert.include(c, 'classes'); - }); + } + expectTextLength('12345', 4, 5); + expectTextLength('\t\t12', 4, 10); + expectTextLength('abc💢123', 4, 7); + expectTextLength('abc\t', 8, 8); + expectTextLength('abc\t\t', 10, 20); + expectTextLength('', 10, 0); + // 17 Thai combining chars. + expectTextLength('ก้้้้้้้้้้้้้้้้', 4, 17); + expectTextLength('abc\tde', 10, 12); + expectTextLength('abc\tde\t', 10, 20); + expectTextLength('\t\t\t\t\t', 20, 100); }); }); diff --git a/polygerrit-ui/app/embed/diff/gr-diff/gr-diff.ts b/polygerrit-ui/app/embed/diff/gr-diff/gr-diff.ts index f7e40f9ac2..a38ec91854 100644 --- a/polygerrit-ui/app/embed/diff/gr-diff/gr-diff.ts +++ b/polygerrit-ui/app/embed/diff/gr-diff/gr-diff.ts @@ -24,7 +24,7 @@ import '../gr-syntax-themes/gr-syntax-theme'; import '../gr-ranged-comment-themes/gr-ranged-comment-theme'; import '../gr-ranged-comment-hint/gr-ranged-comment-hint'; import {PolymerElement} from '@polymer/polymer/polymer-element'; -import {dom} from '@polymer/polymer/lib/legacy/polymer.dom'; +import {dom, EventApi} from '@polymer/polymer/lib/legacy/polymer.dom'; import {htmlTemplate} from './gr-diff_html'; import {LineNumber} from './gr-diff-line'; import { @@ -77,7 +77,7 @@ import { GrDiff as GrDiffApi, DisplayLine, } from '../../../api/diff'; -import {isElementTarget, isSafari, toggleClass} from '../../../utils/dom-util'; +import {isSafari, toggleClass} from '../../../utils/dom-util'; import {assertIsDefined} from '../../../utils/common-util'; import {debounce, DelayedTask} from '../../../utils/async-util'; @@ -530,8 +530,7 @@ export class GrDiff extends PolymerElement implements GrDiffApi { } _handleTap(e: CustomEvent) { - const el = e.composedPath()[0]; - if (!isElementTarget(el)) return; + const el = (dom(e) as EventApi).localTarget as Element; if ( el.getAttribute('data-value') !== 'LOST' && diff --git a/polygerrit-ui/app/embed/diff/gr-diff/gr-diff_html.ts b/polygerrit-ui/app/embed/diff/gr-diff/gr-diff_html.ts index c2e5550e38..e05e85aa88 100644 --- a/polygerrit-ui/app/embed/diff/gr-diff/gr-diff_html.ts +++ b/polygerrit-ui/app/embed/diff/gr-diff/gr-diff_html.ts @@ -670,12 +670,6 @@ export const htmlTemplate = html` .token-highlight { background-color: var(--token-highlighting-color, #fffd54); } - - gr-diff-section, - gr-context-controls-section, - gr-diff-row { - display: contents; - } </style> <style include="gr-syntax-theme"> /* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */ |