├── logos ├── logo-box-builtby.png └── logo-box-madefor.png ├── .gitignore ├── package.json ├── boring.js ├── CHANGELOG.md ├── test └── test.js └── README.md /logos/logo-box-builtby.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apostrophecms/boring/main/logos/logo-box-builtby.png -------------------------------------------------------------------------------- /logos/logo-box-madefor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apostrophecms/boring/main/logos/logo-box-madefor.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | package-lock.json 2 | npm-debug.log 3 | *.DS_Store 4 | node_modules 5 | # We do not commit CSS, only LESS 6 | public/css/*.css 7 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "boring", 3 | "version": "1.1.1", 4 | "description": "A minimalist command line option parser.", 5 | "main": "boring.js", 6 | "scripts": { 7 | "test": "mocha test/test.js" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "https://github.com/apostrophecms/boring" 12 | }, 13 | "keywords": [ 14 | "minimalist", 15 | "command", 16 | "line", 17 | "options", 18 | "argv", 19 | "boring" 20 | ], 21 | "author": "Apostrophe Technologies, Inc.", 22 | "license": "MIT", 23 | "bugs": { 24 | "url": "https://github.com/apostrophecms/boring/issues" 25 | }, 26 | "homepage": "https://github.com/apostrophecms/boring", 27 | "devDependencies": { 28 | "mocha": "^6.2.0" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /boring.js: -------------------------------------------------------------------------------- 1 | module.exports = function(options) { 2 | options = options || {}; 3 | const args = process.argv.slice(2); 4 | const result = { 5 | _: [] 6 | }; 7 | let optionsEnded = false; 8 | for (let i = 0; (i < args.length); i++) { 9 | if (options.end && (args[i] === '--')) { 10 | optionsEnded = true; 11 | continue; 12 | } 13 | if (!optionsEnded) { 14 | let matches = args[i].match(/^--([^\s\=]+)=(.*)$/); 15 | if (matches) { 16 | result[matches[1]] = matches[2]; 17 | continue; 18 | } 19 | matches = args[i].match(/^--(\S+)$/); 20 | if (matches) { 21 | result[matches[1]] = true; 22 | continue; 23 | } 24 | } 25 | result._.push(args[i]); 26 | } 27 | return result; 28 | }; 29 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## 1.1.1 4 | 5 | * Edits project metadata and README. 6 | 7 | ## 1.1.0 8 | 9 | Added the `end` option, which can be used to indicate that no more named options should be parsed after `--` is encountered, and all remaining arguments should be captured in `argv._`, even if they begin with `--`. The `--` itself is not captured. 10 | 11 | ## 1.0.0 12 | 13 | Official stable release, four years after the "0.1.0" release, which was... well... boring and stable in its own right. 14 | 15 | However, we did fix two things: 16 | 17 | * `const` and `let` used in place of `var`; this is 2019. 18 | * `--uri=mongodb://something?foo=bar` now behaves sensibly, coming through as `argv.uri`. Formerly it was confused by the extra `=` in the query string of the uri. 19 | 20 | We hope you find this as boring as we do. 21 | -------------------------------------------------------------------------------- /test/test.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | 3 | describe('boring', function() { 4 | it('has the expected behavior with no arguments', function() { 5 | process.argv = [ 'ignore', 'ignore' ]; 6 | const argv = require('../boring.js')(); 7 | assert(argv); 8 | assert(argv._); 9 | assert(Array.isArray(argv._)); 10 | assert(argv._.length === 0); 11 | for (const key in argv) { 12 | if (key !== '_') { 13 | assert(false); 14 | } 15 | } 16 | }); 17 | it('has the expected behavior with double-hyphen arguments', function() { 18 | process.argv = [ 'ignore', 'ignore', '--foo', '--bar=whee', '--uri=mongodb://foo@baz/wozzle?something=something' ]; 19 | const argv = require('../boring.js')(); 20 | assert(argv); 21 | assert(argv._); 22 | assert(Array.isArray(argv._)); 23 | assert(argv._.length === 0); 24 | assert(argv.foo === true); 25 | assert(argv.bar === 'whee'); 26 | assert(argv.uri === 'mongodb://foo@baz/wozzle?something=something'); 27 | const valid = { 28 | foo: 1, 29 | bar: 1, 30 | _: 1, 31 | uri: 1 32 | }; 33 | for (const key in argv) { 34 | if (!valid[key]) { 35 | assert(false); 36 | } 37 | } 38 | }); 39 | it('has the expected behavior with positional arguments in addition', function() { 40 | process.argv = [ 'ignore', 'ignore', 'jump', 'sideways', '--foo', '--bar=whee', '--super-cool=totally' ]; 41 | const argv = require('../boring.js')(); 42 | assert(argv); 43 | assert(argv._); 44 | assert(Array.isArray(argv._)); 45 | assert(argv._.length === 2); 46 | assert(argv._[0] === 'jump'); 47 | assert(argv._[1] === 'sideways'); 48 | assert(argv.foo === true); 49 | assert(argv.bar === 'whee'); 50 | assert(argv["super-cool"] === 'totally'); 51 | const valid = { 52 | foo: 1, 53 | bar: 1, 54 | _: 1, 55 | "super-cool": 1 56 | }; 57 | for (const key in argv) { 58 | if (!valid[key]) { 59 | assert(false); 60 | } 61 | } 62 | }); 63 | it('treats arguments after an end marker as positional, even if they start with --', function() { 64 | process.argv = [ 'ignore', 'ignore', 'hello', '--pretty', '--', '--boring' ]; 65 | const argv = require('../boring.js')({ end: true }); 66 | assert(argv.pretty === true); 67 | assert(argv._.length === 2); 68 | assert(argv._[0] === 'hello'); 69 | assert(argv._[1] === '--boring'); 70 | }); 71 | it('does not respect end markers if the end option is not used', function() { 72 | process.argv = [ 'ignore', 'ignore', 'hello', '--pretty', '--', '--boring' ]; 73 | const argv = require('../boring.js')(); 74 | assert(argv.boring === true); 75 | assert(argv.pretty === true); 76 | assert(argv._.length === 2); 77 | assert(argv._[0] === 'hello'); 78 | assert(argv._[1] === '--'); 79 | }); 80 | }); 81 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Boring 2 | 3 | Made for ApostropheCMS 4 | 5 | A command line argument parser without pirates 6 | 7 | ## What you get with Boring 8 | 9 | Input: 10 | 11 | ``` 12 | node app jump sideways --foo --bar=whee --super-cool=totally 13 | ``` 14 | 15 | Response: 16 | 17 | ```javascript 18 | { 19 | _: [ "jump", "sideways"], 20 | foo: true, 21 | bar: "whee", 22 | "super-cool": "totally" 23 | } 24 | ``` 25 | 26 | Notice that parameters without `--`, if any, go into the `_` array. Parameters with `--` become properties in their own right. 27 | 28 | ## How you get it 29 | 30 | ```javascript 31 | const argv = require('boring')({}); 32 | ``` 33 | 34 | The options object is optional. 35 | 36 | ## Options 37 | 38 | ### Passthrough 39 | 40 | It is a common convention to never treat any arguments that appear after a `--` placeholder (by itself) as named options, even if they start with `--`. 41 | 42 | Instead, the remainder are treated as positional arguments, no matter what. 43 | 44 | To get this behavior with Boring, pass the `end: true` option: 45 | 46 | ```javascript 47 | const argv = require('boring')({ 48 | end: true 49 | }); 50 | console.log(argv); 51 | ``` 52 | 53 | Now, when you run this command: 54 | 55 | ```bash 56 | node app hello --pretty -- --boring 57 | ``` 58 | 59 | You will get: 60 | 61 | ```javascript 62 | { 63 | _: [ 'hello', '--boring' ], 64 | pretty: true 65 | } 66 | ``` 67 | 68 | ## What you don't get with boring 69 | 70 | ### Single hyphens: nope 71 | 72 | There is no support for old-fashioned "single-hyphen" options, like: 73 | 74 | ``` 75 | -x 50 76 | ``` 77 | 78 | Or: 79 | 80 | ``` 81 | -h 82 | ``` 83 | 84 | You can't tell which are boolean and which take arguments unless a specification is passed in. And that's not boring enough for us. 85 | 86 | ### Usage messages, strictness, etc.: nope 87 | 88 | These are very simple to implement, and if you're like us, you'd rather do it yourself. 89 | 90 | ## Philosophy 91 | 92 | We have nothing against full-featured, pirate-themed option parsers, which are very nice if you're into that sort of thing. We just find ourselves walking the plank when our options don't follow the pattern of what's easy to validate with piracy. 93 | 94 | This simple module is too dumb to break. 95 | 96 | ## About ApostropheCMS 97 | 98 | Boring was created for use in ApostropheCMS, an open-source content management system built on node.js. If you like Boring you should definitely [check out apostrophecms.org](http://apostrophecms.org). 99 | 100 | ## Support 101 | 102 | Feel free to open issues on [github](http://github.com/apostrophecms/boring). 103 | 104 | 105 | --------------------------------------------------------------------------------