Из рекомендаций :
Кодированные строки
Чтобы приложения не использовали строки потенциально небезопасными способами, все строки, предоставляемые API-интерфейсами Spotify, кодируются так, чтобы случайное неправильное использование не приводило к уязвимостям внедрения. Если приложение не декодирует эти строки, используя два метода, описанных ниже, строки будут отображаться как мусор для пользователя. Единственное исключение - URI, которые никогда не кодируются и, следовательно, не требуют декодирования. В документации API указано для каждого метода, какие строки должны быть декодированы или нет.
В строки JavaScript были добавлены два метода: decodeForText () и decodeForHTML () . Если строка предназначена для безопасного использования, например, для установки innerText или создания текстового узла с помощью document.createTextNode (), следует использовать decodeForText (). Он вернет необработанную неэкранированную строку, поэтому убедитесь, что она никогда не вставляется ни в какой контекст, где будет интерпретироваться как HTML. Если строка предназначена для перехода во innerHTML или в любой фрагмент кода, который будет интерпретироваться как HTML, необходимо использовать decodeForHTML (). Это гарантирует, что <и> закодированы как <и> и т. Д. Например:
getElementById('song-title').innerHTML = track.title.decodeForHTML();
getElementById('song-title').innerText = track.title.decodeForText();
getElementById('song-title').appendChild(document.createTextNode(track.title.decodeForText()));
Приложения, которые не используют эти методы, а) не смогут отображать метаданные или любые другие данные из API Spotify, и б) будут отклонены в процессе загрузки. Также убедитесь, что вы правильно избегаете небезопасных строк HTML, откуда бы они ни исходили, например, с ваших внутренних серверов.
И исходный код, если вам интересно:
String.prototype.decodeForText = function() {
var result = "";
for (var i = 0; i < this.length; ++i) {
if (this.charAt(i) !== "&") {
result += this.charAt(i);
continue;
} else if (this.substring(i, i + 5) === "&") {
result += "&";
i += 4;
continue;
} else if (this.substring(i, i + 4) === "<") {
result += "<";
i += 3;
continue;
} else if (this.substring(i, i + 4) === ">") {
result += ">";
i += 3;
continue;
} else if (this.substring(i, i + 6) === """) {
result += "\"";
i += 5;
continue;
} else if (this.substring(i, i + 6) === "'") {
result += "'";
i += 5;
continue;
} else if (this.substring(i, i + 8) === "=") {
result += "=";
i += 7;
continue;
}
}
return result;
};
String.prototype.decodeForHTML = function() {
return this;
};
String.prototype.decodeForLink = function() {
return encodeURI(this.decodeForText());
}
String.prototype.encodeToHTML = function() {
var result = "";
for (var i = 0; i < this.length; ++i) {
if (this.charAt(i) === "&") {
result += "&";
} else if (this.charAt(i) === "<") {
result += "<";
} else if (this.charAt(i) === ">") {
result += ">";
} else if (this.charAt(i) === "\"") {
result += """;
} else if (this.charAt(i) === "'") {
result += "'";
} else if (this.charAt(i) === "=") {
result += "=";
} else {
result += this.charAt(i);
}
}
return result;
}
}(this));