From 1208fc9e106513a4979d054029c49765b8f98ff1 Mon Sep 17 00:00:00 2001 From: jrkong Date: Mon, 22 Oct 2018 16:32:04 -0400 Subject: [PATCH 1/9] updated webLinks regex to fix vscode issue#60401 --- src/addons/webLinks/webLinks.test.ts | 4 ++-- src/addons/webLinks/webLinks.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/addons/webLinks/webLinks.test.ts b/src/addons/webLinks/webLinks.test.ts index c84ee1a5ef..1ae62b80b2 100644 --- a/src/addons/webLinks/webLinks.test.ts +++ b/src/addons/webLinks/webLinks.test.ts @@ -32,11 +32,11 @@ describe('webLinks addon', () => { const term = new MockTerminal(); webLinks.webLinksInit(term); - const row = ' http://foo.com/a~b#c~d?e~f '; + const row = ' http://foo.com/a~b#c~d?e~f: '; const match = row.match(term.regex); const uri = match[term.options.matchIndex]; - assert.equal(uri, 'http://foo.com/a~b#c~d?e~f'); + assert.equal(uri, 'http://foo.com/a~b#c~d?e~f:'); }); }); diff --git a/src/addons/webLinks/webLinks.ts b/src/addons/webLinks/webLinks.ts index a007bbd618..382d5dba28 100644 --- a/src/addons/webLinks/webLinks.ts +++ b/src/addons/webLinks/webLinks.ts @@ -14,7 +14,7 @@ const ipClause = '((\\d{1,3}\\.){3}\\d{1,3})'; const localHostClause = '(localhost)'; const portClause = '(:\\d{1,5})'; const hostClause = '((' + domainBodyClause + '\\.' + tldClause + ')|' + ipClause + '|' + localHostClause + ')' + portClause + '?'; -const pathClause = '(\\/[\\/\\w\\.\\-%~]*)*'; +const pathClause = '(\\/[\\/\\w\\.\\-%~:]*)*'; const queryStringHashFragmentCharacterSet = '[0-9\\w\\[\\]\\(\\)\\/\\?\\!#@$%&\'*+,:;~\\=\\.\\-]*'; const queryStringClause = '(\\?' + queryStringHashFragmentCharacterSet + ')?'; const hashFragmentClause = '(#' + queryStringHashFragmentCharacterSet + ')?'; From 2efd28ad4b32593bf3403f84399c9cf1698c8c15 Mon Sep 17 00:00:00 2001 From: jrkong Date: Thu, 25 Oct 2018 00:14:20 -0400 Subject: [PATCH 2/9] updated webLinks regex to ignore colon at the end of a line and added the corresponding tests --- src/addons/webLinks/webLinks.test.ts | 28 ++++++++++++++++++++++++++-- src/addons/webLinks/webLinks.ts | 2 +- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/src/addons/webLinks/webLinks.test.ts b/src/addons/webLinks/webLinks.test.ts index 1ae62b80b2..ce9b8b4421 100644 --- a/src/addons/webLinks/webLinks.test.ts +++ b/src/addons/webLinks/webLinks.test.ts @@ -32,11 +32,35 @@ describe('webLinks addon', () => { const term = new MockTerminal(); webLinks.webLinksInit(term); - const row = ' http://foo.com/a~b#c~d?e~f: '; + const row = ' http://foo.com/a~b#c~d?e~f '; const match = row.match(term.regex); const uri = match[term.options.matchIndex]; - assert.equal(uri, 'http://foo.com/a~b#c~d?e~f:'); + assert.equal(uri, 'http://foo.com/a~b#c~d?e~f'); + }); + + it('should allow : character in URI path', () => { + const term = new MockTerminal(); + webLinks.webLinksInit(term); + + const row = ' http://foo.com/colon:test '; + + const match = row.match(term.regex); + const uri = match[term.options.matchIndex]; + + assert.equal(uri, 'http://foo.com/colon:test'); + }); + + it('should not allow : character at the end of a URI path', () => { + const term = new MockTerminal(); + webLinks.webLinksInit(term); + + const row = ' http://foo.com/colon:test: '; + + const match = row.match(term.regex); + const uri = match[term.options.matchIndex]; + + assert.equal(uri, 'http://foo.com/colon:test'); }); }); diff --git a/src/addons/webLinks/webLinks.ts b/src/addons/webLinks/webLinks.ts index 382d5dba28..75d79104f3 100644 --- a/src/addons/webLinks/webLinks.ts +++ b/src/addons/webLinks/webLinks.ts @@ -14,7 +14,7 @@ const ipClause = '((\\d{1,3}\\.){3}\\d{1,3})'; const localHostClause = '(localhost)'; const portClause = '(:\\d{1,5})'; const hostClause = '((' + domainBodyClause + '\\.' + tldClause + ')|' + ipClause + '|' + localHostClause + ')' + portClause + '?'; -const pathClause = '(\\/[\\/\\w\\.\\-%~:]*)*'; +const pathClause = '(\\/[\\/\\w\\.\\-%~:]*)*([^:\\s])'; const queryStringHashFragmentCharacterSet = '[0-9\\w\\[\\]\\(\\)\\/\\?\\!#@$%&\'*+,:;~\\=\\.\\-]*'; const queryStringClause = '(\\?' + queryStringHashFragmentCharacterSet + ')?'; const hashFragmentClause = '(#' + queryStringHashFragmentCharacterSet + ')?'; From 774793c7ca77093bb9878d654159164ca28aae98 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Thu, 8 Nov 2018 19:20:12 -0800 Subject: [PATCH 3/9] Fixing isClickInSelection to cover missing cases The following cases weren't working: - The first character on single line selections - The first row on multi-line selection --- src/SelectionManager.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/SelectionManager.ts b/src/SelectionManager.ts index bfb5717732..47cad7ef51 100644 --- a/src/SelectionManager.ts +++ b/src/SelectionManager.ts @@ -290,8 +290,9 @@ export class SelectionManager extends EventEmitter implements ISelectionManager } return (coords[1] > start[1] && coords[1] < end[1]) || - (start[1] === end[1] && coords[1] === start[1] && coords[0] > start[0] && coords[0] < end[0]) || - (start[1] < end[1] && coords[1] === end[1] && coords[0] < end[0]); + (start[1] === end[1] && coords[1] === start[1] && coords[0] >= start[0] && coords[0] < end[0]) || + (start[1] < end[1] && coords[1] === end[1] && coords[0] < end[0]) || + (start[1] < end[1] && coords[1] === start[1] && coords[0] >= start[0]); } /** From 9faebaf5fe8f7e480c4206a041fc2b67679fb3b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Breitbart?= Date: Thu, 15 Nov 2018 00:16:52 +0100 Subject: [PATCH 4/9] hold single AudioContext instance --- src/SoundManager.ts | 38 ++++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/src/SoundManager.ts b/src/SoundManager.ts index 4139c207bc..ffb01658e0 100644 --- a/src/SoundManager.ts +++ b/src/SoundManager.ts @@ -12,7 +12,19 @@ import { ITerminal, ISoundManager } from './Types'; export const DEFAULT_BELL_SOUND = 'data:audio/wav;base64,UklGRigBAABXQVZFZm10IBAAAAABAAEARKwAAIhYAQACABAAZGF0YQQBAADpAFgCwAMlBZoG/wdmCcoKRAypDQ8PbRDBEQQTOxRtFYcWlBePGIUZXhoiG88bcBz7HHIdzh0WHlMeZx51HmkeUx4WHs8dah0AHXwc3hs9G4saxRnyGBIYGBcQFv8U4RPAEoYRQBACD70NWwwHC6gJOwjWBloF7gOBAhABkf8b/qv8R/ve+Xf4Ife79W/0JfPZ8Z/wde9N7ijtE+wU6xvqM+lb6H7nw+YX5mrlxuQz5Mzje+Ma49fioeKD4nXiYeJy4pHitOL04j/jn+MN5IPkFOWs5U3mDefM55/ogOl36m7rdOyE7abuyu8D8Unyj/Pg9D/2qfcb+Yn6/vuK/Qj/lAAlAg=='; export class SoundManager implements ISoundManager { - private _audioContext: AudioContext; + private static _audioContext: AudioContext; + + static get audioContext(): AudioContext { + if (!SoundManager._audioContext) { + const audioContextCtor: typeof AudioContext = (window).AudioContext || (window).webkitAudioContext; + if (!audioContextCtor) { + console.warn('Web Audio API is not supported by this browser. Consider upgrading to the latest version'); + return null; + } + this._audioContext = new audioContextCtor(); + } + return SoundManager._audioContext; + } constructor( private _terminal: ITerminal @@ -20,22 +32,16 @@ export class SoundManager implements ISoundManager { } public playBellSound(): void { - const audioContextCtor: typeof AudioContext = (window).AudioContext || (window).webkitAudioContext; - if (!this._audioContext && audioContextCtor) { - this._audioContext = new audioContextCtor(); - } - - if (this._audioContext) { - const bellAudioSource = this._audioContext.createBufferSource(); - const context = this._audioContext; - this._audioContext.decodeAudioData(this._base64ToArrayBuffer(this._removeMimeType(this._terminal.options.bellSound)), (buffer) => { - bellAudioSource.buffer = buffer; - bellAudioSource.connect(context.destination); - bellAudioSource.start(0); - }); - } else { - console.warn('Sorry, but the Web Audio API is not supported by your browser. Please, consider upgrading to the latest version'); + const context = SoundManager.audioContext; + if (!context) { + return; } + const bellAudioSource = context.createBufferSource(); + context.decodeAudioData(this._base64ToArrayBuffer(this._removeMimeType(this._terminal.options.bellSound)), (buffer) => { + bellAudioSource.buffer = buffer; + bellAudioSource.connect(context.destination); + bellAudioSource.start(0); + }); } private _base64ToArrayBuffer(base64: string): ArrayBuffer { From e3146961bef54bb8e44206c90e5901c6d76434fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Breitbart?= Date: Thu, 15 Nov 2018 00:25:23 +0100 Subject: [PATCH 5/9] make linter happy --- src/SoundManager.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SoundManager.ts b/src/SoundManager.ts index ffb01658e0..a31c7574a1 100644 --- a/src/SoundManager.ts +++ b/src/SoundManager.ts @@ -13,7 +13,7 @@ export const DEFAULT_BELL_SOUND = 'data:audio/wav;base64,UklGRigBAABXQVZFZm10IBA export class SoundManager implements ISoundManager { private static _audioContext: AudioContext; - + static get audioContext(): AudioContext { if (!SoundManager._audioContext) { const audioContextCtor: typeof AudioContext = (window).AudioContext || (window).webkitAudioContext; From 0e3f9b72d1725f1797992b04e5ce320b69c56e24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Breitbart?= Date: Thu, 15 Nov 2018 00:48:31 +0100 Subject: [PATCH 6/9] allow to set audio context per argument --- src/SoundManager.ts | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/SoundManager.ts b/src/SoundManager.ts index a31c7574a1..0ba6e0c2ba 100644 --- a/src/SoundManager.ts +++ b/src/SoundManager.ts @@ -14,7 +14,7 @@ export const DEFAULT_BELL_SOUND = 'data:audio/wav;base64,UklGRigBAABXQVZFZm10IBA export class SoundManager implements ISoundManager { private static _audioContext: AudioContext; - static get audioContext(): AudioContext { + static get audioContext(): AudioContext | null { if (!SoundManager._audioContext) { const audioContextCtor: typeof AudioContext = (window).AudioContext || (window).webkitAudioContext; if (!audioContextCtor) { @@ -27,19 +27,20 @@ export class SoundManager implements ISoundManager { } constructor( - private _terminal: ITerminal + private _terminal: ITerminal, + private _audioContext?: AudioContext ) { } public playBellSound(): void { - const context = SoundManager.audioContext; - if (!context) { + const ctx = this._audioContext || SoundManager.audioContext; + if (!ctx) { return; } - const bellAudioSource = context.createBufferSource(); - context.decodeAudioData(this._base64ToArrayBuffer(this._removeMimeType(this._terminal.options.bellSound)), (buffer) => { + const bellAudioSource = ctx.createBufferSource(); + ctx.decodeAudioData(this._base64ToArrayBuffer(this._removeMimeType(this._terminal.options.bellSound)), (buffer) => { bellAudioSource.buffer = buffer; - bellAudioSource.connect(context.destination); + bellAudioSource.connect(ctx.destination); bellAudioSource.start(0); }); } From a480f483cda4d73edd1f2963a1ae61e32acd973c Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Fri, 16 Nov 2018 17:54:03 -0800 Subject: [PATCH 7/9] Add tests --- src/SelectionManager.test.ts | 13 +++++++++++++ src/SelectionManager.ts | 4 ++++ 2 files changed, 17 insertions(+) diff --git a/src/SelectionManager.test.ts b/src/SelectionManager.test.ts index c42735d522..8735e8945d 100644 --- a/src/SelectionManager.test.ts +++ b/src/SelectionManager.test.ts @@ -30,6 +30,7 @@ class TestSelectionManager extends SelectionManager { public selectLineAt(line: number): void { this._selectLineAt(line); } public selectWordAt(coords: [number, number]): void { this._selectWordAt(coords, true); } + public areCoordsInSelection(coords: [number, number], start: [number, number], end: [number, number]): boolean { return this._areCoordsInSelection(coords, start, end); } // Disable DOM interaction public enable(): void {} @@ -478,5 +479,17 @@ describe('SelectionManager', () => { assert.equal(selectionManager.selectionText, 'a\nšŸ˜\nc'); }); }); + + describe('_areCoordsInSelection', () => { + it('should return whether coords are in the selection', () => { + assert.isFalse(selectionManager.areCoordsInSelection([0, 0], [2, 0], [2, 1])); + assert.isFalse(selectionManager.areCoordsInSelection([1, 0], [2, 0], [2, 1])); + assert.isTrue(selectionManager.areCoordsInSelection([2, 0], [2, 0], [2, 1])); + assert.isTrue(selectionManager.areCoordsInSelection([10, 0], [2, 0], [2, 1])); + assert.isTrue(selectionManager.areCoordsInSelection([0, 1], [2, 0], [2, 1])); + assert.isTrue(selectionManager.areCoordsInSelection([1, 1], [2, 0], [2, 1])); + assert.isFalse(selectionManager.areCoordsInSelection([2, 1], [2, 0], [2, 1])); + }); + }); }); diff --git a/src/SelectionManager.ts b/src/SelectionManager.ts index 47cad7ef51..86be0c48be 100644 --- a/src/SelectionManager.ts +++ b/src/SelectionManager.ts @@ -289,6 +289,10 @@ export class SelectionManager extends EventEmitter implements ISelectionManager return false; } + return this._areCoordsInSelection(coords, start, end); + } + + protected _areCoordsInSelection(coords: [number, number], start: [number, number], end: [number, number]): boolean { return (coords[1] > start[1] && coords[1] < end[1]) || (start[1] === end[1] && coords[1] === start[1] && coords[0] >= start[0] && coords[0] < end[0]) || (start[1] < end[1] && coords[1] === end[1] && coords[0] < end[0]) || From 203ee0f644f833d2dd554a147ec3274349272887 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Breitbart?= Date: Sun, 18 Nov 2018 17:47:49 +0100 Subject: [PATCH 8/9] remove ctx args from ctor --- src/SoundManager.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/SoundManager.ts b/src/SoundManager.ts index 0ba6e0c2ba..9adbfc4af3 100644 --- a/src/SoundManager.ts +++ b/src/SoundManager.ts @@ -27,13 +27,12 @@ export class SoundManager implements ISoundManager { } constructor( - private _terminal: ITerminal, - private _audioContext?: AudioContext + private _terminal: ITerminal ) { } public playBellSound(): void { - const ctx = this._audioContext || SoundManager.audioContext; + const ctx = SoundManager.audioContext; if (!ctx) { return; } From 9286ea3eafe61c3ea9170378568d5fe6f46809f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Breitbart?= Date: Sun, 18 Nov 2018 17:50:29 +0100 Subject: [PATCH 9/9] make statix usage explicit --- src/SoundManager.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SoundManager.ts b/src/SoundManager.ts index 9adbfc4af3..6084edcb0d 100644 --- a/src/SoundManager.ts +++ b/src/SoundManager.ts @@ -21,7 +21,7 @@ export class SoundManager implements ISoundManager { console.warn('Web Audio API is not supported by this browser. Consider upgrading to the latest version'); return null; } - this._audioContext = new audioContextCtor(); + SoundManager._audioContext = new audioContextCtor(); } return SoundManager._audioContext; }