Skip to content

Commit

Permalink
Merge pull request #5003 from josiahhudson/master
Browse files Browse the repository at this point in the history
Support semi-colons in OSC 8 hyperlink URIs
  • Loading branch information
Tyriar committed Apr 22, 2024
2 parents 1709d44 + d77b41e commit 826c057
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 8 deletions.
33 changes: 31 additions & 2 deletions src/common/InputHandler.test.ts
Expand Up @@ -12,11 +12,12 @@ import { Attributes, BgFlags, UnderlineStyle } from 'common/buffer/Constants';
import { AttributeData, ExtendedAttrs } from 'common/buffer/AttributeData';
import { Params } from 'common/parser/Params';
import { MockCoreService, MockBufferService, MockOptionsService, MockLogService, MockCoreMouseService, MockCharsetService, MockUnicodeService, MockOscLinkService } from 'common/TestUtils.test';
import { IBufferService, ICoreService } from 'common/services/Services';
import { IBufferService, ICoreService, type IOscLinkService } from 'common/services/Services';
import { DEFAULT_OPTIONS } from 'common/services/OptionsService';
import { clone } from 'common/Clone';
import { BufferService } from 'common/services/BufferService';
import { CoreService } from 'common/services/CoreService';
import { OscLinkService } from 'common/services/OscLinkService';


function getCursor(bufferService: IBufferService): number[] {
Expand Down Expand Up @@ -59,15 +60,17 @@ describe('InputHandler', () => {
let bufferService: IBufferService;
let coreService: ICoreService;
let optionsService: MockOptionsService;
let oscLinkService: IOscLinkService;
let inputHandler: TestInputHandler;

beforeEach(() => {
optionsService = new MockOptionsService();
bufferService = new BufferService(optionsService);
bufferService.resize(80, 30);
coreService = new CoreService(bufferService, new MockLogService(), optionsService);
oscLinkService = new OscLinkService(bufferService);

inputHandler = new TestInputHandler(bufferService, new MockCharsetService(), coreService, new MockLogService(), optionsService, new MockOscLinkService(), new MockCoreMouseService(), new MockUnicodeService());
inputHandler = new TestInputHandler(bufferService, new MockCharsetService(), coreService, new MockLogService(), optionsService, oscLinkService, new MockCoreMouseService(), new MockUnicodeService());
});

describe('SL/SR/DECIC/DECDC', () => {
Expand Down Expand Up @@ -1982,6 +1985,32 @@ describe('InputHandler', () => {
assert.deepEqual(stack, [[{ type: ColorRequestType.SET, index: 0, color: [170, 187, 204] }, { type: ColorRequestType.SET, index: 123, color: [0, 17, 34] }]]);
stack.length = 0;
});
it('8: hyperlink with id', async () => {
await inputHandler.parseP('\x1b]8;id=100;http://localhost:3000\x07');
assert.notStrictEqual(inputHandler.curAttrData.extended.urlId, 0);
assert.deepStrictEqual(
oscLinkService.getLinkData(inputHandler.curAttrData.extended.urlId),
{
id: '100',
uri: 'http://localhost:3000'
}
);
await inputHandler.parseP('\x1b]8;;\x07');
assert.strictEqual(inputHandler.curAttrData.extended.urlId, 0);
});
it('8: hyperlink with semi-colon', async () => {
await inputHandler.parseP('\x1b]8;;http://localhost:3000;abc=def\x07');
assert.notStrictEqual(inputHandler.curAttrData.extended.urlId, 0);
assert.deepStrictEqual(
oscLinkService.getLinkData(inputHandler.curAttrData.extended.urlId),
{
id: undefined,
uri: 'http://localhost:3000;abc=def'
}
);
await inputHandler.parseP('\x1b]8;;\x07');
assert.strictEqual(inputHandler.curAttrData.extended.urlId, 0);
});
it('104: restore events', async () => {
const stack: IColorEvent[] = [];
inputHandler.onColor(ev => stack.push(ev));
Expand Down
16 changes: 10 additions & 6 deletions src/common/InputHandler.ts
Expand Up @@ -2972,14 +2972,18 @@ export class InputHandler extends Disposable implements IInputHandler {
* feedback. Use `OSC 8 ; ; BEL` to finish the current hyperlink.
*/
public setHyperlink(data: string): boolean {
const args = data.split(';');
if (args.length < 2) {
return false;
// Arg parsing is special cases to support unencoded semi-colons in the URIs (#4944)
const idx = data.indexOf(';');
if (idx === -1) {
// malformed sequence, just return as handled
return true;
}
if (args[1]) {
return this._createHyperlink(args[0], args[1]);
const id = data.slice(0, idx).trim();
const uri = data.slice(idx + 1);
if (uri) {
return this._createHyperlink(id, uri);
}
if (args[0].trim()) {
if (id.trim()) {
return false;
}
return this._finishHyperlink();
Expand Down

0 comments on commit 826c057

Please sign in to comment.