@reality.eth/reality-eth-lib 3.1.15 → 3.2.0
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 +35 -37
- package/package.json +4 -3
- package/test/formatters.js +62 -2
package/formatters/question.js
CHANGED
|
@@ -7,6 +7,8 @@ const vsprintf = require("sprintf-js").vsprintf
|
|
|
7
7
|
const QUESTION_MAX_OUTCOMES = 128;
|
|
8
8
|
const marked = require('marked');
|
|
9
9
|
const DOMPurify = require('isomorphic-dompurify');
|
|
10
|
+
const { convert} = require('html-to-text');
|
|
11
|
+
marked.setOptions({headerIds: false});
|
|
10
12
|
|
|
11
13
|
exports.delimiter = function() {
|
|
12
14
|
return '\u241f'; // Thought about '\u0000' but it seems to break something;
|
|
@@ -190,17 +192,16 @@ exports.parseQuestionJSON = function(data, errors_to_title) {
|
|
|
190
192
|
};
|
|
191
193
|
}
|
|
192
194
|
|
|
193
|
-
if (question_json['outcomes'] && question_json['outcomes'].length > QUESTION_MAX_OUTCOMES)
|
|
194
|
-
if(question_json['errors'])
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
question_json['errors'] = {'invalid_precision': true};
|
|
195
|
+
if (question_json['outcomes'] && question_json['outcomes'].length > QUESTION_MAX_OUTCOMES) {
|
|
196
|
+
if (!question_json['errors']) question_json['errors'] = {};
|
|
197
|
+
question_json['errors']['too_many_outcomes'] = true;
|
|
198
|
+
}
|
|
199
|
+
if ('type' in question_json && question_json['type'] == 'datetime' && 'precision' in question_json) {
|
|
200
|
+
if (!(['Y', 'm', 'd', 'H', 'i', 's'].includes(question_json['precision']))) {
|
|
201
|
+
if (!question_json['errors']) question_json['errors'] = {};
|
|
202
|
+
question_json['errors']['invalid_precision'] = true;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
204
205
|
// If errors_to_title is specified, we add any error message to the title to make sure we don't lose it
|
|
205
206
|
if (errors_to_title) {
|
|
206
207
|
if ('errors' in question_json) {
|
|
@@ -216,34 +217,31 @@ exports.parseQuestionJSON = function(data, errors_to_title) {
|
|
|
216
217
|
}
|
|
217
218
|
}
|
|
218
219
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
question_json['format'] = 'text/plain';
|
|
237
|
-
break;
|
|
238
|
-
}
|
|
239
|
-
default:{
|
|
240
|
-
question_json['errors'] = {'invalid_format': true};
|
|
241
|
-
break;
|
|
220
|
+
if (!question_json['format']) {
|
|
221
|
+
question_json['format'] = 'text/plain';
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
if (question_json['format'] == 'text/plain') {
|
|
225
|
+
question_json['title_text'] = question_json['title'];
|
|
226
|
+
} else if (question_json['format'] == 'text/markdown') {
|
|
227
|
+
try{
|
|
228
|
+
const safeMarkdown = DOMPurify.sanitize(question_json['title'], { USE_PROFILES: {html: false}});
|
|
229
|
+
if (safeMarkdown !== question_json['title']) {
|
|
230
|
+
if (!question_json['errors']) question_json['errors'] = {};
|
|
231
|
+
question_json['errors']['unsafe_markdown'] = true;
|
|
232
|
+
} else {
|
|
233
|
+
question_json['title_html'] = marked.parse(safeMarkdown).replace(/<img.*src=\"(.*?)\".*alt=\"(.*?)\".*\/?>/, '<a href="$1">$2</a>');
|
|
234
|
+
question_json['title_text'] = convert(question_json['title_html'], {
|
|
235
|
+
selectors: [{selector: 'h1', options: { uppercase: false }}, {selector: 'h2', options: { uppercase: false }}]
|
|
236
|
+
});
|
|
242
237
|
}
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
if(question_json && question_json['errors'])
|
|
238
|
+
} catch(e){
|
|
239
|
+
if (!question_json['errors']) question_json['errors'] = {};
|
|
246
240
|
question_json['errors']['markdown_parse_failed'] = true
|
|
241
|
+
}
|
|
242
|
+
} else {
|
|
243
|
+
if (!question_json['errors']) question_json['errors'] = {};
|
|
244
|
+
question_json['errors']['invalid_format'] = true;
|
|
247
245
|
}
|
|
248
246
|
|
|
249
247
|
// If errors_to_title is specified, we add any error message to the title to make sure we don't lose it
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@reality.eth/reality-eth-lib",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.2.0",
|
|
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,10 +16,11 @@
|
|
|
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.17",
|
|
20
20
|
"bignumber.js": "^7.2.1",
|
|
21
21
|
"bn.js": "^5.2.1",
|
|
22
22
|
"ethereumjs-abi": "^0.6.5",
|
|
23
|
+
"html-to-text": "^8.2.1",
|
|
23
24
|
"isomorphic-dompurify": "^0.23.0",
|
|
24
25
|
"marked": "^4.1.1",
|
|
25
26
|
"sprintf-js": "^1.1.1"
|
|
@@ -38,5 +39,5 @@
|
|
|
38
39
|
"url": "https://github.com/RealityETH/monorepo/issues"
|
|
39
40
|
},
|
|
40
41
|
"homepage": "https://reality.eth.link",
|
|
41
|
-
"gitHead": "
|
|
42
|
+
"gitHead": "1962e3224fbde8811b888a731e714c8bd23b42f7"
|
|
42
43
|
}
|
package/test/formatters.js
CHANGED
|
@@ -240,6 +240,66 @@ describe('Broken questions', function() {
|
|
|
240
240
|
});
|
|
241
241
|
});
|
|
242
242
|
|
|
243
|
+
describe('Markdown questions', function() {
|
|
244
|
+
it('Sets title, title_html and title_text appropriatly', function() {
|
|
245
|
+
const qMarkdown = "{\"title\": \"# my title oh yes\", \"type\": \"bool\", \"category\": \"art\", \"lang\": \"en_US\", \"format\": \"text/markdown\"}";
|
|
246
|
+
const q = rc_question.parseQuestionJSON(qMarkdown, true);
|
|
247
|
+
expect(q.errors).to.equal(undefined);
|
|
248
|
+
expect(q.format).to.equal('text/markdown');
|
|
249
|
+
expect(q.title_text).to.equal('my title oh yes');
|
|
250
|
+
expect(q.title).to.equal('# my title oh yes');
|
|
251
|
+
expect(q.title_html).to.equal('<h1>my title oh yes</h1>'+"\n");
|
|
252
|
+
});
|
|
253
|
+
it('Set title_text appropriatly for italic and bold headings', function() {
|
|
254
|
+
const qMarkdown = "{\"title\": \"# _Italic Heading 1_\\n## __Bold Heading 2__\", \"type\": \"bool\", \"category\": \"art\", \"lang\": \"en_US\", \"format\": \"text/markdown\"}";
|
|
255
|
+
const q = rc_question.parseQuestionJSON(qMarkdown, true);
|
|
256
|
+
expect(q.errors).to.equal(undefined);
|
|
257
|
+
expect(q.format).to.equal('text/markdown');
|
|
258
|
+
expect(q.title_text).to.equal('Italic Heading 1\n\n\nBold Heading 2');
|
|
259
|
+
expect(q.title).to.equal('# _Italic Heading 1_\n## __Bold Heading 2__');
|
|
260
|
+
expect(q.title_html).to.equal(`<h1><em>Italic Heading 1</em></h1>\n<h2><strong>Bold Heading 2</strong></h2>`+"\n");
|
|
261
|
+
});
|
|
262
|
+
it('Set title_text appropriatly for italic and bold quotes', function() {
|
|
263
|
+
const qMarkdown = "{\"title\": \">_Italic_ __Bold__\", \"type\": \"bool\", \"category\": \"art\", \"lang\": \"en_US\", \"format\": \"text/markdown\"}";
|
|
264
|
+
const q = rc_question.parseQuestionJSON(qMarkdown, true);
|
|
265
|
+
expect(q.errors).to.equal(undefined);
|
|
266
|
+
expect(q.format).to.equal('text/markdown');
|
|
267
|
+
expect(q.title_text).to.equal('> Italic Bold');
|
|
268
|
+
expect(q.title).to.equal('>_Italic_ __Bold__');
|
|
269
|
+
expect(q.title_html).to.equal('<blockquote>\n<p><em>Italic</em> <strong>Bold</strong></p>\n</blockquote>'+"\n");
|
|
270
|
+
});
|
|
271
|
+
it('Set title_text appropriatly for lists', function() {
|
|
272
|
+
const qMarkdown = "{\"title\": \"* __Item One__\\n* __Item Two__\\n* __Item Three__\\n1. Item One\\n2. Item Two\\n3. Item Three\", \"type\": \"bool\", \"category\": \"art\", \"lang\": \"en_US\", \"format\": \"text/markdown\"}";
|
|
273
|
+
const q = rc_question.parseQuestionJSON(qMarkdown, true);
|
|
274
|
+
expect(q.errors).to.equal(undefined);
|
|
275
|
+
expect(q.format).to.equal('text/markdown');
|
|
276
|
+
expect(q.title_text).to.equal(' * Item One\n * Item Two\n * Item Three\n\n 1. Item One\n 2. Item Two\n 3. Item Three');
|
|
277
|
+
expect(q.title).to.equal('* __Item One__\n* __Item Two__\n* __Item Three__\n1. Item One\n2. Item Two\n3. Item Three');
|
|
278
|
+
expect(q.title_html).to.equal(
|
|
279
|
+
`<ul>
|
|
280
|
+
<li><strong>Item One</strong></li>
|
|
281
|
+
<li><strong>Item Two</strong></li>
|
|
282
|
+
<li><strong>Item Three</strong></li>
|
|
283
|
+
</ul>
|
|
284
|
+
<ol>
|
|
285
|
+
<li>Item One</li>
|
|
286
|
+
<li>Item Two</li>
|
|
287
|
+
<li>Item Three</li>
|
|
288
|
+
</ol>` + "\n");
|
|
289
|
+
});
|
|
290
|
+
it('Set title_text appropriatly for code blocks', function() {
|
|
291
|
+
const qMarkdown = "{\"title\": \"`Inline code` with backticks\\n\\n```# code block\\nprint '3 backticks or'\\nprint 'indent 4 spaces'```\", \"type\": \"bool\", \"category\": \"art\", \"lang\": \"en_US\", \"format\": \"text/markdown\"}";
|
|
292
|
+
const q = rc_question.parseQuestionJSON(qMarkdown, true);
|
|
293
|
+
expect(q.errors).to.equal(undefined);
|
|
294
|
+
expect(q.format).to.equal('text/markdown');
|
|
295
|
+
expect(q.title_text).to.equal(`Inline code with backticks\n\n# code block print '3 backticks or' print 'indent 4 spaces'`);
|
|
296
|
+
expect(q.title).to.equal("`Inline code` with backticks\n\n```# code block\nprint '3 backticks or'\nprint 'indent 4 spaces'```");
|
|
297
|
+
expect(q.title_html).to.equal(
|
|
298
|
+
`<p><code>Inline code</code> with backticks</p>
|
|
299
|
+
<p><code># code block print '3 backticks or' print 'indent 4 spaces'</code></p>`+ "\n");
|
|
300
|
+
});
|
|
301
|
+
});
|
|
302
|
+
|
|
243
303
|
describe('Unsafe markdown questions', function() {
|
|
244
304
|
it('Sets an error if a question includes unsafe html in markdown', function() {
|
|
245
305
|
const qUnsafeMarkdown = "{\"title\": \"# Title <p>abc<iframe\/\/src=jAva	script:alert(3)>def<\/p>\", \"type\": \"bool\", \"category\": \"art\", \"lang\": \"en_US\", \"format\": \"text/markdown\"}";
|
|
@@ -247,8 +307,8 @@ describe('Unsafe markdown questions', function() {
|
|
|
247
307
|
expect(q.errors.unsafe_markdown).to.equal(true);
|
|
248
308
|
});
|
|
249
309
|
it('Sets no error if a question includes valid markdown without html', function() {
|
|
250
|
-
const
|
|
251
|
-
const q = rc_question.parseQuestionJSON(
|
|
310
|
+
const qSafeMarkdown = "{\"title\": \"# Title\", \"type\": \"bool\", \"category\": \"art\", \"lang\": \"en_US\", \"format\": \"text/markdown\"}";
|
|
311
|
+
const q = rc_question.parseQuestionJSON(qSafeMarkdown, true);
|
|
252
312
|
expect(q.errors).to.equal(undefined);
|
|
253
313
|
expect(q.format).to.equal('text/markdown');
|
|
254
314
|
});
|