@iebh/polyglot 4.4.9 → 4.5.1
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/LICENSE +1 -1
- package/README.md +26 -14
- package/lib/data/fieldCodesObject.js +1 -3
- package/lib/data/fieldCodesParse.js +0 -2
- package/lib/data/meshObject.js +1 -3
- package/lib/data/meshTranslationsObject.js +0 -2
- package/lib/data/meshTranslationsParse.js +0 -2
- package/lib/index.js +9 -26
- package/lib/modules/engines/generic.js +20 -84
- package/lib/modules/engines.js +4 -5
- package/lib/modules/global.js +0 -1
- package/lib/modules/parse.js +253 -303
- package/lib/modules/tools.js +28 -76
- package/package.json +6 -2
package/lib/modules/tools.js
CHANGED
|
@@ -4,13 +4,9 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports["default"] = void 0;
|
|
7
|
-
|
|
8
7
|
var _global = _interopRequireDefault(require("./global.js"));
|
|
9
|
-
|
|
10
8
|
var _lodash = _interopRequireDefault(require("lodash"));
|
|
11
|
-
|
|
12
9
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
|
|
13
|
-
|
|
14
10
|
/**
|
|
15
11
|
* Collection of utility functions to apply common behaviour to a compiled tree
|
|
16
12
|
* @var {Object}
|
|
@@ -30,20 +26,21 @@ var tools = {
|
|
|
30
26
|
|
|
31
27
|
var treeWalker = function treeWalker(tree, path) {
|
|
32
28
|
tree.forEach(function (branch, branchKey) {
|
|
33
|
-
var nodePath = path.concat(branchKey);
|
|
29
|
+
var nodePath = path.concat(branchKey);
|
|
34
30
|
|
|
31
|
+
// Fire callback if it matches
|
|
35
32
|
if (!types || _lodash["default"].includes(types, branch.type)) {
|
|
36
33
|
var result = callback(branch, nodePath);
|
|
37
34
|
if (result === 'DEL') removals.push(nodePath);
|
|
38
|
-
}
|
|
39
|
-
|
|
35
|
+
}
|
|
40
36
|
|
|
37
|
+
// Walk down nodes if its a group
|
|
41
38
|
if (branch.type == 'group' || branch.type == 'line') treeWalker(branch.nodes, nodePath.concat(['nodes']));
|
|
42
39
|
});
|
|
43
40
|
};
|
|
41
|
+
treeWalker(tree, []);
|
|
44
42
|
|
|
45
|
-
|
|
46
|
-
|
|
43
|
+
// Crop all items marked as removals
|
|
47
44
|
removals.reverse() // Walk in reverse order so we don't screw up arrays
|
|
48
45
|
.forEach(function (path) {
|
|
49
46
|
var nodeName = path.pop();
|
|
@@ -52,7 +49,6 @@ var tools = {
|
|
|
52
49
|
});
|
|
53
50
|
return tree;
|
|
54
51
|
},
|
|
55
|
-
|
|
56
52
|
/**
|
|
57
53
|
* Apply a series of text replacements to every matching node object within a tree
|
|
58
54
|
* This function mutates tree
|
|
@@ -74,10 +70,10 @@ var tools = {
|
|
|
74
70
|
escapeRegExp: function escapeRegExp(string) {
|
|
75
71
|
return string.replace(/[.*+?^${}()[\]\\]/g, '\\$&'); // $& means the whole matched string
|
|
76
72
|
},
|
|
73
|
+
|
|
77
74
|
// Replace multiple terms at once
|
|
78
75
|
multiReplace: function multiReplace(text, replaceObj) {
|
|
79
76
|
var template = tools.escapeRegExp(Object.keys(replaceObj).join("|"));
|
|
80
|
-
|
|
81
77
|
if (template.length > 0) {
|
|
82
78
|
var regex = new RegExp(template, "g");
|
|
83
79
|
return text.replace(regex, function (match) {
|
|
@@ -87,7 +83,6 @@ var tools = {
|
|
|
87
83
|
return text;
|
|
88
84
|
}
|
|
89
85
|
},
|
|
90
|
-
|
|
91
86
|
/**
|
|
92
87
|
* Retrieve the contents of a template by its ID
|
|
93
88
|
* NOTE: If the specific engine definition is not found 'default' is used (and it will be pre-parsed via .translate())
|
|
@@ -102,7 +97,6 @@ var tools = {
|
|
|
102
97
|
if (!_global["default"].templates[template].engines[engine]) return "Template: \"".concat(template, "\" not found for engine: \"").concat(engine, "\"");
|
|
103
98
|
return '';
|
|
104
99
|
},
|
|
105
|
-
|
|
106
100
|
/**
|
|
107
101
|
* Structure the wild cards correctly for cochrane to ensure no wildcards appear inside quotation marks
|
|
108
102
|
* @param {string} text The text to parse
|
|
@@ -114,56 +108,47 @@ var tools = {
|
|
|
114
108
|
var words = text.split(" ");
|
|
115
109
|
var lastMatch = -1;
|
|
116
110
|
var foundMatch = false;
|
|
117
|
-
|
|
118
111
|
var _loop = function _loop(i) {
|
|
119
112
|
if (wildcards.some(function (wildcard) {
|
|
120
113
|
return words[i].includes(wildcard);
|
|
121
114
|
})) {
|
|
122
|
-
foundMatch = true;
|
|
123
|
-
|
|
115
|
+
foundMatch = true;
|
|
116
|
+
// Add quotation marks to previous word/s if the previous word was not a match
|
|
124
117
|
if (i - 1 > lastMatch) {
|
|
125
118
|
words[lastMatch + 1] = highlighting ? '<font color="DarkBlue">"' + words[lastMatch + 1] : '"' + words[lastMatch + 1];
|
|
126
119
|
words[i - 1] = highlighting ? words[i - 1] + '"</font>' : words[i - 1] + '"';
|
|
127
120
|
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
121
|
+
lastMatch = i;
|
|
122
|
+
// Check that there is a word before and it is not a wildcard word
|
|
131
123
|
if (i > 0 && !wildcards.some(function (wildcard) {
|
|
132
124
|
return words[i - 1].includes(wildcard);
|
|
133
125
|
})) {
|
|
134
126
|
words[i] = highlighting ? '<font color="purple">NEXT</font> ' + words[i] : 'NEXT ' + words[i];
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
|
|
127
|
+
}
|
|
128
|
+
// Check that there is a word after
|
|
138
129
|
if (i < words.length - 1) {
|
|
139
130
|
words[i] = highlighting ? words[i] + ' <font color="purple">NEXT</font>' : words[i] + " NEXT";
|
|
140
131
|
}
|
|
141
132
|
}
|
|
142
133
|
};
|
|
143
|
-
|
|
144
134
|
for (var i = 0; i < words.length; i++) {
|
|
145
135
|
_loop(i);
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
|
|
136
|
+
}
|
|
137
|
+
// Add quotation marks to word/s after the final match
|
|
149
138
|
if (lastMatch + 1 < words.length) {
|
|
150
139
|
words[lastMatch + 1] = highlighting ? '<font color="DarkBlue">"' + words[lastMatch + 1] : '"' + words[lastMatch + 1];
|
|
151
140
|
words[words.length - 1] = highlighting ? words[words.length - 1] + '"</font>' : words[words.length - 1] + '"';
|
|
152
141
|
}
|
|
153
|
-
|
|
154
142
|
return foundMatch ? "(".concat(words.join(" "), ")") : words.join(" ");
|
|
155
143
|
},
|
|
156
|
-
|
|
157
144
|
/**
|
|
158
145
|
* Print number in format defined by engine
|
|
159
146
|
* @param {string} engine Engine to use
|
|
160
147
|
* @param {string} ref Branch ref (e.g. 1)
|
|
161
148
|
* @return {string} Formatted number
|
|
162
|
-
*/
|
|
163
|
-
printNumber: function printNumber(engine, ref) {
|
|
149
|
+
*/printNumber: function printNumber(engine, ref) {
|
|
164
150
|
// Get line number format for engine
|
|
165
151
|
var number = ref;
|
|
166
|
-
|
|
167
152
|
switch (engine) {
|
|
168
153
|
case 'PubMed full':
|
|
169
154
|
case 'PubMed abbreviation':
|
|
@@ -175,24 +160,19 @@ var tools = {
|
|
|
175
160
|
case 'Scopus (advanced search)':
|
|
176
161
|
number = "#" + ref;
|
|
177
162
|
break;
|
|
178
|
-
|
|
179
163
|
case 'Ovid MEDLINE':
|
|
180
164
|
case 'PsycInfo (Ovid)':
|
|
181
165
|
case 'ProQuest Health and Medical':
|
|
182
166
|
number = ref;
|
|
183
167
|
break;
|
|
184
|
-
|
|
185
168
|
case 'CINAHL (Ebsco)':
|
|
186
169
|
case 'SPORTDiscus':
|
|
187
170
|
number = "S" + ref;
|
|
188
171
|
break;
|
|
189
|
-
|
|
190
172
|
default:
|
|
191
173
|
}
|
|
192
|
-
|
|
193
174
|
return number;
|
|
194
175
|
},
|
|
195
|
-
|
|
196
176
|
/**
|
|
197
177
|
* Determine if a phrase needs to be enclosed within speachmarks and return the result
|
|
198
178
|
* @param {Object} branch Phrase branch to examine
|
|
@@ -202,12 +182,11 @@ var tools = {
|
|
|
202
182
|
*/
|
|
203
183
|
quotePhrase: function quotePhrase(branch, engine, settings) {
|
|
204
184
|
var text = _lodash["default"].trimEnd(branch.content);
|
|
185
|
+
var space = /\s/.test(text);
|
|
205
186
|
|
|
206
|
-
|
|
207
|
-
|
|
187
|
+
// Apply wildcard replacements
|
|
208
188
|
if (settings.replaceWildcards) {
|
|
209
189
|
var replaceObj = {};
|
|
210
|
-
|
|
211
190
|
switch (engine) {
|
|
212
191
|
case 'PubMed full':
|
|
213
192
|
case 'PubMed abbreviation':
|
|
@@ -217,23 +196,19 @@ var tools = {
|
|
|
217
196
|
'#': settings.highlighting ? tools.createTooltip("*", "As PubMed does not single character wildcards a wildcard is used here", "highlight") : '*'
|
|
218
197
|
};
|
|
219
198
|
break;
|
|
220
|
-
|
|
221
199
|
case 'Ovid MEDLINE':
|
|
222
200
|
break;
|
|
223
201
|
// Nothing needed
|
|
224
|
-
|
|
225
202
|
case 'Cochrane Library':
|
|
226
203
|
if (space) {
|
|
227
204
|
text = tools.wildCardCochrane(text, settings.highlighting);
|
|
228
205
|
}
|
|
229
|
-
|
|
230
206
|
replaceObj = {
|
|
231
207
|
'$': settings.highlighting ? tools.createTooltip("?", "As Cochrane does not support single character truncation, the 0 or 1 character truncation is used here.", "highlight") : '?',
|
|
232
208
|
'#': '?'
|
|
233
209
|
};
|
|
234
210
|
return tools.multiReplace(text, replaceObj);
|
|
235
211
|
// Return here to prevent duplicate quotes
|
|
236
|
-
|
|
237
212
|
case 'Embase (Elsevier)':
|
|
238
213
|
case 'Web of Science':
|
|
239
214
|
case 'WoS Advanced':
|
|
@@ -243,7 +218,6 @@ var tools = {
|
|
|
243
218
|
'#': '?'
|
|
244
219
|
};
|
|
245
220
|
break;
|
|
246
|
-
|
|
247
221
|
case 'CINAHL (Ebsco)':
|
|
248
222
|
replaceObj = {
|
|
249
223
|
'$': '?',
|
|
@@ -251,7 +225,6 @@ var tools = {
|
|
|
251
225
|
'#': '?'
|
|
252
226
|
};
|
|
253
227
|
break;
|
|
254
|
-
|
|
255
228
|
case 'Scopus (basic search)':
|
|
256
229
|
case 'Scopus (advanced search)':
|
|
257
230
|
// space = true; //Always include quotes with scopus to make phrase a "loose phrase"
|
|
@@ -261,20 +234,17 @@ var tools = {
|
|
|
261
234
|
'#': '?'
|
|
262
235
|
};
|
|
263
236
|
break;
|
|
264
|
-
|
|
265
237
|
case 'PsycInfo (Ovid)':
|
|
266
238
|
replaceObj = {
|
|
267
239
|
'$': '#'
|
|
268
240
|
};
|
|
269
241
|
break;
|
|
270
|
-
|
|
271
242
|
case 'ProQuest Health and Medical':
|
|
272
243
|
replaceObj = {
|
|
273
244
|
'$': '?',
|
|
274
245
|
'#': '?'
|
|
275
246
|
};
|
|
276
247
|
break;
|
|
277
|
-
|
|
278
248
|
case 'SPORTDiscus':
|
|
279
249
|
if (!settings.testing) {
|
|
280
250
|
space = true; //Always include quotes with SPORTDiscus
|
|
@@ -285,7 +255,6 @@ var tools = {
|
|
|
285
255
|
'?': '#'
|
|
286
256
|
};
|
|
287
257
|
break;
|
|
288
|
-
|
|
289
258
|
case 'Informit Health Collection':
|
|
290
259
|
replaceObj = {
|
|
291
260
|
'$': '?',
|
|
@@ -293,13 +262,10 @@ var tools = {
|
|
|
293
262
|
};
|
|
294
263
|
break;
|
|
295
264
|
}
|
|
296
|
-
|
|
297
265
|
text = tools.multiReplace(text, replaceObj);
|
|
298
266
|
}
|
|
299
|
-
|
|
300
267
|
return engine == 'Embase (Elsevier)' ? space ? settings.highlighting ? "<font color='DarkBlue'>'" + text + "'</font>" : "'" + text + "'" : text : space ? settings.highlighting ? '<font color="DarkBlue">"' + text + '"</font>' : '"' + text + '"' : text;
|
|
301
268
|
},
|
|
302
|
-
|
|
303
269
|
/**
|
|
304
270
|
* Convert the '$or' / '$and' nodes within a tree into a nested structure
|
|
305
271
|
* This function will also flatten identical branches (i.e. run-on multiple $and / $or into one array)
|
|
@@ -308,27 +274,26 @@ var tools = {
|
|
|
308
274
|
*/
|
|
309
275
|
renestConditions: function renestConditions(tree) {
|
|
310
276
|
if (!_lodash["default"].isArray(tree)) return tree; // Not an array - skip
|
|
311
|
-
// Transform arrays of the form: [X1, $or/$and, X2] => {$or/$and: [X1, X2]}
|
|
312
277
|
|
|
278
|
+
// Transform arrays of the form: [X1, $or/$and, X2] => {$or/$and: [X1, X2]}
|
|
313
279
|
return tree.reduce(function (res, branch, index, arr) {
|
|
314
280
|
var firstKey = (0, _lodash["default"])(branch).keys().first();
|
|
315
|
-
|
|
316
281
|
if (firstKey == '$or' || firstKey == '$and') {
|
|
317
282
|
// Is a combinator
|
|
318
283
|
var expression = {};
|
|
319
|
-
expression[firstKey] = [res.pop(),
|
|
284
|
+
expression[firstKey] = [res.pop(),
|
|
285
|
+
// Right side is the last thing we added to the buffer
|
|
320
286
|
arr.splice(index + 1, 1)[0] // Left side is the next thing we're going to look at in the array
|
|
321
287
|
];
|
|
288
|
+
|
|
322
289
|
res.push(expression);
|
|
323
290
|
} else {
|
|
324
291
|
// Unknown - just push to array and carry on processing
|
|
325
292
|
res.push(branch);
|
|
326
293
|
}
|
|
327
|
-
|
|
328
294
|
return res;
|
|
329
295
|
}, []);
|
|
330
296
|
},
|
|
331
|
-
|
|
332
297
|
/**
|
|
333
298
|
* Combine multiple run-on $and / $or conditional branches into one branch
|
|
334
299
|
* This function is a companion function to renestConditions and should be called directly afterwards if needed
|
|
@@ -345,25 +310,19 @@ var tools = {
|
|
|
345
310
|
var settings = _lodash["default"].defaults(options, {
|
|
346
311
|
depth: 10
|
|
347
312
|
});
|
|
348
|
-
|
|
349
313
|
var collapses = [];
|
|
350
|
-
|
|
351
314
|
var traverseTree = function traverseTree(branch) {
|
|
352
315
|
var path = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
|
|
353
|
-
|
|
354
316
|
// Recurse into each tree node and make a bottom-up list of nodes we need to collapse
|
|
355
317
|
_lodash["default"].forEach(branch, function (v, k) {
|
|
356
318
|
// Use _.map if its an array and _.mapValues if we're examining an object
|
|
357
319
|
if (_lodash["default"].isObject(v)) {
|
|
358
320
|
var firstKey = (0, _lodash["default"])(branch).keys().first();
|
|
359
|
-
|
|
360
321
|
if (path.length > 1 && (firstKey == '$or' || firstKey == '$and')) {
|
|
361
322
|
// Mark for cleanup later (when we can do a bottom-up traversal)
|
|
362
323
|
var lastKey = _lodash["default"].findLast(collapses, function (i) {
|
|
363
324
|
return i.key == '$and' || i.key == '$or';
|
|
364
325
|
}); // Collapse only identical keys
|
|
365
|
-
|
|
366
|
-
|
|
367
326
|
if (!lastKey || lastKey.key == firstKey) {
|
|
368
327
|
collapses.push({
|
|
369
328
|
key: firstKey,
|
|
@@ -371,50 +330,43 @@ var tools = {
|
|
|
371
330
|
});
|
|
372
331
|
}
|
|
373
332
|
}
|
|
374
|
-
|
|
375
333
|
if (settings.depth && path.length > settings.depth) return; // Stop recursing after depth has been reached
|
|
376
|
-
|
|
377
334
|
traverseTree(v, path.concat([k]));
|
|
378
335
|
}
|
|
379
336
|
});
|
|
380
337
|
};
|
|
381
|
-
|
|
382
338
|
traverseTree(tree);
|
|
383
339
|
collapses.forEach(function (collapse) {
|
|
384
340
|
var parent = _lodash["default"].get(tree, collapse.path.slice(0, -1));
|
|
385
|
-
|
|
386
341
|
var child = _lodash["default"].get(tree, collapse.path.concat([collapse.key]));
|
|
387
|
-
|
|
388
342
|
if (!child || !parent || !parent.length) return;
|
|
389
343
|
var child2 = parent[1];
|
|
390
|
-
if (child2) child.push(child2);
|
|
344
|
+
if (child2) child.push(child2);
|
|
391
345
|
|
|
346
|
+
// Wrap $or conditions (that have an '$and' parent) in an object {{{
|
|
392
347
|
var lastParent = (0, _lodash["default"])(collapse.path).slice(0, -1).findLast(_lodash["default"].isString);
|
|
393
348
|
if (lastParent && lastParent == '$and' && collapse.key == '$or') child = {
|
|
394
349
|
$or: child
|
|
395
|
-
};
|
|
350
|
+
};
|
|
351
|
+
// }}}
|
|
396
352
|
|
|
397
353
|
_lodash["default"].set(tree, collapse.path.slice(0, -1), child);
|
|
398
354
|
});
|
|
399
355
|
return tree;
|
|
400
356
|
},
|
|
401
|
-
|
|
402
357
|
/**
|
|
403
358
|
* Create a tooltip with a specified message
|
|
404
359
|
* @param {string} content Content to append tooltip to
|
|
405
360
|
* @param {string} message Message to contain inside tooltip
|
|
406
361
|
* @param {string} css CSS class to use
|
|
407
|
-
*/
|
|
408
|
-
createTooltip: function createTooltip(content, message, css) {
|
|
362
|
+
*/createTooltip: function createTooltip(content, message, css) {
|
|
409
363
|
css = typeof css !== 'undefined' ? css : "black-underline";
|
|
410
364
|
return "<span class=\"" + css + '" v-tooltip="`' + message + '`">' + content + '</span>';
|
|
411
365
|
},
|
|
412
|
-
|
|
413
366
|
/**
|
|
414
367
|
* Create a popover with options to replace empty field tags with specified field tag
|
|
415
368
|
* @param {string} content Content to append popover to
|
|
416
|
-
*/
|
|
417
|
-
createPopover: function createPopover(content, offset) {
|
|
369
|
+
*/createPopover: function createPopover(content, offset) {
|
|
418
370
|
return '<v-popover offset="8" placement="right">' + '<span class="blue-underline">' + content + '</span>' + '<template slot="popover">' + '<h3 class="popover-header">Add Field Tag</h3>' + '<input class="tooltip-content" v-model="customField" placeholder="Field tag" />' + '<div class="replace-all">' + '<input type="checkbox" id="checkbox" v-model="replaceAll">' + '<label for="checkbox">Replace All</label>' + '</div>' + '<div class="replace-buttons">' + '<button v-on:click="replaceFields(customField, replaceAll, ' + offset + ')" type="button" class="btn btn-primary">Replace</button>' + '<button v-close-popover type="button" class="btn btn-dark">Close</button>' + '</div>' + '</template>' + '</v-popover>';
|
|
419
371
|
}
|
|
420
372
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@iebh/polyglot",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.5.1",
|
|
4
4
|
"description": "IEBH-SRA tool to convert between different medical database search formats",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -30,7 +30,11 @@
|
|
|
30
30
|
"medical",
|
|
31
31
|
"research"
|
|
32
32
|
],
|
|
33
|
-
"author":
|
|
33
|
+
"author": [
|
|
34
|
+
"Matt Carter <m@ttcarter.com> (https://github.com/hash-bang)",
|
|
35
|
+
"Connor Forbes <cforbes.software@gmail.com> (https://github.com/connorf25)",
|
|
36
|
+
"Justin Cark <jclark@bond.edu.au> (https://github.com/Justin-Clarc)"
|
|
37
|
+
],
|
|
34
38
|
"license": "MIT",
|
|
35
39
|
"bugs": {
|
|
36
40
|
"url": "https://github.com/IEBH/sra-polyglot/issues"
|