@reality.eth/reality-eth-lib 3.2.3 → 3.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/formatters/question.js +118 -12
- package/package.json +3 -3
- package/test/formatters.js +95 -0
package/formatters/question.js
CHANGED
|
@@ -5,6 +5,7 @@ const BigNumber = require('bignumber.js');
|
|
|
5
5
|
const ethereumjs_abi = require('ethereumjs-abi')
|
|
6
6
|
const vsprintf = require("sprintf-js").vsprintf
|
|
7
7
|
const QUESTION_MAX_OUTCOMES = 128;
|
|
8
|
+
const TEMPLATE_MAX_PLACEHOLDERS = 128;
|
|
8
9
|
const marked = require('marked');
|
|
9
10
|
const DOMPurify = require('isomorphic-dompurify');
|
|
10
11
|
const { convert} = require('html-to-text');
|
|
@@ -277,21 +278,126 @@ exports.populatedJSONForTemplate = function(template, question, errors_to_title)
|
|
|
277
278
|
return module.exports.parseQuestionJSON(interpolated, errors_to_title);
|
|
278
279
|
}
|
|
279
280
|
|
|
281
|
+
// Encode text, assuming the template has placeholders in the order specified in the params.
|
|
282
|
+
// Additional information about the template can be passed in as template_definitions.
|
|
283
|
+
// If not specified, we'll assume it works like our standard built-in templates.
|
|
284
|
+
exports.encodeCustomText = function(params) {
|
|
285
|
+
|
|
286
|
+
var items = [];
|
|
287
|
+
for (const p in params) {
|
|
288
|
+
var val = params[p];
|
|
289
|
+
if (typeof val === 'string') {
|
|
290
|
+
// Stringify puts quotation marks around the string, so strip them
|
|
291
|
+
val = JSON.stringify(val).replace(/^"|"$/g, '');
|
|
292
|
+
} else if (typeof val === 'object') {
|
|
293
|
+
// An array of values should be stringified as a JSON array.
|
|
294
|
+
// However template should do "outcomes: [%s]" instead of "outcomes: %s".
|
|
295
|
+
// In that case strip the closing brackets.
|
|
296
|
+
val = JSON.stringify(val).replace(/^\[/, '').replace(/\]$/, '');
|
|
297
|
+
} else {
|
|
298
|
+
val = null;
|
|
299
|
+
}
|
|
300
|
+
items.push(val);
|
|
301
|
+
}
|
|
302
|
+
const ret = items.join(module.exports.delimiter());
|
|
303
|
+
return ret;
|
|
304
|
+
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
exports.guessTemplateConfig = function(template) {
|
|
308
|
+
// Use the hash of the template as a temporary placeholder
|
|
309
|
+
// Since you can't hash yourself we can be confident this won't collide.
|
|
310
|
+
const placeholder = '0x' + ethereumjs_abi.soliditySHA3(['string'], [template]).toString('hex');
|
|
311
|
+
const arr_placeholder = '0x' + ethereumjs_abi.soliditySHA3(['string'], [template + "_arr"]).toString('hex');
|
|
312
|
+
var pl_arr = new Array(TEMPLATE_MAX_PLACEHOLDERS);
|
|
313
|
+
pl_arr.fill(placeholder);
|
|
314
|
+
var interpolated = vsprintf(template, pl_arr);
|
|
315
|
+
|
|
316
|
+
// Quote the placeholders in any arrays that didn't originally have quotes
|
|
317
|
+
interpolated = interpolated.replaceAll('['+placeholder+']', '"'+arr_placeholder+'"');
|
|
318
|
+
|
|
319
|
+
const fake_json = module.exports.parseQuestionJSON(interpolated, false);
|
|
320
|
+
|
|
321
|
+
/*
|
|
322
|
+
Meta example:
|
|
323
|
+
{
|
|
324
|
+
'labels': {'dog': 'Dogs', 'cat': 'Cats'},
|
|
325
|
+
'tags': {'2': 'dog'}
|
|
326
|
+
'defaults': {'lang': 'en_US'}
|
|
327
|
+
}
|
|
328
|
+
*/
|
|
329
|
+
|
|
330
|
+
|
|
331
|
+
// If there's a section called __META, use that for titling columns etc
|
|
332
|
+
var meta = '__META' in fake_json ? fake_json['__META'] : {};
|
|
333
|
+
var labels = 'labels' in meta ? meta['labels'] : {};
|
|
334
|
+
|
|
335
|
+
var fields = {};
|
|
336
|
+
for (const k in fake_json) {
|
|
337
|
+
if (k == 'title_text' || k == 'title_html' || k == '__META') {
|
|
338
|
+
// Fields we add automatically
|
|
339
|
+
continue;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
// We assume that every placeholder is either the value for a field, or contained in it.
|
|
343
|
+
// ie we handle
|
|
344
|
+
// "myfield": "%s"
|
|
345
|
+
// "myfield": "A %s and another %s."
|
|
346
|
+
// "myfield": [%s]
|
|
347
|
+
|
|
348
|
+
var fdef = {};
|
|
349
|
+
fdef['label'] = (k in labels) ? labels[k] : k;
|
|
350
|
+
const regexp = new RegExp('('+placeholder+'|'+arr_placeholder+')');
|
|
351
|
+
//const regexp = new RegExp('('+placeholder+')');
|
|
352
|
+
const bits = fake_json[k].split(regexp);
|
|
353
|
+
// console.log(bits);
|
|
354
|
+
var parts = [];
|
|
355
|
+
var part_i = 0;
|
|
356
|
+
for(const b in bits) {
|
|
357
|
+
if (bits[b] == '') {
|
|
358
|
+
continue;
|
|
359
|
+
}
|
|
360
|
+
if (bits[b] == placeholder || bits[b] == arr_placeholder) {
|
|
361
|
+
let part_label = k + '_' + part_i;
|
|
362
|
+
if (part_label in labels) {
|
|
363
|
+
part_label = labels[part_label];
|
|
364
|
+
}
|
|
365
|
+
if (bits[b] == placeholder) {
|
|
366
|
+
parts.push({'part': 'parameter', 'part_index': part_i, 'label': part_label})
|
|
367
|
+
} else {
|
|
368
|
+
parts.push({'part': 'array_parameter', 'part_index': part_i, 'label': part_label})
|
|
369
|
+
}
|
|
370
|
+
part_i++;
|
|
371
|
+
} else {
|
|
372
|
+
parts.push({'part': 'text', 'value': bits[b]});
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
fdef['parts'] = parts;
|
|
376
|
+
fields[k] = fdef;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
var tags = {};
|
|
380
|
+
if ('tags' in meta) {
|
|
381
|
+
tags = meta['tags']
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
return {
|
|
385
|
+
'fields': fields,
|
|
386
|
+
'tags': tags
|
|
387
|
+
};
|
|
388
|
+
|
|
389
|
+
}
|
|
390
|
+
|
|
280
391
|
exports.encodeText = function(qtype, txt, outcomes, category, lang) {
|
|
281
|
-
var
|
|
282
|
-
|
|
283
|
-
//console.log('using template_id', template_id);
|
|
392
|
+
var def = {};
|
|
393
|
+
def['title'] = txt;
|
|
284
394
|
if (qtype == 'single-select' || qtype == 'multiple-select') {
|
|
285
|
-
|
|
286
|
-
//console.log('made outcome_str', outcome_str);
|
|
287
|
-
qtext = qtext + delim + outcome_str;
|
|
288
|
-
//console.log('made qtext', qtext);
|
|
289
|
-
}
|
|
290
|
-
if (typeof lang == 'undefined' || lang == '') {
|
|
291
|
-
lang = 'en_US';
|
|
395
|
+
def['outcomes'] = outcomes;
|
|
292
396
|
}
|
|
293
|
-
|
|
294
|
-
|
|
397
|
+
def['category'] = category;
|
|
398
|
+
def['lang'] = lang;
|
|
399
|
+
|
|
400
|
+
return module.exports.encodeCustomText(def);
|
|
295
401
|
}
|
|
296
402
|
|
|
297
403
|
// A value used to denote that the question is invalid or can't be answered
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@reality.eth/reality-eth-lib",
|
|
3
|
-
"version": "3.2.
|
|
3
|
+
"version": "3.2.5",
|
|
4
4
|
"description": "Tools for handling questions in the reality.eth fact verification platform",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"test": "env TZ='Asia/Kabul' mocha ./test"
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"author": "Edmund Edgar (https://reality.eth.link)",
|
|
17
17
|
"license": "GPL-3.0",
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"@reality.eth/contracts": "^3.0.
|
|
19
|
+
"@reality.eth/contracts": "^3.0.21",
|
|
20
20
|
"bignumber.js": "^7.2.1",
|
|
21
21
|
"bn.js": "^5.2.1",
|
|
22
22
|
"ethereumjs-abi": "^0.6.5",
|
|
@@ -39,5 +39,5 @@
|
|
|
39
39
|
"url": "https://github.com/RealityETH/monorepo/issues"
|
|
40
40
|
},
|
|
41
41
|
"homepage": "https://reality.eth.link",
|
|
42
|
-
"gitHead": "
|
|
42
|
+
"gitHead": "a1a1c9160d34921ac395d23614820eaa8a13b305"
|
|
43
43
|
}
|
package/test/formatters.js
CHANGED
|
@@ -385,3 +385,98 @@ describe('Question ID tests', function() {
|
|
|
385
385
|
});
|
|
386
386
|
|
|
387
387
|
});
|
|
388
|
+
|
|
389
|
+
describe('Custom template handling', function() {
|
|
390
|
+
const example_template = '{"title": "%s", "dogs": "%s", "cats": "%s"}';
|
|
391
|
+
const example_template_arr = '{"title": "%s", "dogs": "%s", "cats": [%s], "ants": [%s]}';
|
|
392
|
+
const multi_template = '{"title": "%s", "dogs": "The dogs item contains thing 1 %s and thing 2 %s.", "cats": "%s"}';
|
|
393
|
+
const example_template_meta = '{"title": "%s", "dogs": "%s", "cats": "%s", "__META": {"tags": {"1": "dogthing1"}, "labels": {"dogs": "Doggies", "cats": "Felines"}}}';
|
|
394
|
+
const multi_template_meta = '{"title": "%s", "dogs": "The dogs item contains thing 1 %s and thing 2 %s.", "cats": "%s", "__META": {"tags": {"1": "dogthing1"}, "labels": {"dogs": "Doggies", "dogs_0": "First Doggy", "dogs_1": "Second Doggy", "cats": "Felines"}}}';
|
|
395
|
+
it('Returns a template config for an otherwise unknown template', function() {
|
|
396
|
+
var q = rc_question.guessTemplateConfig(example_template);
|
|
397
|
+
const t = q['fields']['title']['label'];
|
|
398
|
+
expect(t).to.equal('title');
|
|
399
|
+
const dt = q['fields']['dogs']['label'];
|
|
400
|
+
expect(dt).to.equal('dogs');
|
|
401
|
+
const parts = q['fields']['dogs']['parts'];
|
|
402
|
+
expect(parts.length).to.equal(1);
|
|
403
|
+
expect(parts[0].part).to.equal('parameter');
|
|
404
|
+
expect(parts[0].part_index).to.equal(0);
|
|
405
|
+
expect(parts[0].label).to.equal('dogs_0');
|
|
406
|
+
|
|
407
|
+
var qm = rc_question.guessTemplateConfig(example_template_meta);
|
|
408
|
+
const tm = qm['fields']['title']['label'];
|
|
409
|
+
expect(tm).to.equal('title');
|
|
410
|
+
const dtm = qm['fields']['dogs']['label'];
|
|
411
|
+
expect(dtm).to.equal('Doggies');
|
|
412
|
+
const partsm = qm['fields']['dogs']['parts'];
|
|
413
|
+
expect(partsm.length).to.equal(1);
|
|
414
|
+
expect(partsm[0].part).to.equal('parameter');
|
|
415
|
+
expect(partsm[0].part_index).to.equal(0);
|
|
416
|
+
const tag1 = qm['tags']['1'];
|
|
417
|
+
expect(tag1).to.equal('dogthing1');
|
|
418
|
+
|
|
419
|
+
var qa = rc_question.guessTemplateConfig(example_template_arr);
|
|
420
|
+
const ta = qa['fields']['title']['label'];
|
|
421
|
+
expect(ta).to.equal('title');
|
|
422
|
+
const dta = qa['fields']['dogs']['label'];
|
|
423
|
+
expect(dta).to.equal('dogs');
|
|
424
|
+
const partsa = qa['fields']['dogs']['parts'];
|
|
425
|
+
expect(partsa.length).to.equal(1);
|
|
426
|
+
expect(partsa[0].part).to.equal('parameter');
|
|
427
|
+
expect(partsa[0].part_index).to.equal(0);
|
|
428
|
+
expect(partsa[0].label).to.equal('dogs_0');
|
|
429
|
+
|
|
430
|
+
const bparts2 = qa['fields']['cats']['parts'];
|
|
431
|
+
expect(bparts2.length).to.equal(1);
|
|
432
|
+
expect(bparts2[0].part).to.equal('array_parameter');
|
|
433
|
+
expect(bparts2[0].part_index).to.equal(0);
|
|
434
|
+
expect(bparts2[0].label).to.equal('cats_0');
|
|
435
|
+
|
|
436
|
+
const bparts3 = qa['fields']['ants']['parts'];
|
|
437
|
+
expect(bparts3.length).to.equal(1);
|
|
438
|
+
expect(bparts3[0].part).to.equal('array_parameter');
|
|
439
|
+
expect(bparts3[0].part_index).to.equal(0);
|
|
440
|
+
expect(bparts3[0].label).to.equal('ants_0');
|
|
441
|
+
|
|
442
|
+
});
|
|
443
|
+
|
|
444
|
+
it('Returns a config for placeholders inside strings in json fields', function() {
|
|
445
|
+
var q = rc_question.guessTemplateConfig(multi_template);
|
|
446
|
+
const t = q['fields']['title']['label'];
|
|
447
|
+
expect(t).to.equal('title');
|
|
448
|
+
const parts = q['fields']['dogs']['parts'];
|
|
449
|
+
expect(parts.length).to.equal(5);
|
|
450
|
+
expect(parts[0].part).to.equal('text');
|
|
451
|
+
expect(parts[0].value).to.equal('The dogs item contains thing 1 ');
|
|
452
|
+
expect(parts[1].part).to.equal('parameter');
|
|
453
|
+
expect(parts[1].part_index).to.equal(0);
|
|
454
|
+
expect(parts[1].label).to.equal("dogs_0");
|
|
455
|
+
expect(parts[2].part).to.equal('text');
|
|
456
|
+
expect(parts[2].value).to.equal(' and thing 2 ');
|
|
457
|
+
expect(parts[3].part).to.equal('parameter');
|
|
458
|
+
expect(parts[3].part_index).to.equal(1);
|
|
459
|
+
expect(parts[3].label).to.equal("dogs_1");
|
|
460
|
+
expect(parts[4].part).to.equal('text');
|
|
461
|
+
expect(parts[4].value).to.equal('.');
|
|
462
|
+
|
|
463
|
+
var qm = rc_question.guessTemplateConfig(multi_template_meta);
|
|
464
|
+
const tm = q['fields']['title']['label'];
|
|
465
|
+
expect(tm).to.equal('title');
|
|
466
|
+
const partsm = qm['fields']['dogs']['parts'];
|
|
467
|
+
expect(partsm.length).to.equal(5);
|
|
468
|
+
expect(partsm[0].part).to.equal('text');
|
|
469
|
+
expect(partsm[0].value).to.equal('The dogs item contains thing 1 ');
|
|
470
|
+
expect(partsm[1].part).to.equal('parameter');
|
|
471
|
+
expect(partsm[1].part_index).to.equal(0);
|
|
472
|
+
expect(partsm[1].label).to.equal("First Doggy");
|
|
473
|
+
expect(partsm[2].part).to.equal('text');
|
|
474
|
+
expect(partsm[2].value).to.equal(' and thing 2 ');
|
|
475
|
+
expect(partsm[3].part).to.equal('parameter');
|
|
476
|
+
expect(partsm[3].part_index).to.equal(1);
|
|
477
|
+
expect(partsm[3].label).to.equal("Second Doggy");
|
|
478
|
+
expect(partsm[4].part).to.equal('text');
|
|
479
|
+
expect(partsm[4].value).to.equal('.');
|
|
480
|
+
});
|
|
481
|
+
});
|
|
482
|
+
|