Support multiline links in the WebLinksAddon
This commit is contained in:
@@ -1,3 +1,8 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2019 The xterm.js authors. All rights reserved.
|
||||||
|
* @license MIT
|
||||||
|
*/
|
||||||
|
|
||||||
import { ILinkProvider, IBufferCellPosition, ILink, Terminal, IBuffer } from 'xterm';
|
import { ILinkProvider, IBufferCellPosition, ILink, Terminal, IBuffer } from 'xterm';
|
||||||
|
|
||||||
export class WebLinkProvider implements ILinkProvider {
|
export class WebLinkProvider implements ILinkProvider {
|
||||||
@@ -11,20 +16,15 @@ export class WebLinkProvider implements ILinkProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
provideLink(position: IBufferCellPosition, callback: (link: ILink | undefined) => void): void {
|
provideLink(position: IBufferCellPosition, callback: (link: ILink | undefined) => void): void {
|
||||||
callback(LinkComputer.computeLink(position, this._regex, this._terminal.buffer, this._handler));
|
callback(LinkComputer.computeLink(position, this._regex, this._terminal, this._handler));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class LinkComputer {
|
export class LinkComputer {
|
||||||
public static computeLink(position: IBufferCellPosition, regex: RegExp, buffer: IBuffer, handle: (event: MouseEvent, uri: string) => void): ILink | undefined {
|
public static computeLink(position: IBufferCellPosition, regex: RegExp, terminal: Terminal, handle: (event: MouseEvent, uri: string) => void): ILink | undefined {
|
||||||
const rex = new RegExp(regex.source, (regex.flags || '') + 'g');
|
const rex = new RegExp(regex.source, (regex.flags || '') + 'g');
|
||||||
const bufferLine = buffer.getLine(position.y - 1);
|
|
||||||
|
|
||||||
if (!bufferLine) {
|
const [line, startLineIndex] = LinkComputer._translateBufferLineToStringWithWrap(position.y - 1, false, terminal);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const line = bufferLine.translateToString();
|
|
||||||
|
|
||||||
let match;
|
let match;
|
||||||
let stringIndex = -1;
|
let stringIndex = -1;
|
||||||
@@ -49,18 +49,66 @@ export class LinkComputer {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let endX = stringIndex + url.length + 1;
|
||||||
|
let endY = startLineIndex + 1;
|
||||||
|
|
||||||
|
while (endX > terminal.cols) {
|
||||||
|
endX -= terminal.cols;
|
||||||
|
endY++;
|
||||||
|
}
|
||||||
|
|
||||||
const range = {
|
const range = {
|
||||||
start: {
|
start: {
|
||||||
x: stringIndex + 1,
|
x: stringIndex + 1,
|
||||||
y: position.y
|
y: startLineIndex + 1
|
||||||
},
|
},
|
||||||
end: {
|
end: {
|
||||||
x: stringIndex + url.length + 1,
|
x: endX,
|
||||||
y: position.y
|
y: endY
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return { range, url, handle };
|
return { range, url, handle };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the entire line for the buffer line
|
||||||
|
* @param line The line being translated.
|
||||||
|
* @param trimRight Whether to trim whitespace to the right.
|
||||||
|
* @param terminal The terminal
|
||||||
|
*/
|
||||||
|
private static _translateBufferLineToStringWithWrap(lineIndex: number, trimRight: boolean, terminal: Terminal): [string, number] {
|
||||||
|
let lineString = '';
|
||||||
|
let lineWrapsToNext: boolean;
|
||||||
|
let prevLinesToWrap: boolean;
|
||||||
|
|
||||||
|
do {
|
||||||
|
const line = terminal.buffer.getLine(lineIndex);
|
||||||
|
if (!line) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (line.isWrapped) {
|
||||||
|
lineIndex--;
|
||||||
|
}
|
||||||
|
|
||||||
|
prevLinesToWrap = line.isWrapped;
|
||||||
|
} while (prevLinesToWrap);
|
||||||
|
|
||||||
|
const startLineIndex = lineIndex;
|
||||||
|
|
||||||
|
do {
|
||||||
|
const nextLine = terminal.buffer.getLine(lineIndex + 1);
|
||||||
|
lineWrapsToNext = nextLine ? nextLine.isWrapped : false;
|
||||||
|
const line = terminal.buffer.getLine(lineIndex);
|
||||||
|
if (!line) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
lineString += line.translateToString(!lineWrapsToNext && trimRight).substring(0, terminal.cols);
|
||||||
|
lineIndex++;
|
||||||
|
} while (lineWrapsToNext);
|
||||||
|
|
||||||
|
return [lineString, startLineIndex];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright (c) 2017 The xterm.js authors. All rights reserved.
|
* Copyright (c) 2019 The xterm.js authors. All rights reserved.
|
||||||
* @license MIT
|
* @license MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import { IDisposable } from 'common/Types';
|
|||||||
import { IMouseService } from './services/Services';
|
import { IMouseService } from './services/Services';
|
||||||
import { IBufferService, ICoreService } from 'common/services/Services';
|
import { IBufferService, ICoreService } from 'common/services/Services';
|
||||||
import { EventEmitter, IEvent } from 'common/EventEmitter';
|
import { EventEmitter, IEvent } from 'common/EventEmitter';
|
||||||
|
import { LinkRenderLayer } from './renderer/LinkRenderLayer';
|
||||||
|
|
||||||
export class Linkifier2 implements ILinkifier2 {
|
export class Linkifier2 implements ILinkifier2 {
|
||||||
private _element: HTMLElement | undefined;
|
private _element: HTMLElement | undefined;
|
||||||
@@ -206,9 +207,16 @@ export class Linkifier2 implements ILinkifier2 {
|
|||||||
* @param position
|
* @param position
|
||||||
*/
|
*/
|
||||||
private _linkAtPosition(link: ILink, position: IBufferCellPosition): boolean {
|
private _linkAtPosition(link: ILink, position: IBufferCellPosition): boolean {
|
||||||
return link.range.start.x <= position.x &&
|
const sameLine = link.range.start.y === link.range.end.y;
|
||||||
|
const wrappedFromLeft = link.range.start.y < position.y;
|
||||||
|
const wrappedToRight = link.range.end.y > position.y;
|
||||||
|
|
||||||
|
// If the start and end have the same y, then the position must be between start and end x
|
||||||
|
// If not, then handle each case seperately, depending on which way it wraps
|
||||||
|
return ((sameLine && link.range.start.x <= position.x && link.range.end.x >= position.x) ||
|
||||||
|
(wrappedFromLeft && link.range.end.x >= position.x) ||
|
||||||
|
(wrappedToRight && link.range.start.x <= position.x)) &&
|
||||||
link.range.start.y <= position.y &&
|
link.range.start.y <= position.y &&
|
||||||
link.range.end.x >= position.x &&
|
|
||||||
link.range.end.y >= position.y;
|
link.range.end.y >= position.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user