2018-09-03 07:54:45 +00:00
|
|
|
/**
|
|
|
|
* External dependencies
|
|
|
|
*/
|
|
|
|
import moment from 'moment';
|
|
|
|
import { saveAs } from 'browser-filesaver';
|
|
|
|
|
2019-10-24 16:41:16 +00:00
|
|
|
function escapeCSVValue( value ) {
|
|
|
|
let stringValue = value.toString();
|
|
|
|
|
|
|
|
// Prevent CSV injection.
|
|
|
|
// See: http://www.contextis.com/resources/blog/comma-separated-vulnerabilities/
|
|
|
|
// See: WC_CSV_Exporter::escape_data()
|
|
|
|
if ( [ '=', '+', '-', '@' ].includes( stringValue.charAt( 0 ) ) ) {
|
2021-06-22 22:13:16 +00:00
|
|
|
stringValue = '"\t' + stringValue + '"';
|
2019-10-24 16:41:16 +00:00
|
|
|
} else if ( stringValue.match( /[,"\s]/ ) ) {
|
|
|
|
stringValue = '"' + stringValue.replace( /"/g, '""' ) + '"';
|
|
|
|
}
|
|
|
|
|
|
|
|
return stringValue;
|
|
|
|
}
|
|
|
|
|
2018-09-03 07:54:45 +00:00
|
|
|
function getCSVHeaders( headers ) {
|
2019-10-24 16:41:16 +00:00
|
|
|
return Array.isArray( headers )
|
|
|
|
? headers
|
2020-02-14 02:23:21 +00:00
|
|
|
.map( ( header ) => escapeCSVValue( header.label ) )
|
|
|
|
.join( ',' )
|
2019-10-24 16:41:16 +00:00
|
|
|
: [];
|
2018-09-03 07:54:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function getCSVRows( rows ) {
|
|
|
|
return Array.isArray( rows )
|
2018-10-11 08:30:51 +00:00
|
|
|
? rows
|
2020-02-14 02:23:21 +00:00
|
|
|
.map( ( row ) =>
|
|
|
|
row
|
|
|
|
.map( ( rowItem ) => {
|
|
|
|
if (
|
|
|
|
undefined === rowItem.value ||
|
|
|
|
rowItem.value === null
|
|
|
|
) {
|
|
|
|
return '';
|
|
|
|
}
|
2019-10-24 16:41:16 +00:00
|
|
|
|
2020-02-14 02:23:21 +00:00
|
|
|
return escapeCSVValue( rowItem.value );
|
|
|
|
} )
|
|
|
|
.join( ',' )
|
2018-10-11 08:30:51 +00:00
|
|
|
)
|
|
|
|
.join( '\n' )
|
2018-09-03 07:54:45 +00:00
|
|
|
: [];
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Generates a CSV string from table contents
|
|
|
|
*
|
2022-03-18 11:45:14 +00:00
|
|
|
* @param {Array.<Object>} headers Object with table header information
|
|
|
|
* @param {Array.Array.<Object>} rows Object with table rows information
|
2020-02-14 02:23:21 +00:00
|
|
|
* @return {string} Table contents in a CSV format
|
2018-09-03 07:54:45 +00:00
|
|
|
*/
|
|
|
|
export function generateCSVDataFromTable( headers, rows ) {
|
|
|
|
return [ getCSVHeaders( headers ), getCSVRows( rows ) ]
|
2020-02-14 02:23:21 +00:00
|
|
|
.filter( ( text ) => text.length )
|
2018-09-03 07:54:45 +00:00
|
|
|
.join( '\n' );
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Generates a file name for CSV files based on the provided name, the current date
|
|
|
|
* and the provided params, which are all appended with hyphens.
|
|
|
|
*
|
2022-03-18 11:45:14 +00:00
|
|
|
* @param {string} [name=''] Name of the file
|
|
|
|
* @param {Object} [params={}] Object of key-values to append to the file name
|
2020-02-14 02:23:21 +00:00
|
|
|
* @return {string} Formatted file name
|
2018-09-03 07:54:45 +00:00
|
|
|
*/
|
|
|
|
export function generateCSVFileName( name = '', params = {} ) {
|
|
|
|
const fileNameSections = [
|
2019-03-06 05:16:38 +00:00
|
|
|
name.toLowerCase().replace( /[^a-z0-9]/g, '-' ),
|
2018-09-03 07:54:45 +00:00
|
|
|
moment().format( 'YYYY-MM-DD' ),
|
|
|
|
Object.keys( params )
|
2020-02-14 02:23:21 +00:00
|
|
|
.map(
|
|
|
|
( key ) =>
|
|
|
|
key.toLowerCase().replace( /[^a-z0-9]/g, '-' ) +
|
|
|
|
'-' +
|
|
|
|
decodeURIComponent( params[ key ] )
|
|
|
|
.toLowerCase()
|
|
|
|
.replace( /[^a-z0-9]/g, '-' )
|
|
|
|
)
|
|
|
|
.join( '_' ),
|
|
|
|
].filter( ( text ) => text.length );
|
2018-09-03 07:54:45 +00:00
|
|
|
|
2019-03-06 05:16:38 +00:00
|
|
|
return fileNameSections.join( '_' ) + '.csv';
|
2018-09-03 07:54:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Downloads a CSV file with the given file name and contents
|
|
|
|
*
|
2022-03-18 11:45:14 +00:00
|
|
|
* @param {string} fileName Name of the file to download
|
|
|
|
* @param {string} content Contents of the file to download
|
2018-09-03 07:54:45 +00:00
|
|
|
*/
|
|
|
|
export function downloadCSVFile( fileName, content ) {
|
2020-02-14 02:23:21 +00:00
|
|
|
// eslint-disable-next-line no-undef
|
2018-09-03 07:54:45 +00:00
|
|
|
const blob = new Blob( [ content ], { type: 'text/csv;charset=utf-8' } );
|
|
|
|
|
|
|
|
saveAs( blob, fileName );
|
|
|
|
}
|