Node.js parse non-standard hast data to HTML? - javascript

How can we convert non-standard hast (which is parsed from a Markdown file) to HTML?
For example, this is the HTML tree data I have:
{
"_path": "/hello",
"_draft": false,
"_partial": false,
"_empty": false,
"title": "Hello!",
"description": "",
"body": {
"type": "root",
"children": [
{
"type": "element",
"tag": "h1",
"props": {
"id": "hello!"
},
"children": [
{
"type": "text",
"value": "Hello!"
}
]
}
],
"toc": {
"title": "",
"searchDepth": 2,
"depth": 2,
"links": []
}
},
"_type": "markdown",
"_id": "content:hello.md",
"_source": "content",
"_file": "hello.md",
"_extension": "md"
}
How can I parse that 'body' bit to HTML in Node.js?
I tried to use hast-util-to-html:
import { toHtml } from 'hast-util-to-html'
console.log('data.body =', toHtml(data.body))
But I got the following error:
TypeError: Cannot read properties of undefined (reading 'toLowerCase')
I think the tag key in the data should be tagName for using hast-util-to-html. tag and prop are non-standard keys I suppose, how can I standardise them?

Related

Manipulating nested objects

I have the following data structure:
{
"nodes": [
{
"frontmatter": {
"excerpt": null,
"featured": true,
"title": "A Post with Content"
},
"fields": {
"slug": "posts/a-post-of-type-page",
}
},
{
"frontmatter": {
"excerpt": null,
"featured": null,
"title": "A post of type post"
},
"fields": {
"slug": "posts/a-post-of-type-post",
}
},
{
"frontmatter": {
"excerpt": null,
"featured": null,
"title": "Another Post (or type post)"
},
"fields": {
"slug": "posts/another-post-or-type-post",
}
},
{
"frontmatter": {
"excerpt": "This is the excerpt of a post",
"featured": null,
"title": "With Content"
},
"fields": {
"slug": "posts/with-content",
}
},
]
}
I know that I can use myObject.nodes.map(x => x.frontmatter) to bring the frontmatter up a level and removing the nesting. But, I now need to change each node into the following structure within the resulting array:
{
"nodes": [
{
"excerpt": null,
"featured": true,
"title": "A Post with Content"
"slug": "posts/a-post-of-type-page",
},
...
]
}
So, I need to remove the nesting for both the frontmatter and fields.
Thanks
const d = {"nodes":[{"frontmatter":{"excerpt":null,"featured":true,"title":"A Post with Content"},"fields":{"slug":"posts/a-post-of-type-page"}},{"frontmatter":{"excerpt":null,"featured":null,"title":"A post of type post"},"fields":{"slug":"posts/a-post-of-type-post"}},{"frontmatter":{"excerpt":null,"featured":null,"title":"Another Post (or type post)"},"fields":{"slug":"posts/another-post-or-type-post"}},{"frontmatter":{"excerpt":"This is the excerpt of a post","featured":null,"title":"With Content"},"fields":{"slug":"posts/with-content"}}]};
d.nodes = d.nodes.map(({frontmatter, fields})=>({...frontmatter, ...fields}));
console.log(d);
Here is another solution:
const data = {"nodes":[{"frontmatter":{"excerpt":null,"featured":true,"title":"A Post with Content"},"fields":{"slug":"posts/a-post-of-type-page"}},{"frontmatter":{"excerpt":null,"featured":null,"title":"A post of type post"},"fields":{"slug":"posts/a-post-of-type-post"}},{"frontmatter":{"excerpt":null,"featured":null,"title":"Another Post (or type post)"},"fields":{"slug":"posts/another-post-or-type-post"}},{"frontmatter":{"excerpt":"This is the excerpt of a post","featured":null,"title":"With Content"},"fields":{"slug":"posts/with-content"}}]};
let newArr = [];
data.nodes.forEach((n)=>newArr.push(Object.assign(n.fields, n.frontmatter)));
console.log({"nodes": newArr});

Find and replace key in Javascript object

I'm accessing a JSON that comes back looking like this:
[
{
"itemType": "SelectionTitle",
"name": "1105F.MID",
"active": true,
"isFactoryDefault": false,
"factoryCode": "",
"seasons": [],
"denominations": [],
"groups": [],
"length": 0,
"_id": "5ada2217c114ca048e1db9b0",
"created_by": "5ab57289d8d00507b29a3fdd",
"selectionFile": {
"itemType": "SelectionFile",
"name": "1105F.MID",
"active": true,
"isFactoryDefault": false,
"selectionType": "Music",
"sfzFile": "",
"destination": "/data/uploads",
"encoding": "7bit",
"fieldname": "file",
"filename": "782f49a7cd72b865b4e2d286816792e7",
...
"found": true,
"flError": false,
"error_strings": [],
"_id": "5ada2217c114ca048e1db9af",
"created_by": "5ab57289d8d00507b29a3fdd",
"slug": "1105fmid",
"__v": 0,
"createdAt": "2018-04-20T17:23:35.216Z",
"updatedAt": "2018-04-20T17:23:35.788Z",
"selectionTitles": null,
"id": "5ada2217c114ca048e1db9af"
},
"slug": "1105fmid",
"createdAt": "2018-04-20T17:23:35.285Z",
"updatedAt": "2018-04-20T17:23:35.285Z",
"__v": 0,
"id": "5ada2217c114ca048e1db9b0"
}, ...
The react-select node module that I am using takes the key "label" to generate a populated dropdown.
The JSON is coming from the web so I can't control how the JSON is setup. How do I parse the JSON to find all the instances of "name" and replace that key with "label" ?
For example "name" : 1105F.MID" should be changed to "label" : "1105.MID"
Would it be inefficient to convert the entire thing to a string and use the javascript method find/replace?
Assuming your JSON array is stored in the variable data:
data.forEach(item => item.label = item.name)
This would be sufficient to duplicate the name property as the label property for each item in the array.
I have created a function replace() to deal with every object and nested objects, which will add property 'label' if 'name' property is found. Pls see if it's useful to you.
var arr = [
{
"itemType": "SelectionTitle",
"name": "1105F.MID",
"active": true,
"isFactoryDefault": false,
"factoryCode": "",
"seasons": [],
"denominations": [],
"groups": [],
"length": 0,
"_id": "5ada2217c114ca048e1db9b0",
"created_by": "5ab57289d8d00507b29a3fdd",
"selectionFile": {
"itemType": "SelectionFile",
"name": "1105F.MID"
}
},
{
"itemType": "SelectionTitle",
"name": "test",
"active": true,
"isFactoryDefault": false,
"factoryCode": "",
"seasons": [],
"denominations": [],
"groups": [],
"length": 0,
"_id": "5ada2217c114ca048e1db9b0",
"created_by": "5ab57289d8d00507b29a3fdd",
"selectionFile": {
"itemType": "SelectionFile",
"name": "testing"
}
}
]
// this method will take care of adding new property
function replace(obj, from, to) {
Object.entries(obj).forEach(([key, value]) => (
key == from && (obj[to] = obj[from])
, typeof value === "object" && replace(value, from, to)
))
}
arr.forEach(d => replace(d, 'name', 'label'))
// you can check this log for property 'label' whereever 'name' exists
console.log(arr)
Relying on the structure of server response is bad; especially when you say you have not control over it. A better way would be to always parse the server response, construct whatever necessary for the react-select component to work and pass that only.

Error in enum data type while uploading intent dialogflow

I am trying to upload my intent everything is working fine, i am writing script in V2 and everything works but for parameter webhookState data type is enum ( [here] ) and we have to enter following of the three values ( [here][1]) now when i enter any one and try to upload it shows.
" Unable to load file: SyntaxError: Unexpected token W in JSON at position 98 "
now when I pass WEBHOOK_STATE_ENABLED(or any one) in quotes code uploads successfully (because as per my knowledge it treats it as string and gets executed) and intent is created for my agent but webhook remains off and also training phrases are not there, i am certain that the parameter webhookState is not being activated when i pass in quotes(because of above mentioned reason) Same is the case with rest, like when i try to put in type of training phrases.
{
"name": "Warehouse_Management",
"displayName": "Warehouse_Management",
"webhookState": "WEBHOOK_STATE_ENABLED_FOR_SLOT_FILLING" ,
"priority": 50000,
"isFallback": false,
"mlDisabled": false,
"trainingPhrases": [
{
"name":"Try1" ,
"type": "EXAMPLE",
"parts": [
{
"text": "for",
"userDefined": true
},
{
"text": "warehouse",
"entityType": "#Properties",
"alias": "Properties",
"userDefined": true
},
{
"text": "management",
"userDefined": true
}
]
},
{
"name":"Try2" ,
"type": "EXAMPLE",
"parts": [
{
"text": "i want app for ",
"userDefined": true
},
{
"text": "warehouse",
"alias": "Properties",
"entityType": "#Properties",
"userDefined": true
}
]
}
],
"outputContexts": [
{
"name": "Yes",
"lifespanCount": 2
},
{
"name": "No",
"lifespanCount": 2
},
{
"name": "Device_Integration",
"lifespanCount": 2
}
],
"resetContexts": false,
"parameters": [
{
"name": "Properties",
"displayName": "Properties",
"value": "$parameter_name",
"entityTypeDisplayName": "#Properties",
"mandatory": false,
"isList": true
}
],
"messages": [
{
"text":"This is sample response"
}
],
"rootFollowupIntentName": "root",
"parentFollowupIntentName": "parent"
}
Please NOTE that in the attached Json i have put it in quotes so it would get successfully executed and will create intent.
In order for it to be valid JSON, the enum value should be wrapped in quotes. It's expecting the enum value as a String.

Extract information from json

So I have the following object from my controller, which has a name, a list of beans and a list of operations:
{
"name": "Charge",
"beans": [
],
"operations": [
{
"name": "getSize",
"returnType": "java.lang.Integer",
"description": "empty description",
"parameters": [
]
},
{
"name": "truncate",
"returnType": "java.lang.Void",
"description": "empty description",
"parameters": [
]
},
{
"name": "count",
"returnType": "java.lang.Integer",
"description": "empty description",
"parameters": [
{
"name": "javaCode",
"type": "java.lang.String",
"value": null
}
]
},
{
"name": "update",
"returnType": "java.lang.Integer",
"description": "empty description",
"parameters": [
{
"name": "javaSelectCode",
"type": "java.lang.String",
"value": null
},
{
"name": "javaUpdateCode",
"type": "java.lang.String",
"value": null
}
]
},
{
"name": "delete",
"returnType": "java.lang.Integer",
"description": "empty description",
"parameters": [
{
"name": "javaCode",
"type": "java.lang.String",
"value": null
}
]
},
{
"name": "dump",
"returnType": "java.lang.Void",
"description": "empty description",
"parameters": [
{
"name": "javaSelectCode",
"type": "java.lang.String",
"value": null
},
{
"name": "destinationPath",
"type": "java.lang.String",
"value": null
}
]
},
{
"name": "select",
"returnType": "java.lang.String",
"description": "empty description",
"parameters": [
{
"name": "javaCode",
"type": "java.lang.String",
"value": null
}
]
}
],
"$$hashKey": "object:620"
}
Basically I want to display all the operations from this object in a dropdown menu.
So I was thinking of having something like:
<div ng-repeat="operation in object.operations">
{{operation.name}}
</div>
Except the code above doesn't display anything on the screen, no errors in the console, nothing.
Any help would be much appreciated!
EDIT:
Javascript service:
app.controller('selectAll', ['$http', '$scope' , '$rootScope', function ($http, $scope, $rootScope) {
$scope.response;
$scope.operations;
$rootScope.$on("invokeSelectAll", function(){
$scope.invokeSelectAll();
});
$scope.invokeSelectAll = function(){
$scope.response = $http.post('/invoke/selectAll/', $rootScope.dataObj);
$scope.object = JSON.stringify($rootScope.object);
console.log(" object operation from selectAll " + $scope.object);
$scope.response.then(function(data) {
$scope.responses = data.data ? data.data : "Select Operation not supported on this bean";
});
}
}]);
Screenshot of dev console:
https://imgur.com/a/8WAAL
Use JSON.stringify() to create a JSON string from a JavaScript object.
Use JSON.parse() to parse a JSON string to a JavaScript object.
In your case, you need to use JSON.parse() because you get a JSON string from the server and want to parse it to a JavaScript object.
$scope.object = JSON.parse($rootScope.object);
you are using JSON.stringify which is used to change javascript object to string and store it as a string only.
You should Parse the data with JSON.parse(), and the data becomes a JavaScript object. and you can easily use that in ng-repeat.
Try it ,It will work fine

Iterate through nested Javascript Objects from API response

I've tried 100 different things, and spend days looking through Google and Stackoverflow, but I can't find a solution to this problem. Everything I call after the body of this API response returns undefined!
The response from Facebook SDK looks like this:
[
{
"body": "[
"data": [
{
"name": "Larry Syid Wright",
"administrator": false,
"id": "xxx"
}, {
"name": "Melissa Long Jackson",
"administrator": false,
"id": "xxx"
}, {
"name": "Charlotte Masson",
"administrator": false,
"id": "xxx"
}
],
"paging": {
"next": "url"
}
]"
},{
"body": "{
"data": [
{
"id": "xxx_xxx",
"message": "In honor of Halloween, how many of you have your own ghost stories? Who believes in ghosts and who doesn't?",
"type": "status",
"created_time": "2014-10-31T20:02:01+0000",
"updated_time": "2014-11-01T02:52:51+0000",
"likes": {
"data": [
{
"id": "xxx",
"name": "Joe HerBatman Owenby Jr."
}
],
}
"paging": {
"cursors":
{
"after": "xxx",
"before": "xxx"
}
}
}
},{
"id": "xxx_xxx",
"from": {
"id": "xxx",
"name": "Jessica Starling"
},
"message": "Watching the "Campaign" and I can't help but notice what a fantastic job they did (Will ferrell and all) with that North Carolina accent! Ya'll know we sound different than other southern states ;)",
"type": "status",
"created_time": "2014-11-01T02:36:21+0000",
"updated_time": "2014-11-01T02:36:21+0000",
"likes": {
"data": [
{
"id": "xxx",
"name": "Scott Williams"n
}
]
}
}
],
"paging": {
"previous": "xxx",
"next": "xxx"
}
}"
}
]
This response is from a batch call. If I call them separately, I can easily iterate through the responses, and get everything from them. When I call them in the batch though, I can't get past "body", and I need to use a batch call.
console.log(response[0].body); will return the object inside the body of the first part of the response, but console.log(response[0].body.data); returns undefined. I just don't get it. This should be simple but it's like there's a lock on the door and I don't have the right key.
I normally have no issue iterating through objects, so I don't need a generalized answer. I need help seeing whatever it is here that I don't see. Why does the console show undefined when I call anything after the body, and what do I need to be doing to get any of these values?
That JSON contains nested JSON. body seems to be a string. Use
var body = JSON.parse(response[0].body);
The values from the body are just strings.which are embedded as json.So firstly you would need to parse them using JSON.parse.
The code would be like
var body = JSON.parse(response[0].body);

Categories