mirror of
https://github.com/wavetermdev/xterm.js.git
synced 2026-08-05 13:43:48 -07:00
Cleanup - fix various tests.
This commit is contained in:
@@ -10,7 +10,7 @@ import * as UC from './UnicodeProperties';
|
||||
|
||||
export class UnicodeGraphemeProvider implements IUnicodeVersionProvider {
|
||||
public readonly version = '15-graphemes';
|
||||
|
||||
public ambiguousCharsAreWide: boolean = false;
|
||||
constructor() {
|
||||
}
|
||||
|
||||
@@ -19,9 +19,8 @@ export class UnicodeGraphemeProvider implements IUnicodeVersionProvider {
|
||||
let w = UC.infoToWidthInfo(charInfo);
|
||||
let shouldJoin = false;
|
||||
if (w >= 2) {
|
||||
const preferWide = false; //this.ambiguousCharsAreWide(context);
|
||||
// Treat emoji_presentation_selector as WIDE.
|
||||
w = w == 3 || preferWide || codepoint === 0xfe0f ? 2 : 1;
|
||||
w = w == 3 || this.ambiguousCharsAreWide || codepoint === 0xfe0f ? 2 : 1;
|
||||
} else
|
||||
w = 1;
|
||||
if (preceding !== 0) {
|
||||
@@ -31,14 +30,23 @@ export class UnicodeGraphemeProvider implements IUnicodeVersionProvider {
|
||||
if (shouldJoin) {
|
||||
if (oldWidth > w)
|
||||
w = oldWidth;
|
||||
else if (charInfo === 32) // FIXME UC.GRAPHEME_BREAK_SAW_Regional_Pair)
|
||||
else if (charInfo === 32) // FIXME UC.GRAPHEME_BREAK_SAW_Regional_Pair)
|
||||
w = 2;
|
||||
}
|
||||
}
|
||||
return UnicodeService.createPropertyValue(charInfo, w, shouldJoin);
|
||||
}
|
||||
|
||||
public wcwidth(num: number): UnicodeCharWidth {
|
||||
return UC.infoToWidth(UC.getInfo(num));
|
||||
public wcwidth(codepoint: number): UnicodeCharWidth {
|
||||
let charInfo = UC.getInfo(codepoint);
|
||||
let w = UC.infoToWidthInfo(charInfo);
|
||||
let kind = (charInfo & UC.GRAPHEME_BREAK_MASK) >> UC.GRAPHEME_BREAK_SHIFT;
|
||||
if (kind === UC.GRAPHEME_BREAK_Extend
|
||||
|| kind === UC.GRAPHEME_BREAK_Prepend)
|
||||
return 0;
|
||||
else if (w >= 2)
|
||||
return w == 3 || this.ambiguousCharsAreWide? 2 : 1;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* Copyright (c) 2019 The xterm.js authors. All rights reserved.
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { assert } from 'chai';
|
||||
import { openTerminal, launchBrowser } from '../../../out-test/api/TestUtils';
|
||||
import { Browser, Page } from 'playwright';
|
||||
|
||||
const APP = 'http://127.0.0.1:3001/test';
|
||||
|
||||
let browser: Browser;
|
||||
let page: Page;
|
||||
const width = 800;
|
||||
const height = 600;
|
||||
|
||||
describe('UnicodeGraphemesAddon', () => {
|
||||
before(async function(): Promise<any> {
|
||||
browser = await launchBrowser();
|
||||
page = await (await browser.newContext()).newPage();
|
||||
await page.setViewportSize({ width, height });
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await browser.close();
|
||||
});
|
||||
|
||||
beforeEach(async function(): Promise<any> {
|
||||
await page.goto(APP);
|
||||
await openTerminal(page);
|
||||
});
|
||||
const ourVersion = '15-graphemes';
|
||||
it('wcwidth V15 emoji test', async () => {
|
||||
await page.evaluate(`
|
||||
window.unicode = new UnicodeGraphemesAddon();
|
||||
window.term.loadAddon(window.unicode);
|
||||
`);
|
||||
// should have loaded '15-graphemes'
|
||||
assert.deepEqual(await page.evaluate(`window.term.unicode.versions`), ['6', ourVersion]);
|
||||
// switch should not throw
|
||||
await page.evaluate(`window.term.unicode.activeVersion = '${ourVersion}';`);
|
||||
assert.deepEqual(await page.evaluate(`window.term.unicode.activeVersion`), ourVersion);
|
||||
// v6: 10, V15: 20
|
||||
assert.deepEqual(await page.evaluate(`window.term._core.unicodeService.getStringCellWidth('🤣🤣🤣🤣🤣🤣🤣🤣🤣🤣')`), 20);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"target": "es2015",
|
||||
"lib": [
|
||||
"dom",
|
||||
"es2015"
|
||||
],
|
||||
"rootDir": ".",
|
||||
"outDir": "../out-test",
|
||||
"sourceMap": true,
|
||||
"removeComments": true,
|
||||
"strict": true,
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"common/*": [
|
||||
"../../../src/common/*"
|
||||
]
|
||||
},
|
||||
"types": [
|
||||
"../../../node_modules/@types/mocha",
|
||||
"../../../node_modules/@types/node",
|
||||
"../../../out-test/api/TestUtils"
|
||||
]
|
||||
},
|
||||
"include": [
|
||||
"./**/*",
|
||||
"../../../typings/xterm.d.ts"
|
||||
],
|
||||
"references": [
|
||||
{
|
||||
"path": "../../../src/common"
|
||||
}
|
||||
]
|
||||
}
|
||||
+2
-2
@@ -1,11 +1,11 @@
|
||||
/**
|
||||
* Copyright (c) 2017 The xterm.js authors. All rights reserved.
|
||||
* Copyright (c) 2023 The xterm.js authors. All rights reserved.
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { Terminal, ITerminalAddon } from 'xterm';
|
||||
|
||||
declare module 'xterm-addon-unicode11' {
|
||||
declare module 'xterm-addon-unicode-graphemes' {
|
||||
export class Unicode11Addon implements ITerminalAddon {
|
||||
constructor();
|
||||
public activate(terminal: Terminal): void;
|
||||
@@ -219,14 +219,12 @@ export class UnicodeV11 implements IUnicodeVersionProvider {
|
||||
return 1;
|
||||
}
|
||||
|
||||
charProperties(codepoint: number, preceding: UnicodeCharProperties): UnicodeCharProperties {
|
||||
public charProperties(codepoint: number, preceding: UnicodeCharProperties): UnicodeCharProperties {
|
||||
let width = this.wcwidth(codepoint);
|
||||
let shouldJoin = width === 0;
|
||||
let shouldJoin = width === 0 && preceding !== 0;
|
||||
if (shouldJoin) {
|
||||
let oldWidth = preceding === 0 ? 0
|
||||
: UnicodeService.extractWidth(preceding);
|
||||
const oldWidth = UnicodeService.extractWidth(preceding);
|
||||
if (oldWidth === 0) {
|
||||
width = 1;
|
||||
shouldJoin = false;
|
||||
} else if (oldWidth > width) {
|
||||
width = oldWidth;
|
||||
|
||||
+10
-26
@@ -530,16 +530,15 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
}
|
||||
}
|
||||
|
||||
let precedingInfo = this._parser.precedingCodepoint === 0 ? 0
|
||||
const precedingInfo = this._parser.precedingCodepoint === 0 ? 0
|
||||
: this._parser.precedingJoinState;
|
||||
// calculate print space
|
||||
// expensive call, therefore we save width in line buffer
|
||||
let currentInfo = this._unicodeService.charProperties(code, precedingInfo);
|
||||
let chWidth = UnicodeService.extractWidth(currentInfo);
|
||||
let shouldJoin = UnicodeService.extractShouldJoin(currentInfo);
|
||||
const currentInfo = this._unicodeService.charProperties(code, precedingInfo);
|
||||
chWidth = UnicodeService.extractWidth(currentInfo);
|
||||
const shouldJoin = UnicodeService.extractShouldJoin(currentInfo);
|
||||
const oldWidth = shouldJoin ? UnicodeService.extractWidth(precedingInfo) : 0;
|
||||
this._parser.precedingCodepoint = code;
|
||||
this._parser.precedingJoinState = currentInfo;
|
||||
|
||||
if (screenReaderMode) {
|
||||
this._onA11yChar.fire(stringFromCodePoint(code));
|
||||
}
|
||||
@@ -575,7 +574,7 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
// Combining character widens 1 column to 2.
|
||||
// Move old character to next line.
|
||||
bufferRow.copyCellsFrom(oldRow as BufferLine,
|
||||
oldCol, 0, oldWidth, false);
|
||||
oldCol, 0, oldWidth, false);
|
||||
}
|
||||
// clear left over cells to the right
|
||||
while (oldCol < cols) {
|
||||
@@ -596,12 +595,12 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
// since they always follow a cell consuming char
|
||||
// therefore we can test for this._activeBuffer.x to avoid overflow left
|
||||
if (shouldJoin && this._activeBuffer.x) {
|
||||
const offset = bufferRow.getWidth(this._activeBuffer.x - 1) ? 1 : 2
|
||||
const offset = bufferRow.getWidth(this._activeBuffer.x - 1) ? 1 : 2;
|
||||
// if empty cell after fullwidth, need to go 2 cells back
|
||||
// it is save to step 2 cells back here
|
||||
// since an empty cell is only set by fullwidth chars
|
||||
bufferRow.addCodepointToCell(this._activeBuffer.x - offset,
|
||||
code, chWidth);
|
||||
code, chWidth);
|
||||
this._activeBuffer.x += chWidth - oldWidth;
|
||||
continue;
|
||||
}
|
||||
@@ -609,7 +608,7 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
// insert mode: move characters to right
|
||||
if (insertMode) {
|
||||
// right shift cells according to the width
|
||||
bufferRow.insertCells(this._activeBuffer.x, chWidth, this._activeBuffer.getNullCell(curAttr), curAttr);
|
||||
bufferRow.insertCells(this._activeBuffer.x, chWidth - oldWidth, this._activeBuffer.getNullCell(curAttr), curAttr);
|
||||
// test last cell - since the last cell has only room for
|
||||
// a halfwidth char any fullwidth shifted there is lost
|
||||
// and will be set to empty cell
|
||||
@@ -631,22 +630,7 @@ export class InputHandler extends Disposable implements IInputHandler {
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
// store last char in Parser.precedingCodepoint for REP to work correctly
|
||||
// This needs to check whether:
|
||||
// - fullwidth + surrogates: reset
|
||||
// - combining: only base char gets carried on (bug in xterm?)
|
||||
if (end - start > 0) {
|
||||
bufferRow.loadCell(this._activeBuffer.x - 1, this._workCell);
|
||||
if (this._workCell.getWidth() === 2 || this._workCell.getCode() > 0xFFFF) {
|
||||
this._parser.precedingCodepoint = 0;
|
||||
} else if (this._workCell.isCombined()) {
|
||||
this._parser.precedingCodepoint = this._workCell.getChars().charCodeAt(0);
|
||||
} else {
|
||||
this._parser.precedingCodepoint = this._workCell.content;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// handle wide chars: reset cell to the right if it is second cell of a wide char
|
||||
if (this._activeBuffer.x < cols && end - start > 0 && bufferRow.getWidth(this._activeBuffer.x) === 0 && !bufferRow.hasContent(this._activeBuffer.x)) {
|
||||
bufferRow.setCellFromCodePoint(this._activeBuffer.x, 0, 1, curAttr.fg, curAttr.bg, curAttr.extended);
|
||||
|
||||
@@ -170,9 +170,17 @@ export class MockUnicodeService implements IUnicodeService {
|
||||
public onChange: IEvent<string> = new EventEmitter<string>().event;
|
||||
public wcwidth = (codepoint: number): UnicodeCharWidth => this._provider.wcwidth(codepoint);
|
||||
public charProperties(codepoint: number, preceding: UnicodeCharProperties): UnicodeCharProperties {
|
||||
const w = this.wcwidth(codepoint);
|
||||
const shouldJoin = w !== 0;
|
||||
return UnicodeService.createPropertyValue(0, w, shouldJoin);
|
||||
let width = this.wcwidth(codepoint);
|
||||
let shouldJoin = width === 0 && preceding !== 0;
|
||||
if (shouldJoin) {
|
||||
const oldWidth = UnicodeService.extractWidth(preceding);
|
||||
if (oldWidth === 0) {
|
||||
shouldJoin = false;
|
||||
} else if (oldWidth > width) {
|
||||
width = oldWidth;
|
||||
}
|
||||
}
|
||||
return UnicodeService.createPropertyValue(0, width, shouldJoin);
|
||||
}
|
||||
public getStringCellWidth(s: string): number {
|
||||
throw new Error('Method not implemented.');
|
||||
|
||||
@@ -227,7 +227,7 @@ export class BufferLine implements IBufferLine {
|
||||
* onto a leading char. Since we already set the attrs
|
||||
* by the previous `setDataFromCodePoint` call, we can omit it here.
|
||||
*/
|
||||
public addCodepointToCell(index: number, codePoint: number, width: number): void {
|
||||
public addCodepointToCell(index: number, codePoint: number, width: number): void {
|
||||
let content = this._data[index * CELL_SIZE + Cell.CONTENT];
|
||||
if (content & Content.IS_COMBINED_MASK) {
|
||||
// we already have a combined string, simply add
|
||||
|
||||
@@ -2,8 +2,7 @@
|
||||
* Copyright (c) 2019 The xterm.js authors. All rights reserved.
|
||||
* @license MIT
|
||||
*/
|
||||
import { IUnicodeVersionProvider } from 'common/services/Services';
|
||||
import { UnicodeCharProperties, UnicodeCharWidth } from 'common/services/Services';
|
||||
import { IUnicodeVersionProvider, UnicodeCharProperties, UnicodeCharWidth } from 'common/services/Services';
|
||||
import { UnicodeService } from 'common/services/UnicodeService';
|
||||
|
||||
const BMP_COMBINING = [
|
||||
@@ -130,14 +129,12 @@ export class UnicodeV6 implements IUnicodeVersionProvider {
|
||||
return 1;
|
||||
}
|
||||
|
||||
charProperties(codepoint: number, preceding: UnicodeCharProperties): UnicodeCharProperties {
|
||||
public charProperties(codepoint: number, preceding: UnicodeCharProperties): UnicodeCharProperties {
|
||||
let width = this.wcwidth(codepoint);
|
||||
let shouldJoin = width === 0;
|
||||
let shouldJoin = width === 0 && preceding !== 0;
|
||||
if (shouldJoin) {
|
||||
let oldWidth = preceding === 0 ? 0
|
||||
: UnicodeService.extractWidth(preceding);
|
||||
const oldWidth = UnicodeService.extractWidth(preceding);
|
||||
if (oldWidth === 0) {
|
||||
width = 1;
|
||||
shouldJoin = false;
|
||||
} else if (oldWidth > width) {
|
||||
width = oldWidth;
|
||||
|
||||
@@ -296,7 +296,6 @@ export interface IOscLinkService {
|
||||
|
||||
/** Width and Grapheme_Cluster_Break properties of a character. */
|
||||
export type UnicodeCharProperties = number;
|
||||
export const UnicodeInitialProperties: UnicodeCharProperties = 0; // UNEEDED?
|
||||
export type UnicodeCharWidth = 0 | 1 | 2;
|
||||
|
||||
export const IUnicodeService = createDecorator<IUnicodeService>('UnicodeService');
|
||||
|
||||
@@ -12,7 +12,7 @@ class DummyProvider implements IUnicodeVersionProvider {
|
||||
public wcwidth(n: number): 0 | 1 | 2 {
|
||||
return 2;
|
||||
}
|
||||
charProperties(codepoint: number): number {
|
||||
public charProperties(codepoint: number): number {
|
||||
return UnicodeService.createPropertyValue(0, this.wcwidth(codepoint));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,6 +70,7 @@ export class UnicodeService implements IUnicodeService {
|
||||
|
||||
public getStringCellWidth(s: string): number {
|
||||
let result = 0;
|
||||
let precedingInfo = 0;
|
||||
const length = s.length;
|
||||
for (let i = 0; i < length; ++i) {
|
||||
let code = s.charCodeAt(i);
|
||||
@@ -92,12 +93,18 @@ export class UnicodeService implements IUnicodeService {
|
||||
result += this.wcwidth(second);
|
||||
}
|
||||
}
|
||||
result += this.wcwidth(code);
|
||||
const currentInfo = this.charProperties(code, precedingInfo);
|
||||
let chWidth = UnicodeService.extractWidth(currentInfo);
|
||||
if (UnicodeService.extractShouldJoin(currentInfo)) {
|
||||
chWidth -= UnicodeService.extractWidth(precedingInfo);
|
||||
}
|
||||
result += chWidth;
|
||||
precedingInfo = currentInfo;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
charProperties(codepoint: number, preceding: UnicodeCharProperties): UnicodeCharProperties {
|
||||
public charProperties(codepoint: number, preceding: UnicodeCharProperties): UnicodeCharProperties {
|
||||
return this._activeProvider.charProperties(codepoint, preceding);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user