Creating a nested object from parsed bb code - javascript

I am trying to create an object in javascript from a given string which includes some bbcode.
var bbStr = 'Text with [url=http://somelink]links and [i]nested bb code[/i][/url].';
I need to recursively iterate through the object and transform the above string into something like this:
var result = {
children : [
{
text : 'Text with ',
type : 'text'
},
{
children: [
{
text : 'links and ',
type : 'text'
},
{
text : 'nested bb code',
type : 'italic'
}
],
text : null,
type : 'url',
url : 'http://somelink'
},
{
text : '.',
type : 'text'
}
],
type : null,
text : null
};
Then I would send the object to a rendering function which would recursively create canvas text from it. But I just can't get my head around, how to form this object.

Try this simple stack-based parser:
token = /(?:\[(\w+)(.*?)\])|(?:\[\/(\w+)\])|([^\[\]]+)/g
root = {children:[]}
stack = [root]
bbStr.replace(token, function() {
var a = arguments;
if(a[1]) {
var node = {tag: a[1], attr: a[2], children:[]}
stack[0].children.push(node);
stack.unshift(node);
} else if(a[3]) {
if(stack[0].tag != a[3])
throw "Unmatched tag";
stack.shift();
} else if(a[4]) {
stack[0].children.push({tag: "#text", value: a[4]});
}
})
The output format differs from what you've posted, but that should be no problem.
http://jsfiddle.net/L8UZf/

Related

Javascript to fetch json from unordered data

I have below input code inside script code which comes like a string
The output should be below as a JSON object and extract flags and preference object. Need a solution using regex or any other way
flags = { "onFlag" : true, "offFlag : false }
Preference = { "onPreference" : true, "offPreference : false }
You can use regex to extract data inside the script tag and then parse content in javascript to generate JSON.
const regex = /<script[^>]+>(.*?)<\/script>/gs;
const str = `<script type="text/javascript">
window.__getRoute__=function() {
console.log('hi');
}
window.__LOADED_STATE__ = {
"context": {
"flags": {"onFlag": true, "offFlag": false},
"Preference": {"onPreference": true, "offPreference": false}
}
}
</script>`;
const m = regex.exec(str);
const json = new Function('var window={}; ' + m[1] + ' return window.__LOADED_STATE__')();
console.log(json.context.flags);
console.log(json.context.Preference);

FormData append deep nested object

Is it possible to append nested object to FormData?
let formData = new FormData();
let data = {
title: 'title',
text: 'text',
preview: {
p_title:'p title',
p_text: 'p text',
files: [
{file: File},
{file: File}
]
}
};
I tried this but this didn't help me:
for ( let dataKey in data ) {
if (dataKey === 'profile_applicant') {
for (let previewKey in data[dataKey]) {
formData.append(`${previewKey}`, data[dataKey][previewKey]);
}
} else {
formData.append(dataKey, data[dataKey]);
}
}
Server console - console.log(req.body):
first_name: test
last_name: test
date_of_birth: test
last_contact: test
files: [object Object],[object Object]
I hope I can help, I did it in a simpler way and I believe it works for all hypotheses, please test.
If it doesn't fit your use case, please comment so I can edit my answer.
Full Code:
const parses = []
const fKey = key => ((function until(value, comp = value) {
const result = value.replace(/\.([A-z0-9]*)(\.|$)/, '[$1]$2')
return comp !== result ? until(result, value) : result
})(key))
function populateFormData(values, form = new FormData(), base = '') {
Object.keys(values).forEach(key => {
const value = values[key]
if (typeof value == 'string' ||
typeof value == 'number' ||
typeof value == 'boolean' ||
value instanceof File ||
value instanceof Blob)
{
form.append(fKey(`${base}${key}`), value)
parses.push({
key: `${fKey(`${base}${key}`)}`,
value
})
}
else if (typeof value == 'object')
{
populateFormData(value, form, `${base}${key}.`)
}
})
return form;
}
populateFormData({
title: 'Lucas',
text: 'Is good :)',
preview: {
p_title: 'I am a P title',
p_text: 'I am a P text',
test: {
example: 2,
my: {
obj: [
'eba',
{
hyper: 'text'
},
123
],
yes: true
}
}
}
})
console.log(parses)
Files are particular objects, you have to append them like this:
files?.forEach(item => { formData.append('files[]', item.originFileObj) })
You should find your originFileObj in your file object, often sending all file can be a problem; It's important too to use [] on the append key, otherwise if files are multiple won't be found.

Map manipulation in Node JS

As I have 4 key/value in map , I'm trying to store two keys in string format and rest two in an array.
right now what output I'm getting :
{ url: 'account/43',
status: '200',
headers: '\'content-type\' = \'application/json\'',
body: '{ name: Fatma Zaman }' }
Expected output:
{ url: 'account/43',
status: '200',
headers: [ '\'content-type\' = \'application/json\'' ],
body: [ '{ "name": "Fatma Zaman" }' ]}
below are the code which is returning all key/value pair in string, I can make all key/value pair in array but not sure how to do only two key's value to array.
function processFile(content) {
lodash.forEach(content, function(node) {
if (node.startsWith("//")) {
key = node.substring(2, node.length - 2).toLowerCase().trim()
return
} else {
value = node
}
map[key] = value
})
console.log(lodash.map(map, "key"))
return map
}
You can add a simple condition based on key name and put the value in array
map[key] = ['header', 'body'].includes(key) ? [value] : value;
function processFile(content) {
lodash.forEach(content, function(node) {
if (node.startsWith('//')) {
key = node
.substring(2, node.length - 2)
.toLowerCase()
.trim();
return;
} else {
value = node;
}
map[key] = ['header', 'body'].includes(key) ? [value] : value;
});
return map;
}

json - add 2 elements on the same node at once ? (or in an inexistent node)

This must be easy..but I can't find the answer...
var crit = {
'webshopId': webshopId,
'type': 'product'}
};
i need to add sku.regularPrice = { $gte : parameters.minPrice} on crit;
so...if I do
crit.sku.regularPrice = { $gte : parameters.minPrice};
I will receive a exception: TypeError: Cannot set property 'regularPrice' of undefined
it's because sku does not exists on crit.
Ok, so, let's create...
crit.sku = {};
This will bring me un unwished result...like this...
{ webshopId: 'rawDemo',
type: 'product',
sku: { regularPrice: { '$gte': '3' } } }
So, a child node has been created :( I really need : sku.regularPrice : { $gte : 3}
So, my expected result must be...
{ webshopId: 'rawDemo',
type: 'product',
sku.regularPrice: { '$gte': '3' } }
at the crit variable. A hard coded representation could be...
var crit = { webshopId: 'rawDemo',
type: 'product',
sku.regularPrice: { '$gte': '3' } }
any clue ?
If I understand your question correctly, you can't use dot notation to access the variable you want. You need:
var crit = {
'webshopId': webshopId,
'type': 'product'}
};
crit['sku.regularPrice'] = { $gte : parameters.minPrice};
Which would result in:
{
webshopId: 'rawDemo',
type: 'product',
'sku.regularPrice': { '$gte': '3' }
}

How to access data returned by group reduce in Mongo?

I have a JavaScript file as
var x = new Mongo('127.0.0.1:27017');
var db = x.getDB('user');
var r = db.runCommand({"group" : {
"ns" : "track_user", "key" : {userId : 1}, "initial" : {
count:0 }, cond: {
uri: {
$regex: 'sm'
} }, "$reduce" : function(doc, prev) {
} } } }});
while(r.hasNext()){
rs = r.next();
}
I am not able to run through results returned by group reduce.
output of group reduce run via shell is something like
{
"retval" : [
{
"userId" : 0,
"created" : "2013-08-08 11:32:15",
"uri" : "abc.com",
"uri_set" : [
"xyz.com"
]
},...
],
"count" : 14,
"keys" : 6,
"ok" : 1
}
hasNext is giving error as
Sat Nov 23 00:53:40.351 JavaScript execution failed: TypeError: Object [object Object] has no method 'hasNext' at /var/www/admin/app/controllers/newjavascript1.js:L62
The problem is that db.runCommand() does not return a cursor, so none of the cursor methods are going to work on it. You're returning a document with the results nested inside, so you're going to have to work with the data a different way.
You should be able to either use map or each, depending on what you're trying to do:
var mySet = r.retval;
mySet.forEach( function(doc) {
console.log( doc );
});
Or, whatever you need it to do.

Categories