@iebh/reflib 2.7.2 → 2.8.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/README.md +23 -0
- package/app.js +85 -0
- package/package.json +5 -1
- package/shared/parseArgs.js +104 -0
package/README.md
CHANGED
|
@@ -30,6 +30,29 @@ Compatibility
|
|
|
30
30
|
* Medline seems to implement a totally different [publication type system](https://www.nlm.nih.gov/mesh/pubtypes.html) than others. Reflib will attempt to guess the best match, storing the original type in the `medlineType` key. Should the citation library be exported _back_ to Medline / `.nbib` files this key will take precedence to avoid data loss
|
|
31
31
|
|
|
32
32
|
|
|
33
|
+
Command Line Interface
|
|
34
|
+
======================
|
|
35
|
+
This NPM ships with a very basic Command Line Interface (CLI) for very basic Reflib files manipulation.
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
Usage: reflib -i INPUT_FILE [-f FORMAT] [-o -|OUTPUT_FILE]
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
-i, --input <file> Input file to process
|
|
42
|
+
|
|
43
|
+
-o, --output <file> Output file to save. Use '-' for STDOUT
|
|
44
|
+
|
|
45
|
+
-f, --format <reflib-format> Override or set the file output type (if omitted the outfile filename
|
|
46
|
+
is used to determine the format)
|
|
47
|
+
|
|
48
|
+
-v, --verbose Be verbose when processing
|
|
49
|
+
|
|
50
|
+
--version Print CLI version and exit
|
|
51
|
+
|
|
52
|
+
-h, --help This help screen
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
|
|
33
56
|
Reference Structure
|
|
34
57
|
===================
|
|
35
58
|
Reflib creates a simple Plain-Old-JavaScript-Object (POJO) for each reference it parses, or writes to a file format when given a collection of the same.
|
package/app.js
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
#!/usr/bin/node
|
|
2
|
+
|
|
3
|
+
import parseArgs from './shared/parseArgs.js';
|
|
4
|
+
import packageInfo from './package.json' with {type: 'json'};
|
|
5
|
+
import reflib from './lib/default.js';
|
|
6
|
+
|
|
7
|
+
let help = `
|
|
8
|
+
|
|
9
|
+
Usage: reflib -i INPUT_FILE [-f FORMAT] [-o -|OUTPUT_FILE]
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
-i, --input <file> Input file to process
|
|
13
|
+
|
|
14
|
+
-o, --output <file> Output file to save. Use '-' for STDOUT
|
|
15
|
+
|
|
16
|
+
-f, --format <reflib-format> Override or set the file output type (if omitted the outfile filename
|
|
17
|
+
is used to determine the format)
|
|
18
|
+
|
|
19
|
+
-v, --verbose Be verbose when processing
|
|
20
|
+
|
|
21
|
+
--version Print CLI version and exit
|
|
22
|
+
|
|
23
|
+
-h, --help This help screen
|
|
24
|
+
`;
|
|
25
|
+
|
|
26
|
+
// Parse args {{{
|
|
27
|
+
let args = parseArgs.parse();
|
|
28
|
+
args = parseArgs.expand(args, {
|
|
29
|
+
'h': 'help',
|
|
30
|
+
'i': 'input',
|
|
31
|
+
'o': 'output',
|
|
32
|
+
'f': 'format',
|
|
33
|
+
'v': 'verbose',
|
|
34
|
+
});
|
|
35
|
+
// }}}
|
|
36
|
+
|
|
37
|
+
// Action: Version {{{
|
|
38
|
+
if (args.version) {
|
|
39
|
+
console.log(`Version: ${packageInfo.version}`);
|
|
40
|
+
process.exit(0);
|
|
41
|
+
}
|
|
42
|
+
// }}}
|
|
43
|
+
// Action: Convert (if --input) {{{
|
|
44
|
+
if (args.input) {
|
|
45
|
+
if (args.verbose) console.log('Reading', args.input);
|
|
46
|
+
let refs = await reflib.readFile(args.input);
|
|
47
|
+
if (args.verbose) console.log('Read', refs.length, 'refs');
|
|
48
|
+
|
|
49
|
+
if (!args.output) {
|
|
50
|
+
if (args.verbose) console.log('No output file specified - assuming STDOUT JSON');
|
|
51
|
+
console.log(JSON.stringify(refs, null, 2));
|
|
52
|
+
} else if (args.output == '-' || args.output === true) {
|
|
53
|
+
if (!args.format) {
|
|
54
|
+
if (args.verbose) console.log('No STDOUT format specified - assuming JSON');
|
|
55
|
+
console.log(JSON.stringify(refs, null, 2));
|
|
56
|
+
} else {
|
|
57
|
+
if (args.verbose) console.log(`Raw output to STDOUT using "${args.format}" format`);
|
|
58
|
+
|
|
59
|
+
let stream = reflib.writeStream(args.format, process.stdout);
|
|
60
|
+
await stream.start();
|
|
61
|
+
await Array.fromAsync(refs, ref =>
|
|
62
|
+
stream.write(ref)
|
|
63
|
+
);
|
|
64
|
+
await stream.end();
|
|
65
|
+
}
|
|
66
|
+
} else if (args.output) {
|
|
67
|
+
if (args.verbose) console.log('Writing', args.output);
|
|
68
|
+
await reflib.writeFile(args.output, refs);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (args.verbose) console.log('All done');
|
|
72
|
+
process.exit(0);
|
|
73
|
+
}
|
|
74
|
+
// }}}
|
|
75
|
+
// Action: Help {{{
|
|
76
|
+
if (args.help) {
|
|
77
|
+
console.log(help);
|
|
78
|
+
process.exit(0);
|
|
79
|
+
}
|
|
80
|
+
// }}}
|
|
81
|
+
// Action: Unknown {{{
|
|
82
|
+
console.warn('Nothing to do');
|
|
83
|
+
console.log(help);
|
|
84
|
+
process.exit(1);
|
|
85
|
+
// }}}
|
package/package.json
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@iebh/reflib",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.8.0",
|
|
4
4
|
"description": "Reference / Citation reference library utilities",
|
|
5
|
+
"bin": {
|
|
6
|
+
"reflib": "./app.js"
|
|
7
|
+
},
|
|
5
8
|
"scripts": {
|
|
6
9
|
"lint": "eslint",
|
|
7
10
|
"test": "testa",
|
|
@@ -59,6 +62,7 @@
|
|
|
59
62
|
"@momsfriendlydevco/eslint-config": "^2.3.1",
|
|
60
63
|
"@momsfriendlydevco/testa": "^1.1.2",
|
|
61
64
|
"eslint": "^9.31.0",
|
|
65
|
+
"execa": "^9.6.1",
|
|
62
66
|
"nodemon": "^3.1.9",
|
|
63
67
|
"temp": "^0.9.4",
|
|
64
68
|
"vite-plugin-replace": "^0.1.1"
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Attempt to parse an process.argv like array into extracted flags and their values
|
|
3
|
+
*
|
|
4
|
+
* Supported:
|
|
5
|
+
* `--flag` → `true`
|
|
6
|
+
* `--flag val` → `'val'`
|
|
7
|
+
* `--flag a b c` → `['a', 'b', 'c']` (variadic, stops at next flag)
|
|
8
|
+
* `-f` → `true`
|
|
9
|
+
* `-abc` → `{ a: true, b: true, c: true }`
|
|
10
|
+
* `-n 1 2 3` → `{ n: ['1', '2', '3'] }` (last short flag is variadic)
|
|
11
|
+
* `--` → remaining args go to `_`
|
|
12
|
+
* Bare positional args → `_` array
|
|
13
|
+
*
|
|
14
|
+
* @param {Array<String>} [argv=process.argv] `argv` like array to parse, If omitted `process.argv.slice(2)` is used
|
|
15
|
+
* @returns {Object} An object with extracted flags
|
|
16
|
+
*
|
|
17
|
+
* @example Basic argv example
|
|
18
|
+
* parseArgs([
|
|
19
|
+
* '--name', 'Alice', 'Bob', '--verbose', '-n', '42', '-xvf', 'file1', 'file2',
|
|
20
|
+
* ]) //= {
|
|
21
|
+
* _: [],
|
|
22
|
+
* name: ['Alice', 'Bob'],
|
|
23
|
+
* verbose: true,
|
|
24
|
+
* n: '42',
|
|
25
|
+
* x: true,
|
|
26
|
+
* v: true,
|
|
27
|
+
* f: ['file1', 'file2']
|
|
28
|
+
* }
|
|
29
|
+
*/
|
|
30
|
+
export function parse(argv = process.argv.slice(2)) {
|
|
31
|
+
let result = { _: [] }
|
|
32
|
+
let i = 0
|
|
33
|
+
|
|
34
|
+
let collectValues = (args, start) => {
|
|
35
|
+
let values = []
|
|
36
|
+
let j = start
|
|
37
|
+
while (j < args.length && !args[j].startsWith('-')) {
|
|
38
|
+
values.push(args[j++])
|
|
39
|
+
}
|
|
40
|
+
return { values, next: j }
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
while (i < argv.length) {
|
|
44
|
+
let arg = argv[i]
|
|
45
|
+
|
|
46
|
+
if (arg.startsWith('--')) {
|
|
47
|
+
let key = arg.slice(2)
|
|
48
|
+
if (!key) { i++; break } // -- separator
|
|
49
|
+
let { values, next } = collectValues(argv, i + 1)
|
|
50
|
+
result[key] = values.length === 0 ? true
|
|
51
|
+
: values.length === 1 ? values[0]
|
|
52
|
+
: values
|
|
53
|
+
i = next
|
|
54
|
+
} else if (arg.startsWith('-')) {
|
|
55
|
+
let flags = arg.slice(1)
|
|
56
|
+
// Check if last char is the one collecting values
|
|
57
|
+
for (let f = 0; f < flags.length - 1; f++) {
|
|
58
|
+
result[flags[f]] = true
|
|
59
|
+
}
|
|
60
|
+
let lastFlag = flags.at(-1);
|
|
61
|
+
let { values, next } = collectValues(argv, i + 1);
|
|
62
|
+
result[lastFlag] = values.length === 0 ? true
|
|
63
|
+
: values.length === 1 ? values[0]
|
|
64
|
+
: values
|
|
65
|
+
i = next;
|
|
66
|
+
} else {
|
|
67
|
+
result._.push(arg)
|
|
68
|
+
i++
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Remaining after -- go to _
|
|
73
|
+
while (i < argv.length) result._.push(argv[i++])
|
|
74
|
+
|
|
75
|
+
return result
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Accept a parsed args object and expand short-flags into long-flags
|
|
81
|
+
*
|
|
82
|
+
* @param {Object} args Parsed arg object to process
|
|
83
|
+
* @param {Object} argMap Object of `shortFlag:String => longFlag:String` translations to apply
|
|
84
|
+
*
|
|
85
|
+
* @returns {Object} The input `args` object with all short-flags translated to long-flags
|
|
86
|
+
*/
|
|
87
|
+
export function expand(args, argMap) {
|
|
88
|
+
let outArgs = {...args}; // Shallow copy of incoming args object we are going to mutate
|
|
89
|
+
|
|
90
|
+
Object.entries(argMap)
|
|
91
|
+
.filter(([shortFlag]) => args[shortFlag])
|
|
92
|
+
.map(([shortFlag, longFlag]) => {
|
|
93
|
+
outArgs[longFlag] = outArgs[shortFlag];
|
|
94
|
+
delete outArgs[shortFlag];
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
return outArgs;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
export default {
|
|
102
|
+
expand,
|
|
103
|
+
parse,
|
|
104
|
+
}
|