diff --git a/.gitignore b/.gitignore index 5a3614e3..482996f6 100644 --- a/.gitignore +++ b/.gitignore @@ -76,4 +76,6 @@ out/ **/*.xml dist/** !dist/core/ -!dist/core/package.json \ No newline at end of file +!dist/core/package.json +/core/ +/bundles/ \ No newline at end of file diff --git a/src/core/TerminalDataProcessor.ts b/src/core/TerminalDataProcessor.ts index e371618a..d6514f59 100644 --- a/src/core/TerminalDataProcessor.ts +++ b/src/core/TerminalDataProcessor.ts @@ -9,6 +9,8 @@ import { type IDataProcessor } from './Interfaces' /** class to process serial over lan data **/ export class TerminalDataProcessor implements IDataProcessor { terminal: AmtTerminal + private readonly decoder = new TextDecoder('utf-8') + constructor(terminal) { this.terminal = terminal } @@ -19,17 +21,15 @@ export class TerminalDataProcessor implements IDataProcessor { /** processing data received from serial port**/ processData = (str: string): any => { if (this.terminal.capture != null) this.terminal.capture = String(this.terminal.capture) + str - let c = '' + const bytes: number[] = [] for (let i = 0; i < str.length; i++) { const ch = str.charCodeAt(i) if (str[i] === 'J') { this.clearTerminal() - } else if ((ch & 0x80) !== 0) { - c += String.fromCharCode(this.terminal.AsciiToUnicode[ch & 0x7f]) } else { - c += `${str[i]}` + bytes.push(ch & 0xff) } } - this.processDataToXterm(c) + this.processDataToXterm(this.decoder.decode(new Uint8Array(bytes), { stream: true })) } } diff --git a/src/test/terminaldataprocessor.test.ts b/src/test/terminaldataprocessor.test.ts index 4248ff4d..bae90f14 100644 --- a/src/test/terminaldataprocessor.test.ts +++ b/src/test/terminaldataprocessor.test.ts @@ -6,10 +6,14 @@ import { TerminalDataProcessor } from '../core/TerminalDataProcessor' import { AmtTerminal } from '../core/AMTTerminal' import { AmtTerminal2 } from './helper/amtTerminal2' +import { TextDecoder, TextEncoder } from 'util' + +globalThis.TextDecoder = TextDecoder as typeof globalThis.TextDecoder +globalThis.TextEncoder = TextEncoder as typeof globalThis.TextEncoder describe('Test TerminalDataProcessor class', () => { let result = '' - it('Test TerminalDataProcessor for processData', () => { + it('decodes UTF-8 data received in one chunk', () => { // callback function for Unit testing function callback(value: string): void { result = value @@ -21,34 +25,36 @@ describe('Test TerminalDataProcessor class', () => { tdataprocessor.processDataToXterm = callback // Test input - const s = 'abcD123?!=*“€' + const s = String.fromCharCode(...new TextEncoder().encode('abcD123?!=*“€')) // call processdata tdataprocessor.processData(s) // Test output - expect(result).toBe('abcD123?!=*“¼') + expect(result).toBe('abcD123?!=*“€') }) - it('Test TerminalDataProcessor for processData', () => { + it('decodes UTF-8 data split across chunks', () => { // callback function for Unit testing function callback(value: string): void { - result = value + result += value } // create object and set callback + result = '' const term = new AmtTerminal2(1) const tdataprocessor = new TerminalDataProcessor(term) tdataprocessor.processDataToXterm = callback // Test input - const s = "123Z?“€'" + const encoded = new TextEncoder().encode("123Z?“€'") + const split = encoded.indexOf(0xe2) + 1 - // call processdata - tdataprocessor.processData(s) + tdataprocessor.processData(String.fromCharCode(...encoded.slice(0, split))) + tdataprocessor.processData(String.fromCharCode(...encoded.slice(split))) // Test output - expect(result).toBe("123Z?“¼'") - expect(term.capture).toBe("123Z?“€'") + expect(result).toBe("123Z?“€'") + expect(term.capture).toBe(String.fromCharCode(...encoded)) }) })