Skip to content

Commit

Permalink
better regexp, fix offset issue in xtermjs#4294
Browse files Browse the repository at this point in the history
  • Loading branch information
jerch committed Dec 8, 2022
1 parent 03dc190 commit becec91
Show file tree
Hide file tree
Showing 5 changed files with 31 additions and 15 deletions.
11 changes: 9 additions & 2 deletions addons/xterm-addon-web-links/src/WebLinksAddon.ts
Expand Up @@ -10,8 +10,15 @@ import { ILinkProviderOptions, WebLinkProvider } from './WebLinkProvider';
// up to first whitespace, `"` or `'` as url
// NOTE: The repeated end clause is needed to not match a dangling `:`
// resembling the old (...)*([^:"\'\\s]) final path clause
// also exclude final interpunction like ,.!?
const strictUrlRegex = /https?:[/]{2}[^\s^"^']*[^\s^"^'^:^,^.^!^?]/;
// additionally exclude early + final:
// - unsafe from rfc3986: !*'()
// - unsafe chars from rfc1738: {}|\^~[]` (minus [] as we need them for ipv6 adresses)
// also exclude as finals:
// - final interpunction like ,.!?
// - any sort of brackets <>()[]{} (not spec conform, but often used to enclose urls)
// - unsafe chars from rfc1738: {}|\^~[]`
const strictUrlRegex = /https?:[/]{2}[^\s"'!*(){}|\\\^~<>`]*[^\s"':,.!?{}|\\\^~\[\]`()<>]/;


function handleLink(event: MouseEvent, uri: string): void {
const newWindow = window.open();
Expand Down
25 changes: 17 additions & 8 deletions bin/test_weblinks.sh
@@ -1,25 +1,34 @@
#!/bin/bash

# all half width - only good case
# all half width
echo "aaa http://example.com aaa http://example.com aaa"

# full width before - wrong offset
# full width before
echo "¥¥¥ http://example.com aaa http://example.com aaa"

# full width between - wrong offset
# full width between
echo "aaa http://example.com ¥¥¥ http://example.com aaa"

# full width before and between - error in offsets adding up
# full width before and between
echo "¥¥¥ http://example.com ¥¥¥ http://example.com aaa"

# full width within url - partial wrong match
# full width within url
echo "aaa https://ko.wikipedia.org/wiki/위키백과:대문 aaa https://ko.wikipedia.org/wiki/위키백과:대문 aaa"

# full width within and before - partial wrong match + wrong offsets
# full width within and before
echo "¥¥¥ https://ko.wikipedia.org/wiki/위키백과:대문 aaa https://ko.wikipedia.org/wiki/위키백과:대문 ¥¥¥"

# not matching at all
# username + password scheme
echo "http://test:password@example.com/some_path aaa"

# overly long text with urls with final interpunction
echo "Lorem ipsum dolor sit amet, consetetur sadipscing elitr https://ko.wikipedia.org/wiki/위키백과:대문, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat: http://test:password@example.com/some_path."
echo "Lorem ipsum dolor sit amet, consetetur sadipscing elitr https://ko.wikipedia.org/wiki/위키백과:대문, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat: http://test:password@example.com/some_path."

# bracket enclosed urls
echo "[http://example.de]"
echo "(http://example.de)"
echo "<http://example.de>"
echo "{http://example.de}"

# ipv6 scheme
echo "ipv6 https://[::1]/with/some?vars=and&a#hash"
4 changes: 2 additions & 2 deletions src/browser/renderer/dom/DomRenderer.ts
Expand Up @@ -38,7 +38,7 @@ export class DomRenderer extends Disposable implements IRenderer {
private _rowContainer: HTMLElement;
private _rowElements: HTMLElement[] = [];
private _selectionContainer: HTMLElement;
private _cellToRowElements: Uint16Array[] = [];
private _cellToRowElements: Int16Array[] = [];

public dimensions: IRenderDimensions;

Expand Down Expand Up @@ -361,7 +361,7 @@ export class DomRenderer extends Disposable implements IRenderer {
const lineData = this._bufferService.buffer.lines.get(row);
const cursorStyle = this._optionsService.rawOptions.cursorStyle;
if (!this._cellToRowElements[y] || this._cellToRowElements[y].length !== this._bufferService.cols) {
this._cellToRowElements[y] = new Uint16Array(this._bufferService.cols);
this._cellToRowElements[y] = new Int16Array(this._bufferService.cols);
}
rowElement.replaceChildren(this._rowFactory.createRow(lineData!, row, row === cursorAbsoluteY, cursorStyle, cursorX, cursorBlink, this.dimensions.css.cell.width, this._bufferService.cols, this._cellToRowElements[y]));
}
Expand Down
2 changes: 1 addition & 1 deletion src/browser/renderer/dom/DomRendererRowFactory.test.ts
Expand Up @@ -14,7 +14,7 @@ import { MockCoreService, MockDecorationService, MockOptionsService } from 'comm
import { css } from 'common/Color';
import { MockCharacterJoinerService, MockCoreBrowserService, MockThemeService } from 'browser/TestUtils.test';

const EMPTY_ELEM_MAPPING = new Uint16Array(1000);
const EMPTY_ELEM_MAPPING = new Int16Array(1000);

describe('DomRendererRowFactory', () => {
let dom: jsdom.JSDOM;
Expand Down
4 changes: 2 additions & 2 deletions src/browser/renderer/dom/DomRendererRowFactory.ts
Expand Up @@ -49,7 +49,7 @@ export class DomRendererRowFactory {
this._columnSelectMode = columnSelectMode;
}

public createRow(lineData: IBufferLine, row: number, isCursorRow: boolean, cursorStyle: string | undefined, cursorX: number, cursorBlink: boolean, cellWidth: number, cols: number, cellMap: Uint16Array): DocumentFragment {
public createRow(lineData: IBufferLine, row: number, isCursorRow: boolean, cursorStyle: string | undefined, cursorX: number, cursorBlink: boolean, cellWidth: number, cols: number, cellMap: Int16Array): DocumentFragment {
// NOTE: `cellMap` maps cell positions to a span element index in a row.
// All positions should be updated, even skipped ones after wide chars or left overs at the end,
// otherwise the mouse hover logic might mark the wrong elements as underlined.
Expand Down Expand Up @@ -316,7 +316,7 @@ export class DomRendererRowFactory {
// since the loop above might exit early not handling all cells,
// also set remaining cell positions to last element index
if (x < cols - 1) {
cellMap.subarray(x + 1).fill(elemIndex);
cellMap.subarray(x).fill(++elemIndex);
}

return fragment;
Expand Down

0 comments on commit becec91

Please sign in to comment.