Skip to content

Commit

Permalink
Merge branch 'release-30.5.8'
Browse files Browse the repository at this point in the history
  • Loading branch information
github-actions committed Feb 8, 2024
2 parents 7fc1a0f + 2896e42 commit 29cf14b
Show file tree
Hide file tree
Showing 7 changed files with 229 additions and 65 deletions.
2 changes: 1 addition & 1 deletion views/js/loader/taoQtiItem.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion views/js/loader/taoQtiItem.min.js.map

Large diffs are not rendered by default.

83 changes: 83 additions & 0 deletions views/js/qtiCreator/widgets/helpers/comments.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/**
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; under version 2
* of the License (non-upgradable).
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* 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) 2023 (original work) Open Assessment Technologies SA;
*/
define(function () {
'use strict';

const autogeneratedCodeStartCommentText = ' autogenerated code, do not edit ';
const autogeneratedCodeEndCommentText = ' end of autogenerated code ';
const autogeneratedCodeStartComment = `<!--${autogeneratedCodeStartCommentText}-->`;
const autogeneratedCodeEndComment = `<!--${autogeneratedCodeEndCommentText}-->`;

const isCommentNode = (node, text) =>
node &&
node.nodeType === Node.COMMENT_NODE &&
node.textContent &&
decodeURIComponent(node.textContent).includes(text);

const findAutogeneratedCodeCommentSibling = (el, siblingDirection) => {
let commentNode = null;
const siblingNode = el[siblingDirection];
const commentsByDirection = {
previousSibling: autogeneratedCodeStartCommentText,
nextSibling: autogeneratedCodeEndCommentText
};

if (!siblingNode) {
return null;
}

if (siblingNode.textContent && siblingNode.textContent.trim().length === 0) {
commentNode = findAutogeneratedCodeCommentSibling(siblingNode, siblingDirection);
} else {
//ckeditor wraps comments and URIEncodes it
//so that is the reason to use decodeURIComponent
if (isCommentNode(siblingNode, commentsByDirection[siblingDirection])) {
commentNode = siblingNode;
}
}
return commentNode;
};

const isWrapped = $el =>
findAutogeneratedCodeCommentSibling($el[0], 'previousSibling') &&
findAutogeneratedCodeCommentSibling($el[0], 'nextSibling');

return {
wrapWithAutogeneratedComment: $el => {
if (!isWrapped($el)) {
$el.before(autogeneratedCodeStartComment);
$el.after(autogeneratedCodeEndComment);
}
},

removeAutogeneratedComments: text => {
return text.replaceAll(autogeneratedCodeStartComment, '').replaceAll(autogeneratedCodeEndComment, '');
},

removeAutogeneratedCommentNodes: el => {
const prevCommentNode = findAutogeneratedCodeCommentSibling(el, 'previousSibling');
const nextCommentNode = findAutogeneratedCodeCommentSibling(el, 'nextSibling');
if (prevCommentNode) {
prevCommentNode.remove();
}
if (nextCommentNode) {
nextCommentNode.remove();
}
}
};
});
7 changes: 5 additions & 2 deletions views/js/qtiCreator/widgets/states/Deleting.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ define([
'taoQtiItem/qtiCreator/widgets/states/factory',
'taoQtiItem/qtiCreator/widgets/helpers/deletingState',
'taoQtiItem/qtiCreator/helper/gridUnits',
'taoQtiItem/qtiCreator/widgets/helpers/comments',
'taoQtiItem/qtiCreator/editor/gridEditor/helper',
'taoQtiItem/qtiCreator/editor/gridEditor/content'
], function (_, $, stateFactory, deletingHelper, gridUnits, gridHelper, contentHelper) {
], function (_, $, stateFactory, deletingHelper, gridUnits, comments, gridHelper, contentHelper) {
const DeletingState = stateFactory.create(
'deleting',
function init() {
Expand Down Expand Up @@ -145,7 +146,7 @@ define([
cols = gridUnits.redistribute(cols);

_.forEach(cols, function (col) {
let oldClass = col.elt.context.classList.value
let oldClass = col.elt.context.classList.value;
col.elt.removeClass(oldClass.match(/col-([\d]+)/).input).addClass(`col-${col.refactoredUnits}`);
gridHelper.setUnitsFromClass(col.elt);
});
Expand Down Expand Up @@ -215,6 +216,8 @@ define([
}
});
}
//remove autogenerated comments
comments.removeAutogeneratedCommentNodes(this.$elementToRemove[0]);

this.$elementToRemove.remove(); //remove html from the dom
this.widget.destroy(); //remove what remains of the widget (almost nothing), call this after element remove
Expand Down
70 changes: 70 additions & 0 deletions views/js/qtiCreator/widgets/static/helpers/comments.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/**
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; under version 2
* of the License (non-upgradable).
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* 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) 2023 (original work) Open Assessment Technologies SA;
*/
define(function () {
'use strict';

const autogeneratedCodeStartCommentText = ' autogenerated code, do not edit ';
const autogeneratedCodeEndCommentText = ' end of autogenerated code ';
const autogeneratedCodeStartComment = `<!--${autogeneratedCodeStartCommentText}-->`;
const autogeneratedCodeEndComment = `<!--${autogeneratedCodeEndCommentText}-->`;

const isCommentNode = (node, text) =>
node &&
node.nodeType === Node.COMMENT_NODE &&
node.textContent &&
decodeURIComponent(node.textContent).includes(text);

const hasAutogeneratedCodeCommentSibling = (el, siblingDirection) => {
let commentFound = false;
const siblingNode = el[siblingDirection];
const commentsByDirection = {
previousSibling: autogeneratedCodeStartCommentText,
nextSibling: autogeneratedCodeEndCommentText
};

if (!siblingNode) {
return false;
}

if (siblingNode.textContent && siblingNode.textContent.trim().length === 0) {
commentFound = hasAutogeneratedCodeCommentSibling(siblingNode, siblingDirection);
} else {
//ckeditor wraps comments and URIEncodes it
//so that is the reason to use decodeURIComponent
commentFound = isCommentNode(siblingNode, commentsByDirection[siblingDirection]);
}
return commentFound;
};

const isWrapped = $el =>
hasAutogeneratedCodeCommentSibling($el[0], 'previousSibling') &&
hasAutogeneratedCodeCommentSibling($el[0], 'nextSibling');

return {
wrapWithAutogeneratedComment: $el => {
if (!isWrapped($el)) {
$el.before(autogeneratedCodeStartComment);
$el.after(autogeneratedCodeEndComment);
}
},

removeAutogeneratedComments: text => {
return text.replaceAll(autogeneratedCodeStartComment, '').replaceAll(autogeneratedCodeEndComment, '');
}
};
});
52 changes: 25 additions & 27 deletions views/js/qtiCreator/widgets/static/helpers/widget.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,60 +15,58 @@
*
* Copyright (c) 2014-2017 (original work) Open Assessment Technologies SA;
*/
define([
'jquery',
'lodash'
], function($, _) {
define(['taoQtiItem/qtiCreator/widgets/helpers/comments', 'jquery', 'lodash'], function (comments, $, _) {
'use strict';

var helper = {
buildInlineContainer : function(widget){
buildInlineContainer: function (widget) {
var $wrap,
textNode,
float = '';

if(widget.element.hasClass('lft')){
if (widget.element.hasClass('lft')) {
float = ' lft';
}else if(widget.element.hasClass('rgt')){
} else if (widget.element.hasClass('rgt')) {
float = ' rgt';
}

$wrap = $('<span>', {
'data-serial' : widget.element.serial,
'class' : 'widget-box widget-inline widget-'+widget.element.qtiClass+float,
'data-qti-class' : widget.element.qtiClass,
'contenteditable' : 'false'
'data-serial': widget.element.serial,
class: 'widget-box widget-inline widget-' + widget.element.qtiClass + float,
'data-qti-class': widget.element.qtiClass,
contenteditable: 'false'
});
widget.$container = widget.$original.wrap($wrap).parent();
comments.wrapWithAutogeneratedComment(widget.$container);
},
buildBlockContainer : function(widget){

buildBlockContainer: function (widget) {
//absolutely need a div here (not span), otherwise mathjax will break
var $wrap = $('<div>', {
'data-serial' : widget.element.serial,
'class' : 'widget-box widget-block widget-'+widget.element.qtiClass,
'data-qti-class' : widget.element.qtiClass
'data-serial': widget.element.serial,
class: 'widget-box widget-block widget-' + widget.element.qtiClass,
'data-qti-class': widget.element.qtiClass
});
widget.$container = widget.$original.wrap($wrap).parent();
comments.wrapWithAutogeneratedComment(widget.$container);
},
createToolbar : function(widget, toolbarTpl){
createToolbar: function (widget, toolbarTpl) {
var $tlb;

if(_.isFunction(toolbarTpl)){

$tlb = $(toolbarTpl({
serial : widget.serial,
state : 'active'
}));
if (_.isFunction(toolbarTpl)) {
$tlb = $(
toolbarTpl({
serial: widget.serial,
state: 'active'
})
);

widget.$container.append($tlb);

$tlb.find('[data-role="delete"]').on('click.widget-box', function(e){
e.stopPropagation();//to prevent direct deleting;
$tlb.find('[data-role="delete"]').on('click.widget-box', function (e) {
e.stopPropagation(); //to prevent direct deleting;
widget.changeState('deleting');
});

}else{
} else {
throw new Error('the toolbarTpl must be a handlebars function');
}
}
Expand Down
78 changes: 44 additions & 34 deletions views/js/qtiXmlRenderer/renderers/Container.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,11 @@
* Copyright (c) 2014-2022 (original work) Open Assessment Technologies SA
*/

define(['module', 'tpl!taoQtiItem/qtiXmlRenderer/tpl/container'], function(module, tpl){

define([
'module',
'taoQtiItem/qtiCreator/widgets/helpers/comments',
'tpl!taoQtiItem/qtiXmlRenderer/tpl/container'
], function (module, comments, tpl) {
const config = module.config();
/**
* Elements that need to be prefixed
Expand All @@ -28,35 +31,47 @@ define(['module', 'tpl!taoQtiItem/qtiXmlRenderer/tpl/container'], function(modul
const prefixed = 'article|aside|bdi|figure|footer|header|nav|rb|rp|rt|rtc|ruby|section';
const defaultNsName = 'qh5';
const defaultNsUri = 'http://www.imsglobal.org/xsd/imsqtiv2p2_html5_v1p0';
const xhtmlEntities = function(html){

const condenseImgTags = htmlString => {
//<img...></img> are replaced by <img... />
htmlString = htmlString.replace(/<img([^>]*)?\s?[^\/]>\s?(<\/img>)+/gi, function ($0, $1, $2) {
return $0.replace('>', ' />').replace($2, '');
});
//<img...> are replaced by <img... />
htmlString = htmlString.replace(/(<img([^>]*)?\s?[^\/]>)+/gi, function ($0) {
return $0.replace('>', ' />');
});
return htmlString;
};
const handleRtTags = htmlString => {
//<rt></rt> are replaced by <rt>&nbsp;</rt>
htmlString = htmlString.replace(/(<rt(|\s+[^>]*)><\/rt\s*>)+/gi, function ($0) {
return $0.replace('</rt', '&nbsp;</rt');
});
return htmlString;
};
const addClosingSlash = htmlString => {
//<br...> are replaced by <br... />
//<hr...> are replaced by <hr... />
htmlString = htmlString.replace(/<br([^>]*)?>/gi, '<br />');
htmlString = htmlString.replace(/<hr([^>]*)?>/gi, '<hr />');
return htmlString;
};

const xhtmlEntities = function (html) {
//@todo : check other names entities
return html.replace(/&nbsp;/g, '&#160;');
};
const xhtmlEncode = function(encodedStr){

const xhtmlEncode = function (encodedStr) {
let returnValue = '';

if(encodedStr){
//<br...> are replaced by <br... />
if (encodedStr) {
returnValue = encodedStr;
returnValue = returnValue.replace(/<br([^>]*)?>/ig, '<br />');
returnValue = returnValue.replace(/<hr([^>]*)?>/ig, '<hr />');
returnValue = addClosingSlash(returnValue);
returnValue = condenseImgTags(returnValue);
returnValue = handleRtTags(returnValue);
returnValue = comments.removeAutogeneratedComments(returnValue);

//<img...></img> are replaced by <img... />
returnValue = returnValue.replace(/<img([^>]*)?\s?[^\/]>\s?(<\/img>)+/ig,
function($0, $1, $2) {
return $0.replace('>', ' />').replace($2, '');
});
//<img...> are replaced by <img... />
returnValue = returnValue.replace(/(<img([^>]*)?\s?[^\/]>)+/ig,
function($0){
return $0.replace('>', ' />');
});
//<rt></rt> are replaced by <rt>&nbsp;</rt>
returnValue = returnValue.replace(/(<rt(|\s+[^>]*)><\/rt\s*>)+/ig,
function($0){
return $0.replace('</rt', '&nbsp;</rt');
});
if (!config.skipReplaceNonBreakingSpaceCharacters) {
returnValue = replaceNonBreakingSpaceCharacters(returnValue);
}
Expand All @@ -67,9 +82,9 @@ define(['module', 'tpl!taoQtiItem/qtiXmlRenderer/tpl/container'], function(modul
};

return {
qtiClass : '_container',
template : tpl,
getData:function(container, data){
qtiClass: '_container',
template: tpl,
getData: function (container, data) {
data.body = xhtmlEntities(data.body);
data.body = xhtmlEncode(data.body);
const openRegEx = new RegExp(`(<(${prefixed}))`, 'gi');
Expand Down Expand Up @@ -107,13 +122,8 @@ define(['module', 'tpl!taoQtiItem/qtiXmlRenderer/tpl/container'], function(modul
if (typeof html !== 'string' || html.length <= 0) {
return html;
}
const tagsToMerge = [
'strong',
'em',
'sub',
'sup'
];
tagsToMerge.forEach(function(tag) {
const tagsToMerge = ['strong', 'em', 'sub', 'sup'];
tagsToMerge.forEach(function (tag) {
let matchedTags = new RegExp(`<\\/${tag}>([\\s\\u00A0]*)<${tag}>`, 'gi');
html = html.replace(matchedTags, ' ');
});
Expand Down

0 comments on commit 29cf14b

Please sign in to comment.