diff --git a/src/browser/public/Terminal.ts b/src/browser/public/Terminal.ts index bd95599f96..33aa90246e 100644 --- a/src/browser/public/Terminal.ts +++ b/src/browser/public/Terminal.ts @@ -3,7 +3,7 @@ * @license MIT */ -import { Terminal as ITerminalApi, ITerminalOptions, IMarker, IDisposable, ILinkMatcherOptions, ITheme, ILocalizableStrings, ITerminalAddon, ISelectionPosition, IBuffer as IBufferApi, IBufferNamespace as IBufferNamespaceApi, IBufferLine as IBufferLineApi, IBufferCell as IBufferCellApi, IParser, IFunctionIdentifier, ILinkProvider, IUnicodeHandling, IUnicodeVersionProvider } from 'xterm'; +import { Terminal as ITerminalApi, ITerminalOptions, IMarker, IDisposable, ILinkMatcherOptions, ITheme, ILocalizableStrings, ITerminalAddon, ISelectionPosition, IBuffer as IBufferApi, IBufferNamespace as IBufferNamespaceApi, IBufferLine as IBufferLineApi, IBufferCell as IBufferCellApi, IParser, IFunctionIdentifier, ILinkProvider, IUnicodeHandling, IUnicodeVersionProvider, FontWeight } from 'xterm'; import { ITerminal } from 'browser/Types'; import { IBufferLine, ICellData } from 'common/Types'; import { IBuffer, IBufferSet } from 'common/buffer/Types'; @@ -169,15 +169,16 @@ export class Terminal implements ITerminalApi { public paste(data: string): void { this._core.paste(data); } - public getOption(key: 'bellSound' | 'bellStyle' | 'cursorStyle' | 'fontFamily' | 'fontWeight' | 'fontWeightBold' | 'logLevel' | 'rendererType' | 'termName' | 'wordSeparator'): string; + public getOption(key: 'bellSound' | 'bellStyle' | 'cursorStyle' | 'fontFamily' | 'logLevel' | 'rendererType' | 'termName' | 'wordSeparator'): string; public getOption(key: 'allowTransparency' | 'cancelEvents' | 'convertEol' | 'cursorBlink' | 'disableStdin' | 'macOptionIsMeta' | 'rightClickSelectsWord' | 'popOnBell' | 'visualBell'): boolean; public getOption(key: 'cols' | 'fontSize' | 'letterSpacing' | 'lineHeight' | 'rows' | 'tabStopWidth' | 'scrollback'): number; + public getOption(key: 'fontWeight' | 'fontWeightBold'): FontWeight; public getOption(key: string): any; public getOption(key: any): any { return this._core.optionsService.getOption(key); } public setOption(key: 'bellSound' | 'fontFamily' | 'termName' | 'wordSeparator', value: string): void; - public setOption(key: 'fontWeight' | 'fontWeightBold', value: 'normal' | 'bold' | '100' | '200' | '300' | '400' | '500' | '600' | '700' | '800' | '900'): void; + public setOption(key: 'fontWeight' | 'fontWeightBold', value: 'normal' | 'bold' | '100' | '200' | '300' | '400' | '500' | '600' | '700' | '800' | '900' | number): void; public setOption(key: 'logLevel', value: 'debug' | 'info' | 'warn' | 'error' | 'off'): void; public setOption(key: 'bellStyle', value: 'none' | 'visual' | 'sound' | 'both'): void; public setOption(key: 'cursorStyle', value: 'block' | 'underline' | 'bar'): void; diff --git a/src/common/services/OptionsService.test.ts b/src/common/services/OptionsService.test.ts index 59c17faf9e..c289b5be1d 100644 --- a/src/common/services/OptionsService.test.ts +++ b/src/common/services/OptionsService.test.ts @@ -19,4 +19,42 @@ describe('OptionsService', () => { assert.equal(new OptionsService({tabStopWidth: 0}).getOption('tabStopWidth'), DEFAULT_OPTIONS.tabStopWidth); }); }); + describe('setOption', () => { + let service: OptionsService; + beforeEach(() => { + service = new OptionsService({}); + }); + it('applies valid fontWeight option values', () => { + service.setOption('fontWeight', 'bold'); + assert.equal(service.getOption('fontWeight'), 'bold', '"bold" keyword value should be applied'); + + service.setOption('fontWeight', 'normal'); + assert.equal(service.getOption('fontWeight'), 'normal', '"normal" keyword value should be applied'); + + service.setOption('fontWeight', '600'); + assert.equal(service.getOption('fontWeight'), '600', 'String numeric values should be applied'); + + service.setOption('fontWeight', 350); + assert.equal(service.getOption('fontWeight'), 350, 'Values between 1 and 1000 should be applied as is'); + + service.setOption('fontWeight', 1); + assert.equal(service.getOption('fontWeight'), 1, 'Range should include minimum value: 1'); + + service.setOption('fontWeight', 1000); + assert.equal(service.getOption('fontWeight'), 1000, 'Range should include maximum value: 1000'); + }); + it('normalizes invalid fontWeight option values', () => { + service.setOption('fontWeight', 350); + assert.doesNotThrow(() => service.setOption('fontWeight', 10000), 'fontWeight should be normalized instead of throwing'); + assert.equal(service.getOption('fontWeight'), DEFAULT_OPTIONS.fontWeight, 'Values greater than 1000 should be reset to default'); + + service.setOption('fontWeight', 350); + service.setOption('fontWeight', -10); + assert.equal(service.getOption('fontWeight'), DEFAULT_OPTIONS.fontWeight, 'Values less than 1 should be reset to default'); + + service.setOption('fontWeight', 350); + service.setOption('fontWeight', 'bold700'); + assert.equal(service.getOption('fontWeight'), DEFAULT_OPTIONS.fontWeight, 'Wrong string literals should be reset to default'); + }); + }); }); diff --git a/src/common/services/OptionsService.ts b/src/common/services/OptionsService.ts index 2f01092382..e5f6eaa8dc 100644 --- a/src/common/services/OptionsService.ts +++ b/src/common/services/OptionsService.ts @@ -3,7 +3,7 @@ * @license MIT */ -import { IOptionsService, ITerminalOptions, IPartialTerminalOptions } from 'common/services/Services'; +import { IOptionsService, ITerminalOptions, IPartialTerminalOptions, FontWeight } from 'common/services/Services'; import { EventEmitter, IEvent } from 'common/EventEmitter'; import { isMac } from 'common/Platform'; import { clone } from 'common/Clone'; @@ -56,6 +56,8 @@ export const DEFAULT_OPTIONS: ITerminalOptions = Object.freeze({ cancelEvents: false }); +const FONT_WEIGHT_OPTIONS: Extract[] = ['normal', 'bold', '100', '200', '300', '400', '500', '600', '700', '800', '900']; + /** * The set of options that only have an effect when set in the Terminal constructor. */ @@ -109,14 +111,20 @@ export class OptionsService implements IOptionsService { switch (key) { case 'bellStyle': case 'cursorStyle': - case 'fontWeight': - case 'fontWeightBold': case 'rendererType': case 'wordSeparator': if (!value) { value = DEFAULT_OPTIONS[key]; } break; + case 'fontWeight': + case 'fontWeightBold': + if (typeof value === 'number' && 1 <= value && value <= 1000) { + // already valid numeric value + break; + } + value = FONT_WEIGHT_OPTIONS.indexOf(value) !== -1 ? value : DEFAULT_OPTIONS[key]; + break; case 'cursorWidth': value = Math.floor(value); // Fall through for bounds check diff --git a/src/common/services/Services.ts b/src/common/services/Services.ts index 19a34d19f5..0ea7a30804 100644 --- a/src/common/services/Services.ts +++ b/src/common/services/Services.ts @@ -179,7 +179,7 @@ export interface IOptionsService { getOption(key: string): T | undefined; } -export type FontWeight = 'normal' | 'bold' | '100' | '200' | '300' | '400' | '500' | '600' | '700' | '800' | '900'; +export type FontWeight = 'normal' | 'bold' | '100' | '200' | '300' | '400' | '500' | '600' | '700' | '800' | '900' | number; export type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'off'; export type RendererType = 'dom' | 'canvas'; diff --git a/typings/xterm.d.ts b/typings/xterm.d.ts index f98c629d76..1fc0c853ba 100644 --- a/typings/xterm.d.ts +++ b/typings/xterm.d.ts @@ -11,9 +11,9 @@ declare module 'xterm' { /** - * A string representing text font weight. + * A string or number representing text font weight. */ - export type FontWeight = 'normal' | 'bold' | '100' | '200' | '300' | '400' | '500' | '600' | '700' | '800' | '900'; + export type FontWeight = 'normal' | 'bold' | '100' | '200' | '300' | '400' | '500' | '600' | '700' | '800' | '900' | number; /** * A string representing log level. @@ -933,7 +933,7 @@ declare module 'xterm' { * Retrieves an option's value from the terminal. * @param key The option key. */ - getOption(key: 'bellSound' | 'bellStyle' | 'cursorStyle' | 'fontFamily' | 'fontWeight' | 'fontWeightBold' | 'logLevel' | 'rendererType' | 'termName' | 'wordSeparator'): string; + getOption(key: 'bellSound' | 'bellStyle' | 'cursorStyle' | 'fontFamily' | 'logLevel' | 'rendererType' | 'termName' | 'wordSeparator'): string; /** * Retrieves an option's value from the terminal. * @param key The option key. @@ -944,6 +944,11 @@ declare module 'xterm' { * @param key The option key. */ getOption(key: 'cols' | 'fontSize' | 'letterSpacing' | 'lineHeight' | 'rows' | 'tabStopWidth' | 'scrollback'): number; + /** + * Retrieves an option's value from the terminal. + * @param key The option key. + */ + getOption(key: 'fontWeight' | 'fontWeightBold'): FontWeight; /** * Retrieves an option's value from the terminal. * @param key The option key. @@ -961,7 +966,7 @@ declare module 'xterm' { * @param key The option key. * @param value The option value. */ - setOption(key: 'fontWeight' | 'fontWeightBold', value: null | 'normal' | 'bold' | '100' | '200' | '300' | '400' | '500' | '600' | '700' | '800' | '900'): void; + setOption(key: 'fontWeight' | 'fontWeightBold', value: null | 'normal' | 'bold' | '100' | '200' | '300' | '400' | '500' | '600' | '700' | '800' | '900' | number): void; /** * Sets an option on the terminal. * @param key The option key.