Skip to content

Commit

Permalink
Merge branch 'release-1.19.2'
Browse files Browse the repository at this point in the history
  • Loading branch information
jsconan committed Jun 17, 2022
2 parents 8b0c287 + a20171d commit f6c07bf
Show file tree
Hide file tree
Showing 4 changed files with 195 additions and 71 deletions.
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@oat-sa/tao-core-sdk",
"version": "1.19.1",
"version": "1.19.2",
"displayName": "TAO Core SDK",
"description": "Core libraries of TAO",
"homepage": "https://github.com/oat-sa/tao-core-sdk-fe#readme",
Expand Down
114 changes: 90 additions & 24 deletions src/util/strLimiter.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,50 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Copyright (c) 2018-2019 Open Assessment Technologies SA
*
* Copyright (c) 2018-2022 Open Assessment Technologies SA
*/

/**
* Limit a string by the supplied limiter function.
* @param {string} text
* @param {function} limitText
* @returns {string}
*/
function limitBy(text, limitText) {
/**
* Limits the size of an HTML fragment, removing the extraneous content.
* @param {Node} fragment
*/
const limitFragment = fragment => {
[].slice.call(fragment.childNodes).forEach(node => {
switch (node.nodeType) {
case Node.ELEMENT_NODE:
if (node.childNodes.length && node.textContent.trim()) {
limitFragment(node);

if (!node.textContent.trim()) {
node.remove();
}
}
break;

case Node.TEXT_NODE:
node.textContent = limitText(node.textContent);
break;
}
});
};

if (/<.*>/g.test(text)) {
const fragment = document.createElement('div');
fragment.innerHTML = text;
limitFragment(fragment);
return fragment.innerHTML;
}

return limitText(text);
}

/**
* Limit a string by either word or character count
*
Expand All @@ -25,36 +65,62 @@

export default {
/**
* Limit a string by word count
* Limits a string by word count.
*
* @param {string} str
* @param {integer} maxWordCount
* @param {string} text
* @param {number} limit
* @returns {string}
*/
limitByWordCount: function limitByWordCount(str, maxWordCount) {
// contains alternating a word and whitespace
// to make sure the original whitespace is retained
var textArr = str.match(/(([\S]+)|([\s]+))/g);
var newText = /\s+/.test(textArr[0]) ? textArr.shift() : '';
while (maxWordCount && textArr.length) {
newText += textArr.shift(); // word
if (textArr.length) {
newText += textArr.shift(); // white space
limitByWordCount(text, limit) {
/**
* Cuts a plain text after the max number of words expressed by the variable `limit`.
* @param {string} str
* @returns {string}
*/
const limitText = str => {
// split words by space, keeping the leading spaces attached
const words = str.match(/([\s]*[\S]+)/g);
// keep the trailing spaces
const trailing = str.match(/(\s+)$/);

if (!words) {
return '';
}
maxWordCount--;
}
newText = newText.replace(/\s+$/, ''); // remove trailing space
return newText;

const count = Math.max(0, limit);
limit = Math.max(0, count - words.length);
return words.slice(0, count).join('') + ((trailing && trailing[0]) || '');
};

return limitBy(text, limitText).replace(/(\s+)$/, '');
},

/**
* Limit a string by character count
* Limit a string by character count.
*
* @param {string} str
* @param {integer} maxCharCount
* @returns {string|*}
* @param {string} text
* @param {number} limit
* @returns {string}
*/
limitByCharCount: function limitByCharCount(str, maxCharCount) {
return str.substr(0, maxCharCount);
limitByCharCount(text, limit) {
/**
* Cuts a plain text after the max number of chars expressed by the variable `limit`.
* @param {string} str
* @returns {string}
*/
const limitText = str => {
// split by char or by HTML entity
const chars = str.match(/((&.*?;)|(.))/g);

if (!chars) {
return '';
}

const count = Math.max(0, limit);
limit = Math.max(0, count - chars.length);
return chars.slice(0, count).join('');
};

return limitBy(text, limitText);
}
};
148 changes: 103 additions & 45 deletions test/util/strLimiter/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,54 +13,112 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Copyright (c) 2018 Open Assessment Technologies SA
*
*
* Copyright (c) 2018-2022 Open Assessment Technologies SA
*/
define(['util/strLimiter'], function(strLimiter) {
define(['util/strLimiter'], function (strLimiter) {
'use strict';

var txt = 'Lorem ipsum dolor sit amet'; // 5 words, 26 characters

var weirdWhiteSpace = 'Lorem ipsum dolor sit amet';

QUnit.module('API');

QUnit.test('Limit by Word Count', function(assert) {
assert.equal(
strLimiter.limitByWordCount(txt, 5),
'Lorem ipsum dolor sit amet',
'Word count, input already correct size'
);
assert.equal(strLimiter.limitByWordCount(txt, 10), 'Lorem ipsum dolor sit amet', 'Word count, input too short');
assert.equal(strLimiter.limitByWordCount(txt, 2), 'Lorem ipsum', 'Word count, input too long');
});
QUnit.module('strLimiter');

QUnit.test('Limit by Word Count, weird whitespace', function(assert) {
assert.equal(
strLimiter.limitByWordCount(weirdWhiteSpace, 5),
'Lorem ipsum dolor sit amet',
'Word count, input already correct size'
);
assert.equal(
strLimiter.limitByWordCount(weirdWhiteSpace, 10),
'Lorem ipsum dolor sit amet',
'Word count, input too short'
);
assert.equal(strLimiter.limitByWordCount(weirdWhiteSpace, 2), 'Lorem ipsum', 'Word count, input too long');
});
QUnit.cases
.init([
{
title: 'plain text',
input: 'Lorem ipsum dolor sit amet',
unlimited: 'Lorem ipsum dolor sit amet',
limited: 'Lorem ipsum'
},
{
title: 'plain text with long spaces',
input: ' Lorem ipsum dolor sit amet ',
unlimited: ' Lorem ipsum dolor sit amet',
limited: ' Lorem ipsum'
},
{
title: 'simple HTML',
input: '<p>Lorem ipsum dolor sit amet</p>',
unlimited: '<p>Lorem ipsum dolor sit amet</p>',
limited: '<p>Lorem ipsum</p>'
},
{
title: 'glued HTML',
input: '<p> Lorem </p><p> ipsum <br></p><p> dolor </p><p> sit </p><p> amet </p>',
unlimited: '<p> Lorem </p><p> ipsum <br></p><p> dolor </p><p> sit </p><p> amet </p>',
limited: '<p> Lorem </p><p> ipsum <br></p>'
}
])
.test('limitByWordCount ', (data, assert) => {
assert.equal(strLimiter.limitByWordCount(data.input, 5), data.unlimited, 'Limited by 5 words');
assert.equal(strLimiter.limitByWordCount(data.input, 10), data.unlimited, 'Limited by 10 words');
assert.equal(strLimiter.limitByWordCount(data.input, 2), data.limited, 'Limited by 2 words');
assert.equal(strLimiter.limitByWordCount(data.input, 0), '', 'Limited by 0 words');
assert.equal(strLimiter.limitByWordCount(data.input, -2), '', 'Limited by negative value');
});

QUnit.test('Limit by Character count', function(assert) {
assert.equal(
strLimiter.limitByCharCount(txt, 26),
'Lorem ipsum dolor sit amet',
'Char count, input already correct size'
);
assert.equal(
strLimiter.limitByCharCount(txt, 100),
'Lorem ipsum dolor sit amet',
'Char count, input too short'
);
assert.equal(strLimiter.limitByCharCount(txt, 11), 'Lorem ipsum', 'Char count, input too long');
});
QUnit.cases
.init([
{
title: 'plain text',
length: 26,
limit: 11,
input: 'Lorem ipsum dolor sit amet',
unlimited: 'Lorem ipsum dolor sit amet',
limited: 'Lorem ipsum'
},
{
title: 'plain text with long spaces',
length: 38,
limit: 19,
input: ' Lorem ipsum dolor sit amet ',
unlimited: ' Lorem ipsum dolor sit amet ',
limited: ' Lorem ipsum '
},
{
title: 'plain text with entities',
length: 36,
limit: 14,
input: 'Lorem &nbsp;&nbsp; ipsum &nbsp; dolor &eacute; sit &agrave; amet',
unlimited: 'Lorem &nbsp;&nbsp; ipsum &nbsp; dolor &eacute; sit &agrave; amet',
limited: 'Lorem &nbsp;&nbsp; ipsum'
},
{
title: 'simple HTML',
length: 26,
limit: 11,
input: '<p>Lorem ipsum dolor sit amet</p>',
unlimited: '<p>Lorem ipsum dolor sit amet</p>',
limited: '<p>Lorem ipsum</p>'
},
{
title: 'glued HTML',
length: 32,
limit: 14,
input: '<p> Lorem </p><p> ipsum <br></p><p> dolor </p><p> sit </p><p> amet </p>',
unlimited: '<p> Lorem </p><p> ipsum <br></p><p> dolor </p><p> sit </p><p> amet </p>',
limited: '<p> Lorem </p><p> ipsum <br></p>'
},
{
title: 'simple HTML with entities',
length: 36,
limit: 14,
input: '<p>Lorem &nbsp;&nbsp; ipsum &nbsp; dolor &nbsp; sit &nbsp; amet</p>',
unlimited: '<p>Lorem &nbsp;&nbsp; ipsum &nbsp; dolor &nbsp; sit &nbsp; amet</p>',
limited: '<p>Lorem &nbsp;&nbsp; ipsum</p>'
}
])
.test('limitByCharCount ', (data, assert) => {
assert.equal(
strLimiter.limitByCharCount(data.input, data.length),
data.unlimited,
`Limit by ${data.length} characters`
);
assert.equal(strLimiter.limitByCharCount(data.input, 100), data.unlimited, `Limit by 100 characters`);
assert.equal(
strLimiter.limitByCharCount(data.input, data.limit),
data.limited,
`Limit by ${data.limit} characters`
);
assert.equal(strLimiter.limitByCharCount(data.input, 0), '', 'Limit by 0 characters');
assert.equal(strLimiter.limitByCharCount(data.input, -2), '', 'Limit by negative value');
});
});

0 comments on commit f6c07bf

Please sign in to comment.