From df3506af2665440dc3f3d6bda9b47d2131ceb483 Mon Sep 17 00:00:00 2001 From: Jakub Jankiewicz Date: Sun, 28 Apr 2024 14:18:12 +0200 Subject: [PATCH] unit tests for xml formatting + improvements --- CHANGELOG.md | 6 ++ README.md | 22 ++--- __tests__/__snapshots__/terminal.spec.js.snap | 37 ++++++++ __tests__/terminal.spec.js | 93 ++++++++++++++++++- js/xml_formatting.js | 40 ++++---- 5 files changed, 164 insertions(+), 34 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 24f54ca7..3e4c6348 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## 2.41.0 +### Features +* allow to use class and other attributes in style XML tags (like `` or ``) +### Bugfix +* fix alt image attribute + ## 2.40.6 ### Bugfix * fix resize of text from long animation after finish diff --git a/README.md b/README.md index e54af184..8cb4b82b 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,14 @@

- ASCII Art that represent text jQuery Terminal - JavaScript Library for Web Based Terminal Emulators

[JavaScript Library for Web Based Terminal Emulators](https://terminal.jcubic.pl) -[![npm](https://img.shields.io/badge/npm-2.40.6-blue.svg)](https://www.npmjs.com/package/jquery.terminal) -![bower](https://img.shields.io/badge/bower-2.40.6-yellow.svg) -[![Build and test](https://github.com/jcubic/jquery.terminal/actions/workflows/build.yaml/badge.svg?branch=master&event=push)](https://github.com/jcubic/jquery.terminal/actions/workflows/build.yaml) -[![Coverage Status](https://coveralls.io/repos/github/jcubic/jquery.terminal/badge.svg?branch=master&de53a76e58fa938d09d172e6ddf1bb8c)](https://coveralls.io/github/jcubic/jquery.terminal?branch=master) +[![npm](https://img.shields.io/badge/npm-DEV-blue.svg)](https://www.npmjs.com/package/jquery.terminal) +![bower](https://img.shields.io/badge/bower-DEV-yellow.svg) +[![Build and test](https://github.com/jcubic/jquery.terminal/actions/workflows/build.yaml/badge.svg?branch=devel&event=push)](https://github.com/jcubic/jquery.terminal/actions/workflows/build.yaml) +[![Coverage Status](https://coveralls.io/repos/github/jcubic/jquery.terminal/badge.svg?branch=devel&1b4f43839e9a18890938b506396293ca)](https://coveralls.io/github/jcubic/jquery.terminal?branch=devel) ![NPM Downloads](https://img.shields.io/npm/dm/jquery.terminal.svg?style=flat) [![jsDelivr Downloads](https://data.jsdelivr.com/v1/package/npm/jquery.terminal/badge?style=rounded&n=1)](https://www.jsdelivr.com/package/npm/jquery.terminal) [![Paid Support](https://img.shields.io/badge/paid-support-354465.svg)](https://support.jcubic.pl/) @@ -87,7 +87,7 @@ You can test current version at this URL: or if it doesn't use latest version (because of jsDelivr cache) you can force it with this URL: -* [https://jcubic.github.io/jquery.terminal/?ver=2.40.6](https://jcubic.github.io/jquery.terminal/?ver=2.40.6) +* [https://jcubic.github.io/jquery.terminal/?ver=DEV](https://jcubic.github.io/jquery.terminal/?ver=DEV) And development version using: @@ -106,20 +106,20 @@ or use jsDelivr: ``` -Then include js/jquery.terminal-2.40.6.min.js and css/jquery.terminal-2.40.6.min.css +Then include js/jquery.terminal-DEV.min.js and css/jquery.terminal-DEV.min.css You can grab the files from CDN: ```html - - + + ``` or ```html - - + + ``` If you always want latest version, you can get it from [unpkg](https://unpkg.com/) without specifying version, diff --git a/__tests__/__snapshots__/terminal.spec.js.snap b/__tests__/__snapshots__/terminal.spec.js.snap index 6b2868bc..9bf49d4d 100644 --- a/__tests__/__snapshots__/terminal.spec.js.snap +++ b/__tests__/__snapshots__/terminal.spec.js.snap @@ -779,6 +779,43 @@ Array [ ] `; +exports[`Terminal utils xml formatting should format font 1`] = ` +"[[;white;red;;;{\\"style\\":\\"--size:1.2;letter-spacing:2\\"}]Hello World] +[[;;red]Hello World] +[[;;;;;{\\"style\\":\\"--size:1.2;letter-spacing:2\\"}]Hello World]" +`; + +exports[`Terminal utils xml formatting should format font 2`] = `"
Hello World
Hello World
Hello World
"`; + +exports[`Terminal utils xml formatting should handle invalid xml 1`] = ` +"<< First Line [[[[ of Text <><> is little ]]] bit longer +<<<<>>>> Second ]]]] Line of Text +<<<< Thrid Line of Text" +`; + +exports[`Terminal utils xml formatting should render an empty image 1`] = `"[[@;;;;;{}]]"`; + +exports[`Terminal utils xml formatting should render colors 1`] = ` +"[[;white;;command;;{\\"class\\":\\"command\\"}]ls] +[[;green;;;;{}]ls] +[[;red;;error;;{\\"class\\":\\"error\\",\\"style\\":\\"background:red\\"}]Error: invalid message]" +`; + +exports[`Terminal utils xml formatting should render colors 2`] = `"
ls
ls
Error: invalid message
"`; + +exports[`Terminal utils xml formatting should render links 1`] = `"
example.com
example.com
"`; + +exports[`Terminal utils xml formatting should render tags 1`] = ` +"[[;;;foo;;{\\"class\\":\\"foo\\",\\"style\\":\\"color:red\\"}]text] +[[;;;;;{\\"style\\":\\"color:red\\"}]text] +[[i;;;;;{}]lorem] +[[g;;;;;{}]ipsum] +[[u;;;;;{}]dolor] +[[s;;;;;{}]sit] +[[o;;;;;{}]amet] +[[b;;;;;{}]foo]" +`; + exports[`extensions echo_newline should create sequance of animations (#930) 1`] = `"
Hello, jQuery Terminal
"`; exports[`extensions echo_newline should print mixed newline with !flush 1`] = ` diff --git a/__tests__/terminal.spec.js b/__tests__/terminal.spec.js index 6243e41e..a8e795db 100644 --- a/__tests__/terminal.spec.js +++ b/__tests__/terminal.spec.js @@ -247,6 +247,7 @@ global.URL = window.URL = { require('../js/jquery.terminal-src')(global.$); require('../js/unix_formatting')(global.$); +require('../js/xml_formatting')(global.$); require('../js/pipe')(global.$); require('../js/autocomplete_menu')(global.$); require('../js/less')(global.$); @@ -475,6 +476,78 @@ describe('Terminal utils', function() { }); }); }); + describe('xml formatting', function() { + let term; + beforeEach(() => { + term = $('
').terminal({}, {greetings: false}); + }); + afterEach(() => { + term.destroy(); + }); + it('should render tags', () => { + const input = [ + 'text', + 'text', + 'lorem', + 'ipsum', + 'dolor', + 'sit', + 'amet', + 'foo' + ].join('\n'); + expect($.terminal.apply_formatters(input)).toMatchSnapshot(); + }); + it('should handle invalid xml', () => { + const lines = [ + '<<< First Line [[[[ of Text ><><> is little ]]] bit longer', + '<<<<>>>> Second ]]]] Line of Text ', + '<<<< Thrid Line of Text' + ]; + expect($.terminal.apply_formatters(lines.join('\n'))).toMatchSnapshot(); + }); + it('should render an image', () => { + const url = './__tests__/__fixtures__/Ken_Thompson__and_Dennis_Ritchie_at_PDP-11.jpg'; + const cls = 'foo'; + const alt = 'this is an image'; + term.echo(`${alt}`); + const $img = term.find('img'); + expect($img.attr('src')).toEqual(url); + expect($img.attr('alt')).toEqual(nbsp(alt)); + expect($img.attr('class')).toEqual(cls); + }); + it('should render an empty image', () => { + expect($.terminal.apply_formatters('')).toMatchSnapshot(); + }); + it('should format font', () => { + const input = [ + 'Hello World', + 'Hello World', + 'Hello World' + ].join('\n'); + expect($.terminal.apply_formatters(input)).toMatchSnapshot(); + term.echo(input); + expect(term.find('.terminal-output').html()).toMatchSnapshot(); + }); + it('should render colors', () => { + const input = [ + 'ls', + 'ls', + 'Error: invalid message' + ].join('\n'); + expect($.terminal.apply_formatters(input)).toMatchSnapshot(); + term.echo(input); + expect(term.find('.terminal-output').html()).toMatchSnapshot(); + }); + it('should render links', () => { + const input = [ + 'example.com', + 'example.com', + 'Error: invalid message' + ].join('\n'); + term.echo(input); + expect(term.find('.terminal-output').html()).toMatchSnapshot(); + }); + }); describe('$.terminal.from_ansi', function() { var ansi_string = '\x1b[38;5;12mHello\x1b[2;31;46mFoo\x1b[1;3;4;32;45mB[[sb;;]a]r\x1b[0m\x1b[7mBaz\x1b[0;48;2;255;255;0;38;2;0;100;0mQuux\x1b[m'; it('should convert ansi to terminal formatting', function() { @@ -2067,6 +2140,9 @@ describe('Terminal utils', function() { expect(formatters.includes(formatter_1)).toBeTruthy(); expect(formatters.includes(formatter_2)).toBeTruthy(); }); + it('should use xml formatting', () => { + $.terminal.new_formatter([/foo/g, 'foo']); + }); }); describe('$.terminal.less', function() { var term; @@ -3261,17 +3337,23 @@ describe('Terminal plugin', function() { var term = $('
').terminal($.noop, { raw: true }); - beforeEach(function() { + let formatters; + beforeEach(() => { + formatters = $.terminal.defaults.formatters; + $.terminal.defaults.formatters = []; term.clear(); }); - var img = ''; + afterEach(() => { + $.terminal.defaults.formatters = formatters; + }); + const img = ''; it('should display html when no raw echo option is specified', function() { term.echo(img); expect(last_div(term).find('img').length).toEqual(1); }); it('should display html as text when using raw echo option', function() { term.echo(img, {raw: false}); - var output = last_div(term); + const output = last_div(term); expect(output.find('img').length).toEqual(0); expect(output.text().replace(/\s/g, ' ')).toEqual(img); }); @@ -3804,8 +3886,10 @@ describe('Terminal plugin', function() { }); describe('cmd plugin', function() { var string = ''; - var term, cmd, line, history; + var term, cmd, line, history, formatting; beforeEach(function() { + formatting = $.terminal.defaults.formatters; + $.terminal.defaults.formatters = []; term = $('
').appendTo('body').css('overflow-y', 'scroll').terminal($.noop, { name: 'cmd', numChars: 150, @@ -3820,6 +3904,7 @@ describe('Terminal plugin', function() { }); afterEach(function() { term.destroy().remove(); + $.terminal.defaults.formatters = formatting; }); it('text should have 2 lines', function() { expect(line.is('div')).toBe(true); diff --git a/js/xml_formatting.js b/js/xml_formatting.js index 27f63229..04764753 100644 --- a/js/xml_formatting.js +++ b/js/xml_formatting.js @@ -16,6 +16,7 @@ /* global define */ (function(factory) { var root; + /* istanbul ignore next */ if (typeof window !== 'undefined') { root = window; } else if (typeof self !== 'undefined') { @@ -25,6 +26,7 @@ } else { throw new Error('Unknow context'); } + /* istanbul ignore next */ if (typeof define === 'function' && define.amd) { // AMD. Register as an anonymous module. // istanbul ignore next @@ -59,6 +61,7 @@ factory(root.jQuery); } })(function($) { + /* istanbul ignore next */ if (!$.terminal) { throw new Error('$.terminal is not defined'); } @@ -87,24 +90,12 @@ var formatting = ['@', '', '', cls, src, JSON.stringify(attrs)]; return '[[' + formatting.join(';') + ']' + alt + ']'; }, - bold: function() { - return '[[b;rgba(255,255,255,0.9);]'; - }, - overline: function() { - return '[[o;;]'; - }, - strike: function() { - return '[[s;;]'; - }, - underline: function() { - return '[[u;;]'; - }, - glow: function() { - return '[[g;;]'; - }, - italic: function() { - return '[[i;;]'; - }, + bold: style('b'), + overline: style('o'), + strike: style('s'), + underline: style('u'), + glow: style('g'), + italic: style('i'), span: function(attrs) { var cls = attrs.class || ''; var formatting = ['', '', '', cls, '', JSON.stringify(attrs)]; @@ -117,11 +108,18 @@ return '[[' + formatting.join(';') + ']'; } }; + function style(value) { + return function(attrs) { + var cls = attrs.class || ''; + var formatting = [value, '', '', cls, '', JSON.stringify(attrs)]; + return '[[' + formatting.join(';') + ']'; + }; + } // short aliases tags.b = tags.bold; tags.a = tags.link; tags.i = tags.italic; - var tag_re = /(<\/?\s*[a-zA-Z]+(?: [^>]+)?>)/; + var tag_re = /(<\/?\s*[a-zA-Z]+(?:\s?[^>]+)?>)/; function xml_formatter(string) { return string.split(tag_re).map(function(string) { if (string.match(tag_re)) { @@ -130,6 +128,10 @@ } string = string.replace(/^<|>$/g, ''); var m = string.match(/^([a-zA-Z]+)(?:\s*(.+))?/); + if (!m) { + // invalid XML + return string; + } var name = m[1].toLowerCase(); var attrs = {}; if (m[2]) {