JSFiddle - React, Tailwind, and code Playground

by Sergei Sokolov

HTML

<button id="btn-save">Сохранить файл</button>

JavaScript

/**
 * для вопроса https://toster.ru/q/418900
 */
function save() {
  var delimiter = ',';
	var EOL = "\r\n";
	var data = [
		[123,"первая строка вторая колонка в кириллице"],
		[456,"вторая строка"]
	];

	var rows = data.map( function(el){
		return [ el[0], '"' + el[1].replace(/"/g,'""') + '"']
		  .join(delimiter) + EOL
		;
	});
	rows.unshift('sep=,' + EOL);
	saveAs( new Blob( rows, {type : 'text/csv;charset=utf-8;'}), 'data.csv' );
}

document.getElementById('btn-save').addEventListener('click', save);













/*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */
var saveAs=saveAs||function(e){"use strict";if(typeof e==="undefined"||typeof navigator!=="undefined"&&/MSIE [1-9]\./.test(navigator.userAgent)){return}var t=e.document,n=function(){return e.URL||e.webkitURL||e},r=t.createElementNS("http://www.w3.org/1999/xhtml","a"),o="download"in r,a=function(e){var t=new MouseEvent("click");e.dispatchEvent(t)},i=/constructor/i.test(e.HTMLElement)||e.safari,f=/CriOS\/[\d]+/.test(navigator.userAgent),u=function(t){(e.setImmediate||e.setTimeout)(function(){throw t},0)},s="application/octet-stream",d=1e3*40,c=function(e){var t=function(){if(typeof e==="string"){n().revokeObjectURL(e)}else{e.remove()}};setTimeout(t,d)},l=function(e,t,n){t=[].concat(t);var r=t.length;while(r--){var o=e["on"+t[r]];if(typeof o==="function"){try{o.call(e,n||e)}catch(a){u(a)}}}},p=function(e){if(/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(e.type)){return new Blob([String.fromCharCode(65279),e],{type:e.type})}return e},v=function(t,u,d){if(!d){t=p(t)}var v=this,w=t.type,m=w===s,y,h=function(){l(v,"writestart progress write writeend".split(" "))},S=function(){if((f||m&&i)&&e.FileReader){var r=new FileReader;r.onloadend=function(){var t=f?r.result:r.result.replace(/^data:[^;]*;/,"data:attachment/file;");var...