Currently been successful at every step thus far when trying to parse JSON to deploy on apps script from a JIVE JSON response. At this point, I receive a malformed HTML error and am not quite sure how to respond. I've posted to the Jive Community, but I don't think anyone works there anymore...
Update:
Here's the code I'm using to produce this issue in apps script:
Code.gs
function doGet(request) {
return HtmlService.createTemplateFromFile('Page').evaluate().setSandboxMode(HtmlService.SandboxMode.IFRAME);
}
function include(filename) {
var finalRequest = UrlFetchApp.fetch('https://www.cloudconnect.xxx....');
var data = finalRequest.toString().replace("throw 'allowIllegalResourceCall is false.';", "").trim();
data = JSON.parse(data);
var returnData = [];
for(var i in data){
if(i == "list"){
var content = data[i];
}
for(var i in content){
var text = content[i];
var json_string = JSON.stringify(text).replace(/[&]/g, "and");
returnData.push(json_string);
}
}
return returnData;
}
Page.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<?!= include('Stylesheet'); ?>
</head>
<body>
<script>
function displayData(responseData) {
document.getElementById('output').innerHTML = responseData.join(", ");
}
google.script.run.withFailureHandler(displayData).withSuccessHandler(displayData).include();
</script>
</body>
</html>
When publishing to a web app, this is the response I get:
Exception: Malformed HTML content: {"content":{"text":"<body><!-- [DocumentBodyStart:c062b27a-e734-42fb-a146-c2d978fb77da] --><div class=\"jive-rendered-content\"></div><!-- [DocumentBodyEnd:c062b27a-e734-42fb-a146-c2d978fb77da] --></body>","editable":false,"type":"text/html"},"subject":"GCI - Partner Project Plan - Template","type":"file"},{"content":{"text":"<body><!-- [DocumentBodyStart:1248f967-2b32-42d0-a9aa-a20f40485c77] --><div class=\"jive-rendered-content\"><span>Unable to access trainingand#160;Google Cloud Sales Credential</span></div><!-- [DocumentBodyEnd:1248f967-2b32-42d0-a9aa-a20f40485c77] --></body>","editable":false,"type":"text/html"},"subject":"Unable to access training Google Cloud Sales Credential","type":"update"},{"content":{"text":"<body><!-- [DocumentBodyStart:67e6b807-8421-4e61-a3c9-a08943f8a368] --><div class=\"jive-rendered-content\"><span>I am having issues with Capital Letter Confusion ie - Example.Com and example.com.I have major account confusion as a result.Thanks for reading.</span></div><!-- [DocumentBodyEnd:67e6b807-8421-4e61-a3c9-a08943f8a368] --></body>","editable":false,"type":"text/html"},"subject":"I am having issues with Capital Letter Confusion ie - Example.Com and example.com.I have major...","type":"update"},{"content":{"text":"<body><!-- [DocumentBodyStart:0013baf2-c12e-4869-9849-0959d99bdd77] --><div class=\"jive-rendered-content\"><p>or how can I know who is the admin? if they no longer have any IT administrator and the last one they had quits two years ago with zero documentation?</p></div><!-- [DocumentBodyEnd:0013baf2-c12e-4869-9849-0959d99bdd77] --></body>","editable":false,"type":"text/html"},"subject":"Why a gsuite edu user shows that his admin is a domain instead of an name or email account?","type":"discussion"},{"content":{"text":"<body><!-- [DocumentBodyStart:907a55ec-9332-43fe-876c-00384af7be79] --><div class=\"jive-rendered-content\"><span>Startup FB Data Science University will launch in the San Francisco, CA and Cloud Tech developers as individuals or companies can be Partner of the Startup Tech University without capital.</span><a class=\"jive-link-external-small\" href=\"https://www.cloudconnect.goog/external-link.jspa?url=http%3A%2F%2Fbit.ly%2Ffbdatascienceuniversity\" rel=\"nofollow\" target=\"_blank\">xxx</a></div><!-- [DocumentBodyEnd:907a55ec-9332-43fe-876c-00384af7be79] --></body>","editable":false,"type":"text/html"},"subject":"Startup FB Data Science University will launch in the San Francisco, CA and Cloud Tech developers...","type":"update"},{"content":{"text":"<body><!-- [DocumentBodyStart:c062b27a-e734-42fb-a146-c2d978fb77da] --><div class=\"jive-rendered-content\"></div><!-- [DocumentBodyEnd:c062b27a-e734-42fb-a146-c2d978fb77da] --></body>","editable":false,"type":"text/html"},"subject":"GCI - Partner Project Plan - Template","type":"file"},{"content":{"text":"<body><!-- [DocumentBodyStart:1248f967-2b32-42d0-a9aa-a20f40485c77] --><div class=\"jive-rendered-content\"><span>Unable to access trainingand#160;Google Cloud Sales Credential</span></div><!-- [DocumentBodyEnd:1248f967-2b32-42d0-a9aa-a20f40485c77] --></body>","editable":false,"type":"text/html"},"subject":"Unable to access training Google Cloud Sales Credential","type":"update"},{"content":{"text":"<body><!-- [DocumentBodyStart:67e6b807-8421-4e61-a3c9-a08943f8a368] --><div class=\"jive-rendered-content\"><span>I am having issues with Capital Letter Confusion ie - Example.Com and example.com.I have major account confusion as a result.Thanks for reading.</span></div><!-- [DocumentBodyEnd:67e6b807-8421-4e61-a3c9-a08943f8a368] --></body>","editable":false,"type":"text/html"},"subject":"I am having issues with Capital Letter Confusion ie - Example.Com and example.com.I have major...","type":"update"},{"content":{"text":"<body><!-- [DocumentBodyStart:0013baf2-c12e-4869-9849-0959d99bdd77] --><div class=\"jive-rendered-content\"><p>or how can I know who is the admin? if they no longer have any IT administrator and the last one they had quits two years ago with zero documentation?</p></div><!-- [DocumentBodyEnd:0013baf2-c12e-4869-9849-0959d99bdd77] --></body>","editable":false,"type":"text/html"},"subject":"Why a gsuite edu user shows that his admin is a domain instead of an name or email account?","type":"discussion"},{"content":{"text":"<body><!-- [DocumentBodyStart:907a55ec-9332-43fe-876c-00384af7be79] --><div class=\"jive-rendered-content\"><span>Startup FB Data Science University will launch in the San Francisco, CA and Cloud Tech developers as individuals or companies can be Partner of the Startup Tech University without capital.</span><a class=\"jive-link-external-small\" href=\"https://www.cloudconnect.goog/external-link.jspa?url=xxx\" rel=\"nofollow\" target=\"_blank\">xxx</a></div><!-- [DocumentBodyEnd:907a55ec-9332-43fe-876c-00384af7be79] --></body>","editable":false,"type":"text/html"},"subject":"Startup FB Data Science University will launch in the San Francisco, CA and Cloud Tech developers...","type":"update"}.
at [unknown function]([unknown file]:5:22)
at [unknown function]([unknown file]:18:3)
at doGet(Code:2:53)
Has anyone seen this before? Can you point me to any documentation on how to proceed here?
Inside the Page.html
file, you are using the include()
function to insert data into your HTML template.
The issue is that that data itself (fetched from the API) includes HTML tags which collide with your pre-existing HTML code, thus causing a "Malformed HTML content" Exception.
In order to overcome this issue, you should use HTML character escaping on the data that you want to insert into your HTML template. See below a possible solution:
Code.gs
function doGet(request) {
return HtmlService.createTemplateFromFile('Page').evaluate().setSandboxMode(HtmlService.SandboxMode.IFRAME);
}
function include(filename) {
var finalRequest = UrlFetchApp.fetch('https://www.cloudconnect.xxx....');
var data = finalRequest.toString().replace("throw 'allowIllegalResourceCall is false.';", "").trim();
data = JSON.parse(data);
var returnData = [];
for(var i in data){
if(i == "list"){
var content = data[i];
}
for(var i in content){
var text = content[i];
var json_string = JSON.stringify(text).replace(/[&]/g, "and");
returnData.push(json_string);
}
}
return escapeHtml(returnData);
}
var entityMap = {
'&': '&',
'<': '<',
'>': '>',
'"': '"',
"'": ''',
'/': '/',
'`': '`',
'=': '='
};
function escapeHtml(string) {
return String(string).replace(/[&<>"'`=\/]/g, function (s) {
return entityMap[s];
});
}
escapeHtml
function which can be used to escape the HTML characters present in the string passed as parameter.entityMap
variable which is used by the escapeHtml
function to escape/translate the characters.return
statement of the include()
function. Instead of returning the string itself, now it returns the escaped version of the string.