| // Copyright 2020 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| /* eslint-disable @devtools/no-lit-render-outside-of-view, @devtools/enforce-custom-element-definitions-location */ |
| |
| import * as Platform from '../../../core/platform/platform.js'; |
| import * as Lit from '../../lit/lit.js'; |
| import * as RenderCoordinator from '../render_coordinator/render_coordinator.js'; |
| |
| import linkifierImplStyles from './linkifierImpl.css.js'; |
| import * as LinkifierUtils from './LinkifierUtils.js'; |
| |
| const {html} = Lit; |
| |
| export interface LinkifierData { |
| url: Platform.DevToolsPath.UrlString; |
| lineNumber?: number; |
| columnNumber?: number; |
| linkText?: string; |
| title?: string; |
| } |
| |
| export class LinkifierClick extends Event { |
| static readonly eventName = 'linkifieractivated'; |
| constructor(public data: LinkifierData) { |
| super(LinkifierClick.eventName, { |
| bubbles: true, |
| composed: true, |
| }); |
| this.data = data; |
| } |
| } |
| |
| /** |
| * @deprecated do not use |
| */ |
| export class Linkifier extends HTMLElement { |
| readonly #shadow = this.attachShadow({mode: 'open'}); |
| #url: Platform.DevToolsPath.UrlString = Platform.DevToolsPath.EmptyUrlString; |
| #lineNumber?: number; |
| #columnNumber?: number; |
| #linkText?: string; |
| #title?: string; |
| |
| set data(data: LinkifierData) { |
| this.#url = data.url; |
| this.#lineNumber = data.lineNumber; |
| this.#columnNumber = data.columnNumber; |
| this.#linkText = data.linkText; |
| this.#title = data.title; |
| |
| if (!this.#url) { |
| throw new Error('Cannot construct a Linkifier without providing a valid string URL.'); |
| } |
| |
| void this.#render(); |
| } |
| |
| override cloneNode(deep?: boolean): Node { |
| const node = super.cloneNode(deep) as Linkifier; |
| node.data = { |
| url: this.#url, |
| lineNumber: this.#lineNumber, |
| columnNumber: this.#columnNumber, |
| linkText: this.#linkText, |
| title: this.#title |
| }; |
| return node; |
| } |
| |
| #onLinkActivation(event: Event): void { |
| event.preventDefault(); |
| const linkifierClickEvent = new LinkifierClick({ |
| url: this.#url, |
| lineNumber: this.#lineNumber, |
| columnNumber: this.#columnNumber, |
| }); |
| this.dispatchEvent(linkifierClickEvent); |
| } |
| |
| async #render(): Promise<void> { |
| const linkText = this.#linkText ?? LinkifierUtils.linkText(this.#url, this.#lineNumber); |
| // Disabled until https://crbug.com/1079231 is fixed. |
| await RenderCoordinator.write(() => { |
| // clang-format off |
| // eslint-disable-next-line @devtools/no-a-tags-in-lit |
| Lit.render(html` |
| <style>${linkifierImplStyles}</style> |
| <a class="link" href=${this.#url} @click=${this.#onLinkActivation} title=${Lit.Directives.ifDefined(this.#title) as string}> |
| <slot>${linkText}</slot> |
| </a>`, |
| this.#shadow, { host: this}); |
| // clang-format on |
| }); |
| } |
| } |
| |
| customElements.define('devtools-linkifier', Linkifier); |
| |
| declare global { |
| interface HTMLElementTagNameMap { |
| 'devtools-linkifier': Linkifier; |
| } |
| } |