Bug 40525: [24.05] Update spreadsheet format to escape formulas
Signed-off-by: Jesse Maseto <jesse@bywatersolutions.com>
This commit is contained in:
parent
6ad5eeefea
commit
4dee52666c
|
|
@ -1,5 +1,5 @@
|
|||
[% USE TablesSettings %]
|
||||
|
||||
[% Asset.js("js/datatables_buttons_shim.js") | $raw %]
|
||||
<script>
|
||||
function KohaTable(selector, dt_parameters, columns_settings) {
|
||||
var id = 0;
|
||||
|
|
@ -40,6 +40,8 @@ function KohaTable(selector, dt_parameters, columns_settings) {
|
|||
}
|
||||
}
|
||||
|
||||
const export_format_spreadsheet = ButtonsShim.export_format_spreadsheet;
|
||||
|
||||
// Add a "Clear filter" button to table filter form field
|
||||
dt_parameters[ "buttons" ] = [
|
||||
{
|
||||
|
|
@ -58,7 +60,7 @@ function KohaTable(selector, dt_parameters, columns_settings) {
|
|||
text: _("CSV"),
|
||||
exportOptions: {
|
||||
columns: exportColumns,
|
||||
format: export_format
|
||||
format: export_format_spreadsheet
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2,4 +2,5 @@
|
|||
[% USE Asset %]
|
||||
[% Asset.js("lib/jquery/plugins/jquery.dataTables.min.js") | $raw %]
|
||||
[% Asset.js("lib/jquery/plugins/dataTables.responsive.min.js") | $raw %]
|
||||
[% Asset.js("js/datatables_buttons_shim.js") | $raw %]
|
||||
[% Asset.js("js/datatables.js") | $raw %]
|
||||
|
|
|
|||
|
|
@ -1210,6 +1210,8 @@
|
|||
);
|
||||
});
|
||||
|
||||
const export_format_spreadsheet = ButtonsShim.export_format_spreadsheet;
|
||||
|
||||
var dTables = $("#checkoutst,#holdst,#overduest,#opac-user-relative-issues-table");
|
||||
dTables.each(function(){
|
||||
var thIndex = $(this).find("th.psort").index();
|
||||
|
|
@ -1250,7 +1252,8 @@
|
|||
extend: "csv",
|
||||
exportOptions: {
|
||||
/* CSV export should include all columns (even invisible ones) unless they are .noExport */
|
||||
columns: ":not(.noExport)"
|
||||
columns: ":not(.noExport)",
|
||||
format: export_format_spreadsheet
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
|
|||
|
|
@ -240,6 +240,8 @@ $.fn.dataTable.ext.buttons.clearFilter = {
|
|||
}
|
||||
};
|
||||
|
||||
const export_format_spreadsheet = ButtonsShim.export_format_spreadsheet;
|
||||
|
||||
var export_buttons = [
|
||||
{
|
||||
extend: 'excelHtml5',
|
||||
|
|
@ -252,7 +254,7 @@ $.fn.dataTable.ext.buttons.clearFilter = {
|
|||
extend: 'csvHtml5',
|
||||
exportOptions: {
|
||||
columns: exportColumns,
|
||||
format: export_format
|
||||
format: export_format_spreadsheet
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,112 @@
|
|||
window.ButtonsShim = {};
|
||||
|
||||
ButtonsShim.export_format_spreadsheet = {
|
||||
body: function (data, row, column, node) {
|
||||
const newnode = node.cloneNode(true);
|
||||
const no_export_nodes = newnode.querySelectorAll(".no-export");
|
||||
no_export_nodes.forEach(child => {
|
||||
child.parentNode.removeChild(child);
|
||||
});
|
||||
//Note: innerHTML is the same thing as the data variable,
|
||||
//minus the ".no-export" nodes that we've removed
|
||||
//Note: See dataTables.buttons.js for original function usage
|
||||
const str = ButtonsShim.stripData(newnode.innerHTML, {
|
||||
decodeEntities: false,
|
||||
stripHtml: true,
|
||||
stripNewlines: true,
|
||||
trim: true,
|
||||
escapeExcelFormula: true
|
||||
});
|
||||
return str;
|
||||
},
|
||||
};
|
||||
|
||||
ButtonsShim._stripHtml = function (input) {
|
||||
var _max_str_len = Math.pow(2, 28);
|
||||
var _re_html = /<([^>]*>)/g;
|
||||
if (! input || typeof input !== 'string') {
|
||||
return input;
|
||||
}
|
||||
// Irrelevant check to workaround CodeQL's false positive on the regex
|
||||
if (input.length > _max_str_len) {
|
||||
throw new Error('Exceeded max str len');
|
||||
}
|
||||
var previous;
|
||||
input = input.replace(_re_html, ''); // Complete tags
|
||||
// Safety for incomplete script tag - use do / while to ensure that
|
||||
// we get all instances
|
||||
do {
|
||||
previous = input;
|
||||
input = input.replace(/<script/i, '');
|
||||
} while (input !== previous);
|
||||
return previous;
|
||||
};
|
||||
|
||||
ButtonsShim.stripHtml = function (mixed) {
|
||||
var type = typeof mixed;
|
||||
|
||||
if (type === 'function') {
|
||||
ButtonsShim._stripHtml = mixed;
|
||||
return;
|
||||
}
|
||||
else if (type === 'string') {
|
||||
return ButtonsShim._stripHtml(mixed);
|
||||
}
|
||||
return mixed;
|
||||
};
|
||||
ButtonsShim.stripHtmlScript = function (input) {
|
||||
var previous;
|
||||
do {
|
||||
previous = input;
|
||||
input = input.replace(/<script\b[^<]*(?:(?!<\/script[^>]*>)<[^<]*)*<\/script[^>]*>/gi, '');
|
||||
} while (input !== previous);
|
||||
return input;
|
||||
};
|
||||
ButtonsShim.stripHtmlComments = function (input) {
|
||||
var previous;
|
||||
do {
|
||||
previous = input;
|
||||
input = input.replace(/(<!--.*?--!?>)|(<!--[\S\s]+?--!?>)|(<!--[\S\s]*?$)/g, '');
|
||||
} while (input !== previous);
|
||||
return input;
|
||||
};
|
||||
ButtonsShim.stripData = function (str, config) {
|
||||
// If the input is an HTML element, we can use the HTML from it (HTML might be stripped below).
|
||||
if (str !== null && typeof str === 'object' && str.nodeName && str.nodeType) {
|
||||
str = str.innerHTML;
|
||||
}
|
||||
|
||||
if (typeof str !== 'string') {
|
||||
return str;
|
||||
}
|
||||
|
||||
// Always remove script tags
|
||||
//str = Buttons.stripHtmlScript(str);
|
||||
str = ButtonsShim.stripHtmlScript(str);
|
||||
|
||||
// Always remove comments
|
||||
//str = Buttons.stripHtmlComments(str);
|
||||
str = ButtonsShim.stripHtmlComments(str);
|
||||
|
||||
if (!config || config.stripHtml) {
|
||||
//str = DataTable.util.stripHtml(str);
|
||||
str = ButtonsShim.stripHtml(str);
|
||||
}
|
||||
|
||||
if (!config || config.trim) {
|
||||
str = str.trim();
|
||||
}
|
||||
|
||||
if (!config || config.stripNewlines) {
|
||||
str = str.replace(/\n/g, ' ');
|
||||
}
|
||||
|
||||
// Prevent Excel from running a formula
|
||||
if (!config || config.escapeExcelFormula) {
|
||||
if (str.match(/^[=@\t\r]/)) {
|
||||
str = "'" + str;
|
||||
}
|
||||
}
|
||||
|
||||
return str;
|
||||
};
|
||||
Loading…
Reference in New Issue