├── .babelrc ├── .gitignore ├── .travis.yml ├── README.md ├── deps ├── Spinner.js ├── assert.js ├── cache.json ├── emoji-by-name.js ├── filter.js ├── fun.js ├── index.js └── matcher.js ├── docs ├── CHANGELOG.md └── resources.md ├── examples └── multispinner.js ├── fuse.js ├── index.js ├── middleware ├── data.js ├── index.js └── text.js ├── modules ├── ansi-escapes │ └── index.js ├── ansi-styles │ └── index.js ├── ansi │ ├── index.js │ └── newlines.js ├── babar │ └── index.js ├── beeper │ └── index.js ├── camel-case │ └── index.js ├── chalk │ ├── index.js │ └── supports-color.js ├── charm │ ├── README.md │ ├── charm-example.js │ ├── index.js │ └── lib │ │ └── encode.js ├── cli-cursor │ ├── README.md │ └── index.js ├── cli-spinners │ ├── cli-spinners.json │ └── index.js ├── cli-table2 │ ├── cell.js │ ├── index.js │ ├── layout-manager.js │ ├── table.js │ └── utils.js ├── color-convert │ ├── README.md │ ├── conversions.js │ ├── index.js │ └── route.js ├── color-name │ └── index.js ├── diff-match-patch │ └── index.js ├── diff │ ├── convert │ │ ├── dmp.js │ │ └── xml.js │ ├── diff │ │ ├── array.js │ │ ├── base.js │ │ ├── character.js │ │ ├── css.js │ │ ├── json.js │ │ ├── line.js │ │ ├── sentence.js │ │ └── word.js │ ├── index.js │ ├── patch │ │ ├── apply.js │ │ ├── create.js │ │ ├── merge.js │ │ └── parse.js │ └── util │ │ ├── array.js │ │ ├── distance-iterator.js │ │ └── params.js ├── diffs │ └── index.js ├── duplexer2 │ └── index.js ├── error-stack-parser │ ├── index.js │ └── stackframe.js ├── escape-string-regexp │ └── index.js ├── esutils │ ├── README.md │ ├── index.js │ └── lib │ │ ├── ast.js │ │ ├── code.js │ │ ├── keyword.js │ │ └── utils.js ├── expose-hidden │ └── index.js ├── figures │ └── index.js ├── fmt-obj │ └── index.js ├── funwithflags │ ├── index.js │ └── utils.js ├── indent-string │ └── index.js ├── index.js ├── inherits │ ├── README.md │ └── index.js ├── inspector-gadget │ ├── README.md │ ├── _package.json │ ├── cleaner │ │ ├── index.js │ │ ├── test.js │ │ └── traverse.js │ ├── index.js │ ├── inspector-gadget.js │ └── inspector.js ├── is-buffer │ └── index.js ├── is-fullwidth-code-point │ └── index.js ├── is-nodejs │ └── index.js ├── is-number │ └── index.js ├── javascript-stringify │ └── index.js ├── kind-of │ └── index.js ├── lodash.clonedeep │ └── index.js ├── lodash.merge │ └── index.js ├── log-symbols │ └── index.js ├── log-update │ └── index.js ├── longest │ └── index.js ├── lpad-align │ └── index.js ├── mimic-fn │ └── index.js ├── multispinner │ ├── README.md │ ├── index.js │ └── lib │ │ ├── constants.js │ │ ├── errs.js │ │ ├── spinners.js │ │ └── validOpts.js ├── nanoseconds │ └── index.js ├── node-notifier │ ├── .eslintrc │ ├── DECISION_FLOW.md │ ├── README.md │ ├── example │ │ ├── advanced.js │ │ ├── coulson.jpg │ │ ├── growl.png │ │ ├── input-example.gif │ │ ├── mac.png │ │ ├── macInput.js │ │ ├── message.js │ │ ├── toaster.js │ │ └── windows.png │ ├── index.js │ ├── lib │ │ ├── checkGrowl.js │ │ └── utils.js │ ├── notifiers │ │ ├── balloon.js │ │ ├── growl.js │ │ ├── notificationcenter.js │ │ ├── notifysend.js │ │ └── toaster.js │ ├── package.json │ ├── test │ │ ├── _test-matchers.js │ │ ├── _test-utils.js │ │ ├── balloon.js │ │ ├── fixture │ │ │ ├── coulson.jpg │ │ │ ├── listAll.txt │ │ │ └── removeAll.txt │ │ ├── growl.js │ │ ├── index.js │ │ ├── notify-send.js │ │ ├── terminal-notifier.js │ │ ├── toaster.js │ │ └── utils.js │ └── vendor │ │ ├── notifu │ │ ├── notifu.exe │ │ └── notifu64.exe │ │ ├── snoreToast │ │ └── SnoreToast.exe │ │ └── terminal-notifier.app │ │ └── Contents │ │ ├── Info.plist │ │ ├── MacOS │ │ └── terminal-notifier │ │ ├── PkgInfo │ │ └── Resources │ │ ├── Terminal.icns │ │ └── en.lproj │ │ ├── Credits.rtf │ │ ├── InfoPlist.strings │ │ └── MainMenu.nib ├── onetime │ └── index.js ├── ora │ └── index.js ├── pretty-format │ ├── index.js │ └── printString.js ├── pretty-time │ ├── index.js │ └── utils.js ├── prettyjson │ ├── index.js │ └── utils.js ├── prettysize │ └── index.js ├── progress │ └── index.js ├── restore-cursor │ └── index.js ├── retro │ ├── examples │ │ ├── client.js │ │ ├── menu.js │ │ ├── server.js │ │ └── simple.js │ ├── index.js │ └── retro.js ├── semver │ ├── README.md │ └── index.js ├── shellwords │ ├── README.md │ └── index.js ├── signal-exit │ ├── README.md │ ├── index.js │ └── signals.js ├── sleepfor │ └── index.js ├── sprintf │ └── index.js ├── string-width │ ├── README.md │ └── index.js ├── strip-ansi │ └── index.js ├── tosource │ └── index.js ├── treeify │ └── index.js ├── visualwidth │ ├── README.md │ └── index.js ├── which │ ├── README.md │ └── index.js └── wrap-ansi │ └── index.js ├── package.json ├── plugins ├── ansi.js ├── bar.js ├── beep.js ├── box.js ├── capture.js ├── chalk.js ├── clear.js ├── diff.js ├── expose.js ├── file.js ├── filter.js ├── flags.js ├── formatter.js ├── highlight.js ├── index.js ├── inspect.js ├── json.js ├── list.js ├── notify.js ├── presets.js ├── pretty.js ├── progress.js ├── quick.js ├── register.js ├── returnVals.js ├── sleep.js ├── sparkly.js ├── spinners.js ├── story.js ├── stringify.js ├── table.js ├── text.js ├── time.js ├── timer.js ├── track.js ├── verbose.js ├── web.js ├── weights.js └── xterm.js ├── rollup.config.js ├── test ├── _bench.js ├── _benchFilter.js ├── _debug.js ├── _emptyMemory.js ├── _old.js ├── boxen.js ├── capturing.js ├── charm.js ├── dept.js ├── diff.js ├── examples.js ├── filter-plus.js ├── filter.js ├── flags.js ├── formatter.js ├── from.js ├── fun.js ├── indent.js ├── isnode.js ├── pretty.js ├── progress.js ├── quick.js ├── slow.js ├── spinner.js ├── spinners-multi.js ├── spinners-ora.js ├── spinners.js ├── split.js ├── strip.js ├── test.js ├── time.js ├── treeify.js ├── treeify2.js └── write.js └── todo ├── Progress.js ├── TODO.md ├── deps-dynamic ├── DynamicDeps.js ├── cache.json ├── config.js ├── dynamicTags.js ├── getDep.js ├── index.js └── tagged.js └── types.ts /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "babel-preset-babili", 4 | [ 5 | "env", 6 | { 7 | "targets": { 8 | "node": "current", 9 | "uglify": true 10 | } 11 | } 12 | ] 13 | ] 14 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .idea 3 | npm-debug.log 4 | dist 5 | .DS_Store 6 | .eslintcache 7 | built 8 | tmp 9 | _tmp 10 | lerna-debug.log 11 | .tmp 12 | .happypack 13 | .fusebox 14 | .flipbox 15 | yarn.lock 16 | build 17 | 18 | playground 19 | #!playground 20 | #playground 21 | yuge 22 | public 23 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "7" 4 | 5 | sudo: required 6 | dist: trusty 7 | 8 | install: 9 | - npm install 10 | - npm run test 11 | -------------------------------------------------------------------------------- /deps/Spinner.js: -------------------------------------------------------------------------------- 1 | // const {Spinner} = require('cli-spinner') 2 | const readline = require('readline') 3 | 4 | module.exports = class Spinner { 5 | constructor(options) { 6 | this.text = '' 7 | this.title = '' 8 | this.chars = '⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏' 9 | this.stream = process.stdout 10 | this.delay = 60 11 | if (typeof options === 'string') { 12 | options = {text: options} 13 | } 14 | else if (!options) { 15 | options = {} 16 | } 17 | 18 | if (options.chars) this.chars = options.chars 19 | if (options.text) this.text = options.text 20 | if (options.onTick) this.onTick = options.onTick 21 | if (options.stream) this.stream = options.stream 22 | if (options.title) this.title = options.title 23 | if (options.delay) this.delay = options.delay 24 | } 25 | 26 | start() { 27 | let current = 0 28 | this.id = setInterval(() => { 29 | let msg = this.chars[current] + ' ' + this.text 30 | if (this.text.includes('%s')) { 31 | msg = this.text.replace('%s', this.chars[current]) 32 | } 33 | 34 | this.onTick(msg) 35 | current = ++current % this.chars.length 36 | }, this.delay) 37 | } 38 | 39 | stop(clear) { 40 | clearInterval(this.id) 41 | this.id = undefined 42 | if (clear) { 43 | this.clearLine(this.stream) 44 | } 45 | } 46 | 47 | isSpinning() { 48 | return this.id !== undefined 49 | } 50 | 51 | onTick(msg) { 52 | this.clearLine(this.stream) 53 | this.stream.write(msg) 54 | return this 55 | } 56 | 57 | clearLine(stream) { 58 | readline.clearLine(stream, 0) 59 | readline.cursorTo(stream, 0) 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /deps/assert.js: -------------------------------------------------------------------------------- 1 | const dotProp = require('dot-prop') 2 | 3 | // https://github.com/avajs/ava/pull/1154/files 4 | // https://github.com/avajs/ava/blob/dfca2d9a24e7ee4a12102a8976b89380dde74d4b/lib/assert.js 5 | // 6 | // When adding patterns, don't forget to add to 7 | // https://github.com/avajs/babel-preset-transform-test-files/blob/master/espower-patterns.json 8 | // Then release a new version of that preset and bump the SemVer range here. 9 | const PATTERNS = [ 10 | 't.truthy(value, [message])', 11 | 't.falsy(value, [message])', 12 | 't.true(value, [message])', 13 | 't.false(value, [message])', 14 | 't.is(value, expected, [message])', 15 | 't.not(value, expected, [message])', 16 | 't.regex(contents, regex, [message])', 17 | 't.notRegex(contents, regex, [message])', 18 | ] 19 | 20 | const NON_ENHANCED_PATTERNS = [ 21 | 't.pass([message])', 22 | 't.fail([message])', 23 | 't.throws(fn, [message])', 24 | 't.notThrows(fn, [message])', 25 | 't.ifError(error, [message])', 26 | 't.snapshot(contents, [message])', 27 | 't.is(value, expected, [message])', 28 | 't.not(value, expected, [message])', 29 | 't.deepEqual(value, expected, [message])', 30 | 't.notDeepEqual(value, expected, [message])', 31 | ] 32 | 33 | const enhanceAssert = opts => { 34 | const empower = require('empower-core') 35 | const enhanced = empower(opts.assert, { 36 | destructive: false, 37 | onError: opts.onError, 38 | onSuccess: opts.onSuccess, 39 | patterns: PATTERNS, 40 | wrapOnlyPatterns: NON_ENHANCED_PATTERNS, 41 | bindReceiver: false, 42 | }) 43 | 44 | return enhanced 45 | } 46 | 47 | const isRangeMatch = (a, b) => { 48 | return ( 49 | (a[0] === b[0] && a[1] === b[1]) || 50 | (a[0] > b[0] && a[0] < b[1]) || 51 | (a[1] > b[0] && a[1] < b[1]) 52 | ) 53 | } 54 | 55 | const computeStatement = (tokens, range) => { 56 | return tokens 57 | .filter(token => isRangeMatch(token.range, range)) 58 | .map(token => (token.value === undefined ? token.type.label : token.value)) 59 | .join('') 60 | } 61 | 62 | const getNode = (ast, path) => dotProp.get(ast, path.replace(/\//g, '.')) 63 | 64 | const formatter = () => { 65 | return context => { 66 | const ast = JSON.parse(context.source.ast) 67 | const tokens = JSON.parse(context.source.tokens) 68 | const args = context.args[0].events 69 | 70 | return args 71 | .map(arg => { 72 | const range = getNode(ast, arg.espath).range 73 | 74 | return [computeStatement(tokens, range), arg.value] 75 | }) 76 | .reverse() 77 | } 78 | } 79 | 80 | module.exports = enhanceAssert 81 | module.exports.PATTERNS = PATTERNS 82 | module.exports.NON_ENHANCED_PATTERNS = NON_ENHANCED_PATTERNS 83 | module.exports.formatter = formatter 84 | -------------------------------------------------------------------------------- /deps/cache.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /deps/emoji-by-name.js: -------------------------------------------------------------------------------- 1 | const byName = { 2 | preset: '🍰', 3 | step: '👣', 4 | fusebox: '💣🛅', 5 | webpack: '🕸🛅', 6 | rollup: '🗞️🛅', 7 | babel: '🗼', 8 | neutrino: '🇳🕸', 9 | plugin: '🔌', 10 | alias: '🏹', 11 | factory: '🏭', 12 | chain: '⛓', 13 | fancy: '🎩', 14 | safety: '🛡', 15 | deps: '📦', 16 | util: '🖇', 17 | logUp: '🔈', 18 | logDown: '🔇', 19 | logNo: '🙊', 20 | save: '💾', 21 | validate: '🛂', 22 | script: '📜', 23 | filter: '☕', 24 | whitelist: '🏳️', 25 | blacklist: '🏴', 26 | flag: '🚩', 27 | vanilla: '🍦', 28 | trick: '🎃', 29 | lint: '👕', 30 | phone: '📞', 31 | gear: '⚙', 32 | config: '⚙', 33 | color: '🎨', 34 | done: '☑️', 35 | scale: '⚖️️', 36 | loader: '🏋', 37 | pub: '📢', 38 | sub: '👂', 39 | file: '📒', 40 | map: '🗺', 41 | api: '🌐', 42 | trash: '🗑', 43 | perf: '⚡', 44 | find: '🔎', 45 | tool: '🔧', 46 | sugar: '🍬', 47 | timeStart: '⌛', 48 | timeEnd: '⏳', 49 | timer: '⏲', 50 | run: '🏃', 51 | serve: '🤾', 52 | split: '🤸', 53 | car: '🏎️', 54 | cache: '💸', 55 | info: 'ℹ️️', 56 | fix: '⚒️', 57 | cut: '✂️', 58 | dials: '🎛', 59 | slider: '🎚', 60 | up: '⬆', 61 | down: '⬇', 62 | flip: '🏗', 63 | test: '🔬', 64 | target: '🎯', 65 | fire: '👨‍🔧', 66 | add: '➕', 67 | remove: '❌', 68 | data: '🐘', 69 | x: '✖️', 70 | no: '🚫', 71 | model: '🗽', 72 | undo: '↩️', 73 | redo: '↪️', 74 | tree: '🌲', 75 | crown: '👑', 76 | cli: '🖥', 77 | hole: '🕳', 78 | num: '🔢', 79 | letter: '🔤', 80 | caps: '🔠', 81 | symbol: '🔣', 82 | key: '🗝️', 83 | wave: '👋', 84 | battery: '🔋', 85 | view: '👀', 86 | link: '🔗', 87 | simplify: '👾', 88 | todo: '📝', 89 | docs: '📚', 90 | snail: '🐌', 91 | lock: '🔒', 92 | unlock: '🔓', 93 | window: '🖼️', 94 | graph: '📊', 95 | rocket: '🚀', 96 | freeze: '❄️', 97 | promise: '💍', 98 | wip: '🚧', 99 | story: '📓', 100 | measure: '📐', 101 | baby: '🚼', 102 | ship: '⛴', 103 | meta: '📇', 104 | loop: '🔁', 105 | magic: '🔮', 106 | pin: '📌', 107 | hub: '💠', 108 | anim: '🌀', 109 | merge: '▶️◀️', 110 | bug: '🐛', 111 | leak: '🚱', 112 | experiment: '⚗', 113 | abstract: '♻️', 114 | nest: '🐣', 115 | architecture: '🏛️', 116 | structure: '🏰', 117 | } 118 | module.exports = function emoji(name) { 119 | return byName[name] 120 | } 121 | -------------------------------------------------------------------------------- /deps/fun.js: -------------------------------------------------------------------------------- 1 | function random(min, max) { 2 | // eslint-disable-next-line no-mixed-operators 3 | return Math.floor(Math.random() * (max - min + 1) + min) 4 | } 5 | function shuffle(a) { 6 | for (let i = a.length; i; i--) { 7 | let j = Math.floor(Math.random() * i) 8 | ;[a[i - 1], a[j]] = [a[j], a[i - 1]] 9 | } 10 | return a 11 | } 12 | function chance() { 13 | return random(0, 10) > 5 14 | } 15 | 16 | module.exports = {random, shuffle, chance} 17 | -------------------------------------------------------------------------------- /deps/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @tutorial https://github.com/lukeed/obj-str 3 | * @param {Object} obj 4 | * @return {string} 5 | */ 6 | function objToStr(obj) { 7 | let cls = '' 8 | for (const k in obj) { 9 | if (obj[k]) { 10 | cls && (cls += ' ') 11 | cls += k 12 | } 13 | } 14 | return cls 15 | } 16 | 17 | // https://github.com/npm/npmlog 18 | // http://tostring.it/2014/06/23/advanced-logging-with-nodejs/ 19 | // http://www.100percentjs.com/best-way-debug-node-js/ 20 | // https://www.loggly.com/ultimate-guide/node-logging-basics/ 21 | // https://www.npmjs.com/package/cli-color 22 | const clrs = [ 23 | 'black', 24 | 'green', 25 | 'yellow', 26 | 'blue', 27 | 'magenta', 28 | 'cyan', 29 | 'white', 30 | 'gray', 31 | 'red', 32 | 'dim', 33 | ] 34 | const bgColors = [ 35 | 'bgBlack', 36 | 'bgRed', 37 | 'bgGreen', 38 | 'bgYellow', 39 | 'bgBlue', 40 | 'bgMagenta', 41 | 'bgCyan', 42 | 'bgWhite', 43 | ] 44 | const em = ['italic', 'bold', 'underline'] 45 | const xtermByName = { 46 | colors: { 47 | orange: 202, 48 | }, 49 | bg: { 50 | orange: 236, 51 | }, 52 | } 53 | // const psr3 = [ 54 | // 'emergency', 55 | // 'alert', 56 | // 'critical', 57 | // 'error', 58 | // 'warning', 59 | // 'notice', 60 | // 'warning', 61 | // 'debug', 62 | // ] 63 | 64 | const combinations = clrs.concat(bgColors).concat(em) 65 | 66 | // https://www.youtube.com/watch?v=SwSle66O5sU 67 | const OFF = `${~315 >>> 3}@@` 68 | 69 | const isFunctionWithNoKeys = obj => 70 | typeof obj === 'function' && Object.keys(obj).length === 0 71 | 72 | const matcher = require('./matcher') 73 | 74 | module.exports = { 75 | matcher, 76 | isFunctionWithNoKeys, 77 | combinations, 78 | OFF, 79 | bgColors, 80 | // psr3, 81 | xtermByName, 82 | objToStr, 83 | } 84 | -------------------------------------------------------------------------------- /deps/matcher.js: -------------------------------------------------------------------------------- 1 | // https://github.com/sindresorhus/matcher/blob/master/index.js 2 | const toArr = x => [].concat(x) 3 | const escapeStringRegexp = str => str.replace(/[|\\{}()[\]^$+*?.]/g, '\\$&') 4 | const toRegExp = str => escapeStringRegexp(str).replace(/\\\*/g, '.*') 5 | const isFunction = x => typeof x === 'function' || x instanceof Function 6 | const isRegExp = x => x instanceof RegExp 7 | 8 | // @TODO: default strings without slashes to node_modules, if that is best 9 | const reCache = new Map() 10 | 11 | function map(patterns, shouldNegate, beginningEnd = false) { 12 | return toArr(patterns).map(pattern => 13 | makeRe(pattern, shouldNegate, beginningEnd) 14 | ) 15 | } 16 | function makeRe(pattern, shouldNegate, beginningEnd = false) { 17 | const cacheKey = pattern + shouldNegate 18 | if (reCache.has(cacheKey)) return reCache.get(cacheKey) 19 | 20 | // @NOTE: added for function callbacks 21 | if (isFunction(pattern) && !pattern.test) pattern.test = pattern 22 | if (isFunction(pattern) || isRegExp(pattern)) return pattern 23 | 24 | let negated = pattern[0] === '!' 25 | if (negated) pattern = pattern.slice(1) 26 | 27 | pattern = toRegExp(pattern) 28 | 29 | if (negated && shouldNegate) pattern = `(?!${pattern})` 30 | let re = new RegExp(`${pattern}`, 'i') 31 | if (beginningEnd === true) re = new RegExp(`^${pattern}$`, 'i') 32 | 33 | re.negated = negated 34 | reCache.set(cacheKey, re) 35 | 36 | return re 37 | } 38 | 39 | const matcher = (inputs, patterns) => { 40 | if (!(Array.isArray(inputs) && Array.isArray(patterns))) { 41 | throw new TypeError( 42 | `Expected two arrays, got ${typeof inputs} ${typeof patterns}` 43 | ) 44 | } 45 | 46 | if (patterns.length === 0) return inputs 47 | const firstNegated = patterns[0][0] === '!' 48 | const matchesToReturn = [] 49 | patterns = patterns.map(x => makeRe(x, false)) 50 | 51 | inputs.forEach(input => { 52 | // If first pattern is negated we include everything to match user expectation 53 | let matches = firstNegated 54 | 55 | // TODO: Figure out why tests fail when I use a for-of loop here 56 | for (let j = 0; j < patterns.length; j++) { 57 | if (patterns[j].test(input)) { 58 | matches = !patterns[j].negated 59 | } 60 | } 61 | 62 | if (matches) matchesToReturn.push(input) 63 | }) 64 | 65 | return matchesToReturn 66 | } 67 | 68 | const isMatch = (input, pattern, negate = false, beginningEnd = false) => 69 | map(pattern, negate, beginningEnd).map(fn => fn.test(input)) 70 | 71 | const isMatchCurry = (pattern, negate = false, beginningEnd = false) => input => 72 | matcher(input, map(pattern, negate, beginningEnd)) 73 | 74 | module.exports = matcher 75 | module.exports.isMatch = isMatch 76 | module.exports.isMatchCurry = isMatchCurry 77 | module.exports.makeRe = makeRe 78 | module.exports.matcher = matcher 79 | module.exports.map = map 80 | -------------------------------------------------------------------------------- /docs/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # 🔊 changelog 🔊 2 | 3 | ## 0.3.0 4 | - soon to be 1.0.0 5 | - removed all but 1 external dep, inlined 6 | - 👾💄 simplify and prettier the diffing 7 | - 🆕 start web specific features plugin 8 | - 🤸 split echo into 3 functions 9 | - add scoped (scope instances to string names) 10 | - 🏭 add factory 11 | - 🗑 clean out dynamic deps for now 12 | - ⛓ use chain-able 13 | - 🛁 add the cleaner 14 | - 🎁💄 pretty format 15 | 16 | ## 0.2.0 17 | #### 0.2.6 18 | - removed microtime dep 19 | 20 | #### 0.2.5 21 | - added fmtobj 22 | -------------------------------------------------------------------------------- /docs/resources.md: -------------------------------------------------------------------------------- 1 | // http://stackoverflow.com/questions/26675055/nodejs-parse-process-stdout-to-a-variable 2 | // https://github.com/ariya/phantomjs/issues/10980 3 | // https://nodejs.org/api/process.html#process_process_stdout 4 | // https://developer.mozilla.org/en-US/docs/Web/API/Console/table 5 | // https://github.com/Automattic/cli-table 6 | -------------------------------------------------------------------------------- /examples/multispinner.js: -------------------------------------------------------------------------------- 1 | const log = require('../') 2 | 3 | log 4 | .addSpinner('key2', 'spinner 2 msg') 5 | .addSpinner('key3', 'spinner 3 msg') 6 | .startSpinners() 7 | -------------------------------------------------------------------------------- /fuse.js: -------------------------------------------------------------------------------- 1 | const { 2 | FuseBox, 3 | OptimisedBundlePlugin, 4 | BabelPlugin, 5 | JSONPlugin, 6 | UglifyJSPlugin, 7 | } = require('fsbx') 8 | 9 | let fuse = new FuseBox({ 10 | homeDir: __dirname, 11 | sourcemaps: true, 12 | output: 'disted/$name.js', 13 | cache: false, 14 | log: true, 15 | debug: true, 16 | plugins: [ 17 | JSONPlugin(), 18 | [BabelPlugin(), UglifyJSPlugin()], 19 | // OptimisedBundlePlugin(), 20 | ], 21 | }) 22 | 23 | // fuse.dev() 24 | fuse 25 | .bundle('fliplog') 26 | .target('server') 27 | .instructions( 28 | `[index.js] +[modules/**/*.js] +[deps/**/*.js] +[plugins/**/*.js] +[middleware/**/*.js]` 29 | ) 30 | 31 | fuse.run() 32 | -------------------------------------------------------------------------------- /middleware/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | data: require('./data'), 3 | text: require('./text'), 4 | } 5 | -------------------------------------------------------------------------------- /modules/ansi-escapes/index.js: -------------------------------------------------------------------------------- 1 | // https://github.com/sindresorhus/ansi-escapes/blob/master/index.js 2 | const x = module.exports 3 | const ESC = '\u001B[' 4 | const isTerminalApp = process.env.TERM_PROGRAM === 'Apple_Terminal' 5 | 6 | x.cursorTo = function(x, y) { 7 | if (arguments.length === 0) { 8 | return ESC + 'H' 9 | } 10 | 11 | if (arguments.length === 1) { 12 | return ESC + (x + 1) + 'G' 13 | } 14 | 15 | return ESC + (y + 1) + ';' + (x + 1) + 'H' 16 | } 17 | 18 | x.cursorMove = (x, y) => { 19 | let ret = '' 20 | 21 | if (x < 0) { 22 | ret += ESC + (-x) + 'D' 23 | } 24 | else if (x > 0) { 25 | ret += ESC + x + 'C' 26 | } 27 | 28 | if (y < 0) { 29 | ret += ESC + (-y) + 'A' 30 | } 31 | else if (y > 0) { 32 | ret += ESC + y + 'B' 33 | } 34 | 35 | return ret 36 | } 37 | 38 | x.cursorUp = count => ESC + (typeof count === 'number' ? count : 1) + 'A' 39 | x.cursorDown = count => ESC + (typeof count === 'number' ? count : 1) + 'B' 40 | x.cursorForward = count => ESC + (typeof count === 'number' ? count : 1) + 'C' 41 | x.cursorBackward = count => ESC + (typeof count === 'number' ? count : 1) + 'D' 42 | 43 | x.cursorLeft = ESC + 'G' 44 | x.cursorSavePosition = ESC + (isTerminalApp ? '7' : 's') 45 | x.cursorRestorePosition = ESC + (isTerminalApp ? '8' : 'u') 46 | x.cursorGetPosition = ESC + '6n' 47 | x.cursorNextLine = ESC + 'E' 48 | x.cursorPrevLine = ESC + 'F' 49 | x.cursorHide = ESC + '?25l' 50 | x.cursorShow = ESC + '?25h' 51 | 52 | x.eraseLines = count => { 53 | let clear = '' 54 | 55 | for (let i = 0; i < count; i++) { 56 | clear += x.eraseLine + (i < count - 1 ? x.cursorUp() : '') 57 | } 58 | 59 | if (count) { 60 | clear += x.cursorLeft 61 | } 62 | 63 | return clear 64 | } 65 | 66 | x.eraseEndLine = ESC + 'K' 67 | x.eraseStartLine = ESC + '1K' 68 | x.eraseLine = ESC + '2K' 69 | x.eraseDown = ESC + 'J' 70 | x.eraseUp = ESC + '1J' 71 | x.eraseScreen = ESC + '2J' 72 | x.scrollUp = ESC + 'S' 73 | x.scrollDown = ESC + 'T' 74 | 75 | x.clearScreen = '\u001Bc' 76 | x.beep = '\u0007' 77 | 78 | x.image = (buf, opts) => { 79 | opts = opts || {} 80 | 81 | let ret = '\u001B]1337;File=inline=1' 82 | 83 | if (opts.width) { 84 | ret += `;width=${opts.width}` 85 | } 86 | 87 | if (opts.height) { 88 | ret += `;height=${opts.height}` 89 | } 90 | 91 | if (opts.preserveAspectRatio === false) { 92 | ret += ';preserveAspectRatio=0' 93 | } 94 | 95 | return ret + ':' + buf.toString('base64') + '\u0007' 96 | } 97 | 98 | x.iTerm = {} 99 | 100 | x.iTerm.setCwd = cwd => '\u001B]50;CurrentDir=' + (cwd || process.cwd()) + '\u0007' 101 | -------------------------------------------------------------------------------- /modules/ansi/newlines.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Accepts any node Stream instance and hijacks its "write()" function, 3 | * so that it can count any newlines that get written to the output. 4 | * 5 | * When a '\n' byte is encountered, then a "newline" event will be emitted 6 | * on the stream, with no arguments. It is up to the listeners to determine 7 | * any necessary deltas required for their use-case. 8 | * 9 | * Ex: 10 | * 11 | * var cursor = ansi(process.stdout) 12 | * , ln = 0 13 | * process.stdout.on('newline', function () { 14 | * ln++ 15 | * }) 16 | */ 17 | 18 | /** 19 | * Module dependencies. 20 | */ 21 | 22 | var assert = require('assert') 23 | var NEWLINE = '\n'.charCodeAt(0) 24 | 25 | function emitNewlineEvents(stream) { 26 | if (stream._emittingNewlines) { 27 | // already emitting newline events 28 | return 29 | } 30 | 31 | var write = stream.write 32 | 33 | stream.write = function(data) { 34 | // first write the data 35 | var rtn = write.apply(stream, arguments) 36 | 37 | if (stream.listeners('newline').length > 0) { 38 | var len = data.length, i = 0 39 | // now try to calculate any deltas 40 | if (typeof data === 'string') { 41 | for (; i < len; i++) { 42 | processByte(stream, data.charCodeAt(i)) 43 | } 44 | } 45 | else { 46 | // buffer 47 | for (; i < len; i++) { 48 | processByte(stream, data[i]) 49 | } 50 | } 51 | } 52 | 53 | return rtn 54 | } 55 | 56 | stream._emittingNewlines = true 57 | } 58 | module.exports = emitNewlineEvents 59 | 60 | /** 61 | * Processes an individual byte being written to a stream 62 | */ 63 | 64 | function processByte(stream, b) { 65 | assert.equal(typeof b, 'number') 66 | if (b === NEWLINE) { 67 | stream.emit('newline') 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /modules/beeper/index.js: -------------------------------------------------------------------------------- 1 | // https://github.com/sindresorhus/beeper/blob/master/index.js 2 | var BEEP_DELAY = 500 3 | 4 | function beep() { 5 | process.stdout.write('\u0007') 6 | } 7 | 8 | function melodicalBeep(val, cb) { 9 | if (val.length === 0) { 10 | cb() 11 | return 12 | } 13 | 14 | setTimeout(() => { 15 | if (val.shift() === '*') { 16 | beep() 17 | } 18 | 19 | melodicalBeep(val, cb) 20 | }, BEEP_DELAY) 21 | } 22 | 23 | module.exports = function(val, cb) { 24 | if ( 25 | !process.stdout.isTTY || 26 | process.argv.indexOf('--no-beep') !== -1 || 27 | process.argv.indexOf('--beep=false') !== -1 28 | ) { 29 | return 30 | } 31 | 32 | cb = cb || function() {} 33 | 34 | if (val === parseInt(val)) { 35 | if (val < 0) { 36 | throw new TypeError('Negative numbers are not accepted') 37 | } 38 | 39 | if (val === 0) { 40 | cb() 41 | return 42 | } 43 | 44 | for (var i = 0; i < val; i++) { 45 | setTimeout( 46 | i => { 47 | beep() 48 | 49 | if (i === val - 1) { 50 | cb() 51 | } 52 | }, 53 | BEEP_DELAY * i, 54 | i 55 | ) 56 | } 57 | } 58 | else if (!val) { 59 | beep() 60 | cb() 61 | } 62 | else if (typeof val === 'string') { 63 | melodicalBeep(val.split(''), cb) 64 | } 65 | else { 66 | throw new TypeError('Not an accepted type') 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /modules/camel-case/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @tutorial http://stackoverflow.com/questions/2970525/converting-any-string-into-camel-case 3 | * @tutorial https://github.com/sindresorhus/camelcase 4 | * @param {string} str 5 | * @return {string} 6 | * 7 | * s.charAt(0).toLowerCase() + string.slice(1) 8 | */ 9 | function camelCase(str) { 10 | return str 11 | .replace(/(?:^\w|[A-Z]|\b\w|\s+)/g, (match, index) => { 12 | if (+match === 0) return '' // or if (/\s+/.test(match)) for white spaces 13 | 14 | // needs to be a loose 0 or first char will be uc if first char is - 15 | // eslint-disable-next-line 16 | return index == 0 ? match.toLowerCase() : match.toUpperCase() 17 | }) 18 | .replace(/[-_]/g, '') 19 | } 20 | 21 | /** 22 | * @desc this duplicates keys, is simplest fastest 23 | * @NOTE mutates obj 24 | * @param {Object} obj 25 | * @return {Object} 26 | */ 27 | function camelCaseKeys(obj) { 28 | const keys = Object.keys(obj) 29 | const camelKeys = keys.map(camelCase) 30 | for (let i = 0; i < keys.length; i++) { 31 | const camel = camelKeys[i] 32 | // console.log({camel, camelKeys, i, keys, c: camelKeys[i], k: keys[i]}) 33 | if (camel.length === 0) continue 34 | obj[camel] = obj[keys[i]] 35 | } 36 | return obj 37 | } 38 | 39 | camelCase.keys = camelCaseKeys 40 | camelCase.str = camelCase 41 | module.exports = camelCase 42 | -------------------------------------------------------------------------------- /modules/chalk/supports-color.js: -------------------------------------------------------------------------------- 1 | const env = process.env 2 | 3 | const support = level => { 4 | if (level === 0) { 5 | return false 6 | } 7 | 8 | return { 9 | level, 10 | hasBasic: true, 11 | has256: level >= 2, 12 | has16m: level >= 3, 13 | } 14 | } 15 | 16 | let supportLevel = (() => { 17 | // if (hasFlag('no-color') || hasFlag('no-colors') || hasFlag('color=false')) { 18 | // return 0 19 | // } 20 | // 21 | // if ( 22 | // hasFlag('color=16m') || 23 | // hasFlag('color=full') || 24 | // hasFlag('color=truecolor') 25 | // ) { 26 | // return 3 27 | // } 28 | // 29 | // if (hasFlag('color=256')) { 30 | // return 2 31 | // } 32 | // 33 | // if ( 34 | // hasFlag('color') || 35 | // hasFlag('colors') || 36 | // hasFlag('color=true') || 37 | // hasFlag('color=always') 38 | // ) { 39 | // return 1 40 | // } 41 | 42 | if (process.stdout && !process.stdout.isTTY) { 43 | return 0 44 | } 45 | 46 | if (process.platform === 'win32') { 47 | return 1 48 | } 49 | 50 | if ('CI' in env) { 51 | if ('TRAVIS' in env || env.CI === 'Travis') { 52 | return 1 53 | } 54 | 55 | return 0 56 | } 57 | 58 | if ('TEAMCITY_VERSION' in env) { 59 | return (/^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/).test(env.TEAMCITY_VERSION) ? 1 : 0 60 | } 61 | 62 | if ('TERM_PROGRAM' in env) { 63 | const version = parseInt((env.TERM_PROGRAM_VERSION || '').split('.')[0], 10) 64 | 65 | switch (env.TERM_PROGRAM) { 66 | case 'iTerm.app': 67 | return version >= 3 ? 3 : 2 68 | case 'Hyper': 69 | return 3 70 | case 'Apple_Terminal': 71 | return 2 72 | // no default 73 | } 74 | } 75 | 76 | if (/^(screen|xterm)-256(?:color)?/.test(env.TERM)) { 77 | return 2 78 | } 79 | 80 | if (/^screen|^xterm|^vt100|color|ansi|cygwin|linux/i.test(env.TERM)) { 81 | return 1 82 | } 83 | 84 | if ('COLORTERM' in env) { 85 | return 1 86 | } 87 | 88 | if (env.TERM === 'dumb') { 89 | return 0 90 | } 91 | 92 | return 0 93 | })() 94 | 95 | // if ('FORCE_COLOR' in env) { 96 | // supportLevel = parseInt(env.FORCE_COLOR, 10) === 0 ? 0 : supportLevel || 1 97 | // } 98 | module.exports = process && support(supportLevel) 99 | -------------------------------------------------------------------------------- /modules/charm/README.md: -------------------------------------------------------------------------------- 1 | used by retro 2 | -------------------------------------------------------------------------------- /modules/charm/charm-example.js: -------------------------------------------------------------------------------- 1 | var charm = require('./charm')() 2 | charm.pipe(process.stdout) 3 | charm.reset() 4 | 5 | var colors = ['red', 'cyan', 'yellow', 'green', 'blue'] 6 | var text = 'Always after me lucky charms.' 7 | 8 | var offset = 0 9 | var iv = setInterval(() => { 10 | var y = 0, dy = 1 11 | for (var i = 0; i < 40; i++) { 12 | var color = colors[(i + offset) % colors.length] 13 | var c = text[(i + offset) % text.length] 14 | charm.move(1, dy).foreground(color).write(c) 15 | 16 | y += dy 17 | if (y <= 0 || y >= 5) dy *= -1 18 | } 19 | charm.position(0, 1) 20 | offset++ 21 | }, 150) 22 | -------------------------------------------------------------------------------- /modules/charm/lib/encode.js: -------------------------------------------------------------------------------- 1 | var encode = (module.exports = function(xs) { 2 | function bytes(s) { 3 | if (typeof s === 'string') { 4 | return s.split('').map(ord) 5 | } 6 | else if (Array.isArray(s)) { 7 | return s.reduce((acc, c) => { 8 | return acc.concat(bytes(c)) 9 | }, []) 10 | } 11 | } 12 | 13 | return new Buffer([0x1b].concat(bytes(xs))) 14 | }) 15 | 16 | var ord = (encode.ord = function ord(c) { 17 | return c.charCodeAt(0) 18 | }) 19 | -------------------------------------------------------------------------------- /modules/cli-cursor/README.md: -------------------------------------------------------------------------------- 1 | used by chalk & progress 2 | -------------------------------------------------------------------------------- /modules/cli-cursor/index.js: -------------------------------------------------------------------------------- 1 | const restoreCursor = require('../restore-cursor') 2 | 3 | let hidden = false 4 | 5 | exports.show = stream => { 6 | const s = stream || process.stderr 7 | 8 | if (!s.isTTY) { 9 | return 10 | } 11 | 12 | hidden = false 13 | s.write('\u001b[?25h') 14 | } 15 | 16 | exports.hide = stream => { 17 | const s = stream || process.stderr 18 | 19 | if (!s.isTTY) { 20 | return 21 | } 22 | 23 | restoreCursor() 24 | hidden = true 25 | s.write('\u001b[?25l') 26 | } 27 | 28 | exports.toggle = (force, stream) => { 29 | if (force !== undefined) { 30 | hidden = force 31 | } 32 | 33 | if (hidden) { 34 | exports.show(stream) 35 | } 36 | else { 37 | exports.hide(stream) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /modules/cli-spinners/index.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./cli-spinners.json') 2 | -------------------------------------------------------------------------------- /modules/cli-table2/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fliphub/fliplog/b0a1581e749a41ab65731f88cc90f2c24d20247d/modules/cli-table2/index.js -------------------------------------------------------------------------------- /modules/cli-table2/table.js: -------------------------------------------------------------------------------- 1 | var utils = require('./utils') 2 | var tableLayout = require('./layout-manager') 3 | 4 | function Table(options) { 5 | this.options = utils.mergeOptions(options) 6 | } 7 | 8 | Table.prototype.__proto__ = Array.prototype 9 | 10 | Table.prototype.toString = function() { 11 | var array = this 12 | var headersPresent = this.options.head && this.options.head.length 13 | if (headersPresent) { 14 | array = [this.options.head] 15 | if (this.length) { 16 | array.push.apply(array, this) 17 | } 18 | } 19 | else { 20 | this.options.style.head = [] 21 | } 22 | 23 | var cells = tableLayout.makeTableLayout(array) 24 | 25 | cells.forEach(function(row) { 26 | row.forEach(function(cell) { 27 | cell.mergeTableOptions(this.options, cells) 28 | }, this) 29 | }, this) 30 | 31 | tableLayout.computeWidths(this.options.colWidths, cells) 32 | tableLayout.computeHeights(this.options.rowHeights, cells) 33 | 34 | cells.forEach(function(row, rowIndex) { 35 | row.forEach(function(cell, cellIndex) { 36 | cell.init(this.options) 37 | }, this) 38 | }, this) 39 | 40 | var result = [] 41 | 42 | for (var rowIndex = 0; rowIndex < cells.length; rowIndex++) { 43 | var row = cells[rowIndex] 44 | var heightOfRow = this.options.rowHeights[rowIndex] 45 | 46 | if ( 47 | rowIndex === 0 || 48 | !this.options.style.compact || 49 | (rowIndex == 1 && headersPresent) 50 | ) { 51 | doDraw(row, 'top', result) 52 | } 53 | 54 | for (var lineNum = 0; lineNum < heightOfRow; lineNum++) { 55 | doDraw(row, lineNum, result) 56 | } 57 | 58 | if (rowIndex + 1 == cells.length) { 59 | doDraw(row, 'bottom', result) 60 | } 61 | } 62 | 63 | return result.join('\n') 64 | } 65 | 66 | function doDraw(row, lineNum, result) { 67 | var line = [] 68 | row.forEach(cell => { 69 | line.push(cell.draw(lineNum)) 70 | }) 71 | var str = line.join('') 72 | if (str.length) result.push(str) 73 | } 74 | 75 | Table.prototype.__defineGetter__('width', function() { 76 | var str = this.toString().split('\n') 77 | return str[0].length 78 | }) 79 | 80 | module.exports = Table 81 | -------------------------------------------------------------------------------- /modules/color-convert/README.md: -------------------------------------------------------------------------------- 1 | https://github.com/qix-/color-convert 2 | -------------------------------------------------------------------------------- /modules/color-convert/index.js: -------------------------------------------------------------------------------- 1 | var conversions = require('./conversions') 2 | var route = require('./route') 3 | 4 | var convert = {} 5 | 6 | var models = Object.keys(conversions) 7 | 8 | function wrapRaw(fn) { 9 | var wrappedFn = function(args) { 10 | if (args === undefined || args === null) { 11 | return args 12 | } 13 | 14 | if (arguments.length > 1) { 15 | args = Array.prototype.slice.call(arguments) 16 | } 17 | 18 | return fn(args) 19 | } 20 | 21 | // preserve .conversion property if there is one 22 | if ('conversion' in fn) { 23 | wrappedFn.conversion = fn.conversion 24 | } 25 | 26 | return wrappedFn 27 | } 28 | 29 | function wrapRounded(fn) { 30 | var wrappedFn = function(args) { 31 | if (args === undefined || args === null) { 32 | return args 33 | } 34 | 35 | if (arguments.length > 1) { 36 | args = Array.prototype.slice.call(arguments) 37 | } 38 | 39 | var result = fn(args) 40 | 41 | // we're assuming the result is an array here. 42 | // see notice in conversions.js; don't use box types 43 | // in conversion functions. 44 | if (typeof result === 'object') { 45 | for (var len = result.length, i = 0; i < len; i++) { 46 | result[i] = Math.round(result[i]) 47 | } 48 | } 49 | 50 | return result 51 | } 52 | 53 | // preserve .conversion property if there is one 54 | if ('conversion' in fn) { 55 | wrappedFn.conversion = fn.conversion 56 | } 57 | 58 | return wrappedFn 59 | } 60 | 61 | models.forEach(fromModel => { 62 | convert[fromModel] = {} 63 | 64 | Object.defineProperty(convert[fromModel], 'channels', { 65 | value: conversions[fromModel].channels, 66 | }) 67 | Object.defineProperty(convert[fromModel], 'labels', { 68 | value: conversions[fromModel].labels, 69 | }) 70 | 71 | var routes = route(fromModel) 72 | var routeModels = Object.keys(routes) 73 | 74 | routeModels.forEach(toModel => { 75 | var fn = routes[toModel] 76 | 77 | convert[fromModel][toModel] = wrapRounded(fn) 78 | convert[fromModel][toModel].raw = wrapRaw(fn) 79 | }) 80 | }) 81 | 82 | module.exports = convert 83 | -------------------------------------------------------------------------------- /modules/color-convert/route.js: -------------------------------------------------------------------------------- 1 | var conversions = require('./conversions') 2 | 3 | /* 4 | this function routes a model to all other models. 5 | all functions that are routed have a property `.conversion` attached 6 | to the returned synthetic function. This property is an array 7 | of strings, each with the steps in between the 'from' and 'to' 8 | color models (inclusive). 9 | conversions that are not possible simply are not included. 10 | */ 11 | 12 | // https://jsperf.com/object-keys-vs-for-in-with-closure/3 13 | var models = Object.keys(conversions) 14 | 15 | function buildGraph() { 16 | var graph = {} 17 | 18 | for (var len = models.length, i = 0; i < len; i++) { 19 | graph[models[i]] = { 20 | // http://jsperf.com/1-vs-infinity 21 | // micro-opt, but this is simple. 22 | distance: -1, 23 | parent: null, 24 | } 25 | } 26 | 27 | return graph 28 | } 29 | 30 | // https://en.wikipedia.org/wiki/Breadth-first_search 31 | function deriveBFS(fromModel) { 32 | var graph = buildGraph() 33 | var queue = [fromModel] // unshift -> queue -> pop 34 | 35 | graph[fromModel].distance = 0 36 | 37 | while (queue.length) { 38 | var current = queue.pop() 39 | var adjacents = Object.keys(conversions[current]) 40 | 41 | for (var len = adjacents.length, i = 0; i < len; i++) { 42 | var adjacent = adjacents[i] 43 | var node = graph[adjacent] 44 | 45 | if (node.distance === -1) { 46 | node.distance = graph[current].distance + 1 47 | node.parent = current 48 | queue.unshift(adjacent) 49 | } 50 | } 51 | } 52 | 53 | return graph 54 | } 55 | 56 | function link(from, to) { 57 | return function(args) { 58 | return to(from(args)) 59 | } 60 | } 61 | 62 | function wrapConversion(toModel, graph) { 63 | var path = [graph[toModel].parent, toModel] 64 | var fn = conversions[graph[toModel].parent][toModel] 65 | 66 | var cur = graph[toModel].parent 67 | while (graph[cur].parent) { 68 | path.unshift(graph[cur].parent) 69 | fn = link(conversions[graph[cur].parent][cur], fn) 70 | cur = graph[cur].parent 71 | } 72 | 73 | fn.conversion = path 74 | return fn 75 | } 76 | 77 | module.exports = function(fromModel) { 78 | var graph = deriveBFS(fromModel) 79 | var conversion = {} 80 | 81 | var models = Object.keys(graph) 82 | for (var len = models.length, i = 0; i < len; i++) { 83 | var toModel = models[i] 84 | var node = graph[toModel] 85 | 86 | if (node.parent === null) { 87 | // no possible conversion, or this node is the source model. 88 | continue 89 | } 90 | 91 | conversion[toModel] = wrapConversion(toModel, graph) 92 | } 93 | 94 | return conversion 95 | } 96 | -------------------------------------------------------------------------------- /modules/diff/convert/dmp.js: -------------------------------------------------------------------------------- 1 | /*istanbul ignore start*/"use strict"; 2 | 3 | exports.__esModule = true; 4 | exports. /*istanbul ignore end*/convertChangesToDMP = convertChangesToDMP; 5 | // See: http://code.google.com/p/google-diff-match-patch/wiki/API 6 | function convertChangesToDMP(changes) { 7 | var ret = [], 8 | change = /*istanbul ignore start*/void 0 /*istanbul ignore end*/, 9 | operation = /*istanbul ignore start*/void 0 /*istanbul ignore end*/; 10 | for (var i = 0; i < changes.length; i++) { 11 | change = changes[i]; 12 | if (change.added) { 13 | operation = 1; 14 | } else if (change.removed) { 15 | operation = -1; 16 | } else { 17 | operation = 0; 18 | } 19 | 20 | ret.push([operation, change.value]); 21 | } 22 | return ret; 23 | } 24 | //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jb252ZXJ0L2RtcC5qcyJdLCJuYW1lcyI6WyJjb252ZXJ0Q2hhbmdlc1RvRE1QIiwiY2hhbmdlcyIsInJldCIsImNoYW5nZSIsIm9wZXJhdGlvbiIsImkiLCJsZW5ndGgiLCJhZGRlZCIsInJlbW92ZWQiLCJwdXNoIiwidmFsdWUiXSwibWFwcGluZ3MiOiI7OztnQ0FDZ0JBLG1CLEdBQUFBLG1CO0FBRGhCO0FBQ08sU0FBU0EsbUJBQVQsQ0FBNkJDLE9BQTdCLEVBQXNDO0FBQzNDLE1BQUlDLE1BQU0sRUFBVjtBQUFBLE1BQ0lDLHdDQURKO0FBQUEsTUFFSUMsMkNBRko7QUFHQSxPQUFLLElBQUlDLElBQUksQ0FBYixFQUFnQkEsSUFBSUosUUFBUUssTUFBNUIsRUFBb0NELEdBQXBDLEVBQXlDO0FBQ3ZDRixhQUFTRixRQUFRSSxDQUFSLENBQVQ7QUFDQSxRQUFJRixPQUFPSSxLQUFYLEVBQWtCO0FBQ2hCSCxrQkFBWSxDQUFaO0FBQ0QsS0FGRCxNQUVPLElBQUlELE9BQU9LLE9BQVgsRUFBb0I7QUFDekJKLGtCQUFZLENBQUMsQ0FBYjtBQUNELEtBRk0sTUFFQTtBQUNMQSxrQkFBWSxDQUFaO0FBQ0Q7O0FBRURGLFFBQUlPLElBQUosQ0FBUyxDQUFDTCxTQUFELEVBQVlELE9BQU9PLEtBQW5CLENBQVQ7QUFDRDtBQUNELFNBQU9SLEdBQVA7QUFDRCIsImZpbGUiOiJkbXAuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBTZWU6IGh0dHA6Ly9jb2RlLmdvb2dsZS5jb20vcC9nb29nbGUtZGlmZi1tYXRjaC1wYXRjaC93aWtpL0FQSVxuZXhwb3J0IGZ1bmN0aW9uIGNvbnZlcnRDaGFuZ2VzVG9ETVAoY2hhbmdlcykge1xuICBsZXQgcmV0ID0gW10sXG4gICAgICBjaGFuZ2UsXG4gICAgICBvcGVyYXRpb247XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgY2hhbmdlcy5sZW5ndGg7IGkrKykge1xuICAgIGNoYW5nZSA9IGNoYW5nZXNbaV07XG4gICAgaWYgKGNoYW5nZS5hZGRlZCkge1xuICAgICAgb3BlcmF0aW9uID0gMTtcbiAgICB9IGVsc2UgaWYgKGNoYW5nZS5yZW1vdmVkKSB7XG4gICAgICBvcGVyYXRpb24gPSAtMTtcbiAgICB9IGVsc2Uge1xuICAgICAgb3BlcmF0aW9uID0gMDtcbiAgICB9XG5cbiAgICByZXQucHVzaChbb3BlcmF0aW9uLCBjaGFuZ2UudmFsdWVdKTtcbiAgfVxuICByZXR1cm4gcmV0O1xufVxuIl19 25 | -------------------------------------------------------------------------------- /modules/diff/convert/xml.js: -------------------------------------------------------------------------------- 1 | /*istanbul ignore start*/'use strict'; 2 | 3 | exports.__esModule = true; 4 | exports. /*istanbul ignore end*/convertChangesToXML = convertChangesToXML; 5 | function convertChangesToXML(changes) { 6 | var ret = []; 7 | for (var i = 0; i < changes.length; i++) { 8 | var change = changes[i]; 9 | if (change.added) { 10 | ret.push(''); 11 | } else if (change.removed) { 12 | ret.push(''); 13 | } 14 | 15 | ret.push(escapeHTML(change.value)); 16 | 17 | if (change.added) { 18 | ret.push(''); 19 | } else if (change.removed) { 20 | ret.push(''); 21 | } 22 | } 23 | return ret.join(''); 24 | } 25 | 26 | function escapeHTML(s) { 27 | var n = s; 28 | n = n.replace(/&/g, '&'); 29 | n = n.replace(//g, '>'); 31 | n = n.replace(/"/g, '"'); 32 | 33 | return n; 34 | } 35 | //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jb252ZXJ0L3htbC5qcyJdLCJuYW1lcyI6WyJjb252ZXJ0Q2hhbmdlc1RvWE1MIiwiY2hhbmdlcyIsInJldCIsImkiLCJsZW5ndGgiLCJjaGFuZ2UiLCJhZGRlZCIsInB1c2giLCJyZW1vdmVkIiwiZXNjYXBlSFRNTCIsInZhbHVlIiwiam9pbiIsInMiLCJuIiwicmVwbGFjZSJdLCJtYXBwaW5ncyI6Ijs7O2dDQUFnQkEsbUIsR0FBQUEsbUI7QUFBVCxTQUFTQSxtQkFBVCxDQUE2QkMsT0FBN0IsRUFBc0M7QUFDM0MsTUFBSUMsTUFBTSxFQUFWO0FBQ0EsT0FBSyxJQUFJQyxJQUFJLENBQWIsRUFBZ0JBLElBQUlGLFFBQVFHLE1BQTVCLEVBQW9DRCxHQUFwQyxFQUF5QztBQUN2QyxRQUFJRSxTQUFTSixRQUFRRSxDQUFSLENBQWI7QUFDQSxRQUFJRSxPQUFPQyxLQUFYLEVBQWtCO0FBQ2hCSixVQUFJSyxJQUFKLENBQVMsT0FBVDtBQUNELEtBRkQsTUFFTyxJQUFJRixPQUFPRyxPQUFYLEVBQW9CO0FBQ3pCTixVQUFJSyxJQUFKLENBQVMsT0FBVDtBQUNEOztBQUVETCxRQUFJSyxJQUFKLENBQVNFLFdBQVdKLE9BQU9LLEtBQWxCLENBQVQ7O0FBRUEsUUFBSUwsT0FBT0MsS0FBWCxFQUFrQjtBQUNoQkosVUFBSUssSUFBSixDQUFTLFFBQVQ7QUFDRCxLQUZELE1BRU8sSUFBSUYsT0FBT0csT0FBWCxFQUFvQjtBQUN6Qk4sVUFBSUssSUFBSixDQUFTLFFBQVQ7QUFDRDtBQUNGO0FBQ0QsU0FBT0wsSUFBSVMsSUFBSixDQUFTLEVBQVQsQ0FBUDtBQUNEOztBQUVELFNBQVNGLFVBQVQsQ0FBb0JHLENBQXBCLEVBQXVCO0FBQ3JCLE1BQUlDLElBQUlELENBQVI7QUFDQUMsTUFBSUEsRUFBRUMsT0FBRixDQUFVLElBQVYsRUFBZ0IsT0FBaEIsQ0FBSjtBQUNBRCxNQUFJQSxFQUFFQyxPQUFGLENBQVUsSUFBVixFQUFnQixNQUFoQixDQUFKO0FBQ0FELE1BQUlBLEVBQUVDLE9BQUYsQ0FBVSxJQUFWLEVBQWdCLE1BQWhCLENBQUo7QUFDQUQsTUFBSUEsRUFBRUMsT0FBRixDQUFVLElBQVYsRUFBZ0IsUUFBaEIsQ0FBSjs7QUFFQSxTQUFPRCxDQUFQO0FBQ0QiLCJmaWxlIjoieG1sLmpzIiwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0IGZ1bmN0aW9uIGNvbnZlcnRDaGFuZ2VzVG9YTUwoY2hhbmdlcykge1xuICBsZXQgcmV0ID0gW107XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgY2hhbmdlcy5sZW5ndGg7IGkrKykge1xuICAgIGxldCBjaGFuZ2UgPSBjaGFuZ2VzW2ldO1xuICAgIGlmIChjaGFuZ2UuYWRkZWQpIHtcbiAgICAgIHJldC5wdXNoKCc8aW5zPicpO1xuICAgIH0gZWxzZSBpZiAoY2hhbmdlLnJlbW92ZWQpIHtcbiAgICAgIHJldC5wdXNoKCc8ZGVsPicpO1xuICAgIH1cblxuICAgIHJldC5wdXNoKGVzY2FwZUhUTUwoY2hhbmdlLnZhbHVlKSk7XG5cbiAgICBpZiAoY2hhbmdlLmFkZGVkKSB7XG4gICAgICByZXQucHVzaCgnPC9pbnM+Jyk7XG4gICAgfSBlbHNlIGlmIChjaGFuZ2UucmVtb3ZlZCkge1xuICAgICAgcmV0LnB1c2goJzwvZGVsPicpO1xuICAgIH1cbiAgfVxuICByZXR1cm4gcmV0LmpvaW4oJycpO1xufVxuXG5mdW5jdGlvbiBlc2NhcGVIVE1MKHMpIHtcbiAgbGV0IG4gPSBzO1xuICBuID0gbi5yZXBsYWNlKC8mL2csICcmYW1wOycpO1xuICBuID0gbi5yZXBsYWNlKC88L2csICcmbHQ7Jyk7XG4gIG4gPSBuLnJlcGxhY2UoLz4vZywgJyZndDsnKTtcbiAgbiA9IG4ucmVwbGFjZSgvXCIvZywgJyZxdW90OycpO1xuXG4gIHJldHVybiBuO1xufVxuIl19 36 | -------------------------------------------------------------------------------- /modules/diff/diff/array.js: -------------------------------------------------------------------------------- 1 | /*istanbul ignore start*/'use strict'; 2 | 3 | exports.__esModule = true; 4 | exports.arrayDiff = undefined; 5 | exports. /*istanbul ignore end*/diffArrays = diffArrays; 6 | 7 | var /*istanbul ignore start*/_base = require('./base') /*istanbul ignore end*/; 8 | 9 | /*istanbul ignore start*/var _base2 = _interopRequireDefault(_base); 10 | 11 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 12 | 13 | /*istanbul ignore end*/var arrayDiff = /*istanbul ignore start*/exports. /*istanbul ignore end*/arrayDiff = new /*istanbul ignore start*/_base2['default'] /*istanbul ignore end*/(); 14 | arrayDiff.tokenize = arrayDiff.join = function (value) { 15 | return value.slice(); 16 | }; 17 | 18 | function diffArrays(oldArr, newArr, callback) { 19 | return arrayDiff.diff(oldArr, newArr, callback); 20 | } 21 | //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9kaWZmL2FycmF5LmpzIl0sIm5hbWVzIjpbImRpZmZBcnJheXMiLCJhcnJheURpZmYiLCJ0b2tlbml6ZSIsImpvaW4iLCJ2YWx1ZSIsInNsaWNlIiwib2xkQXJyIiwibmV3QXJyIiwiY2FsbGJhY2siLCJkaWZmIl0sIm1hcHBpbmdzIjoiOzs7O2dDQU9nQkEsVSxHQUFBQSxVOztBQVBoQjs7Ozs7O3VCQUVPLElBQU1DLGlGQUFZLHdFQUFsQjtBQUNQQSxVQUFVQyxRQUFWLEdBQXFCRCxVQUFVRSxJQUFWLEdBQWlCLFVBQVNDLEtBQVQsRUFBZ0I7QUFDcEQsU0FBT0EsTUFBTUMsS0FBTixFQUFQO0FBQ0QsQ0FGRDs7QUFJTyxTQUFTTCxVQUFULENBQW9CTSxNQUFwQixFQUE0QkMsTUFBNUIsRUFBb0NDLFFBQXBDLEVBQThDO0FBQUUsU0FBT1AsVUFBVVEsSUFBVixDQUFlSCxNQUFmLEVBQXVCQyxNQUF2QixFQUErQkMsUUFBL0IsQ0FBUDtBQUFrRCIsImZpbGUiOiJhcnJheS5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBEaWZmIGZyb20gJy4vYmFzZSc7XG5cbmV4cG9ydCBjb25zdCBhcnJheURpZmYgPSBuZXcgRGlmZigpO1xuYXJyYXlEaWZmLnRva2VuaXplID0gYXJyYXlEaWZmLmpvaW4gPSBmdW5jdGlvbih2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUuc2xpY2UoKTtcbn07XG5cbmV4cG9ydCBmdW5jdGlvbiBkaWZmQXJyYXlzKG9sZEFyciwgbmV3QXJyLCBjYWxsYmFjaykgeyByZXR1cm4gYXJyYXlEaWZmLmRpZmYob2xkQXJyLCBuZXdBcnIsIGNhbGxiYWNrKTsgfVxuIl19 22 | -------------------------------------------------------------------------------- /modules/diff/diff/character.js: -------------------------------------------------------------------------------- 1 | /*istanbul ignore start*/'use strict'; 2 | 3 | exports.__esModule = true; 4 | exports.characterDiff = undefined; 5 | exports. /*istanbul ignore end*/diffChars = diffChars; 6 | 7 | var /*istanbul ignore start*/_base = require('./base') /*istanbul ignore end*/; 8 | 9 | /*istanbul ignore start*/var _base2 = _interopRequireDefault(_base); 10 | 11 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 12 | 13 | /*istanbul ignore end*/var characterDiff = /*istanbul ignore start*/exports. /*istanbul ignore end*/characterDiff = new /*istanbul ignore start*/_base2['default'] /*istanbul ignore end*/(); 14 | function diffChars(oldStr, newStr, options) { 15 | return characterDiff.diff(oldStr, newStr, options); 16 | } 17 | //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9kaWZmL2NoYXJhY3Rlci5qcyJdLCJuYW1lcyI6WyJkaWZmQ2hhcnMiLCJjaGFyYWN0ZXJEaWZmIiwib2xkU3RyIiwibmV3U3RyIiwib3B0aW9ucyIsImRpZmYiXSwibWFwcGluZ3MiOiI7Ozs7Z0NBR2dCQSxTLEdBQUFBLFM7O0FBSGhCOzs7Ozs7dUJBRU8sSUFBTUMseUZBQWdCLHdFQUF0QjtBQUNBLFNBQVNELFNBQVQsQ0FBbUJFLE1BQW5CLEVBQTJCQyxNQUEzQixFQUFtQ0MsT0FBbkMsRUFBNEM7QUFBRSxTQUFPSCxjQUFjSSxJQUFkLENBQW1CSCxNQUFuQixFQUEyQkMsTUFBM0IsRUFBbUNDLE9BQW5DLENBQVA7QUFBcUQiLCJmaWxlIjoiY2hhcmFjdGVyLmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IERpZmYgZnJvbSAnLi9iYXNlJztcblxuZXhwb3J0IGNvbnN0IGNoYXJhY3RlckRpZmYgPSBuZXcgRGlmZigpO1xuZXhwb3J0IGZ1bmN0aW9uIGRpZmZDaGFycyhvbGRTdHIsIG5ld1N0ciwgb3B0aW9ucykgeyByZXR1cm4gY2hhcmFjdGVyRGlmZi5kaWZmKG9sZFN0ciwgbmV3U3RyLCBvcHRpb25zKTsgfVxuIl19 18 | -------------------------------------------------------------------------------- /modules/diff/diff/css.js: -------------------------------------------------------------------------------- 1 | /*istanbul ignore start*/'use strict'; 2 | 3 | exports.__esModule = true; 4 | exports.cssDiff = undefined; 5 | exports. /*istanbul ignore end*/diffCss = diffCss; 6 | 7 | var /*istanbul ignore start*/_base = require('./base') /*istanbul ignore end*/; 8 | 9 | /*istanbul ignore start*/var _base2 = _interopRequireDefault(_base); 10 | 11 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 12 | 13 | /*istanbul ignore end*/var cssDiff = /*istanbul ignore start*/exports. /*istanbul ignore end*/cssDiff = new /*istanbul ignore start*/_base2['default'] /*istanbul ignore end*/(); 14 | cssDiff.tokenize = function (value) { 15 | return value.split(/([{}:;,]|\s+)/); 16 | }; 17 | 18 | function diffCss(oldStr, newStr, callback) { 19 | return cssDiff.diff(oldStr, newStr, callback); 20 | } 21 | //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9kaWZmL2Nzcy5qcyJdLCJuYW1lcyI6WyJkaWZmQ3NzIiwiY3NzRGlmZiIsInRva2VuaXplIiwidmFsdWUiLCJzcGxpdCIsIm9sZFN0ciIsIm5ld1N0ciIsImNhbGxiYWNrIiwiZGlmZiJdLCJtYXBwaW5ncyI6Ijs7OztnQ0FPZ0JBLE8sR0FBQUEsTzs7QUFQaEI7Ozs7Ozt1QkFFTyxJQUFNQyw2RUFBVSx3RUFBaEI7QUFDUEEsUUFBUUMsUUFBUixHQUFtQixVQUFTQyxLQUFULEVBQWdCO0FBQ2pDLFNBQU9BLE1BQU1DLEtBQU4sQ0FBWSxlQUFaLENBQVA7QUFDRCxDQUZEOztBQUlPLFNBQVNKLE9BQVQsQ0FBaUJLLE1BQWpCLEVBQXlCQyxNQUF6QixFQUFpQ0MsUUFBakMsRUFBMkM7QUFBRSxTQUFPTixRQUFRTyxJQUFSLENBQWFILE1BQWIsRUFBcUJDLE1BQXJCLEVBQTZCQyxRQUE3QixDQUFQO0FBQWdEIiwiZmlsZSI6ImNzcy5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBEaWZmIGZyb20gJy4vYmFzZSc7XG5cbmV4cG9ydCBjb25zdCBjc3NEaWZmID0gbmV3IERpZmYoKTtcbmNzc0RpZmYudG9rZW5pemUgPSBmdW5jdGlvbih2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUuc3BsaXQoLyhbe306OyxdfFxccyspLyk7XG59O1xuXG5leHBvcnQgZnVuY3Rpb24gZGlmZkNzcyhvbGRTdHIsIG5ld1N0ciwgY2FsbGJhY2spIHsgcmV0dXJuIGNzc0RpZmYuZGlmZihvbGRTdHIsIG5ld1N0ciwgY2FsbGJhY2spOyB9XG4iXX0= 22 | -------------------------------------------------------------------------------- /modules/diff/diff/sentence.js: -------------------------------------------------------------------------------- 1 | /*istanbul ignore start*/'use strict'; 2 | 3 | exports.__esModule = true; 4 | exports.sentenceDiff = undefined; 5 | exports. /*istanbul ignore end*/diffSentences = diffSentences; 6 | 7 | var /*istanbul ignore start*/_base = require('./base') /*istanbul ignore end*/; 8 | 9 | /*istanbul ignore start*/var _base2 = _interopRequireDefault(_base); 10 | 11 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 12 | 13 | /*istanbul ignore end*/var sentenceDiff = /*istanbul ignore start*/exports. /*istanbul ignore end*/sentenceDiff = new /*istanbul ignore start*/_base2['default'] /*istanbul ignore end*/(); 14 | sentenceDiff.tokenize = function (value) { 15 | return value.split(/(\S.+?[.!?])(?=\s+|$)/); 16 | }; 17 | 18 | function diffSentences(oldStr, newStr, callback) { 19 | return sentenceDiff.diff(oldStr, newStr, callback); 20 | } 21 | //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9kaWZmL3NlbnRlbmNlLmpzIl0sIm5hbWVzIjpbImRpZmZTZW50ZW5jZXMiLCJzZW50ZW5jZURpZmYiLCJ0b2tlbml6ZSIsInZhbHVlIiwic3BsaXQiLCJvbGRTdHIiLCJuZXdTdHIiLCJjYWxsYmFjayIsImRpZmYiXSwibWFwcGluZ3MiOiI7Ozs7Z0NBUWdCQSxhLEdBQUFBLGE7O0FBUmhCOzs7Ozs7dUJBR08sSUFBTUMsdUZBQWUsd0VBQXJCO0FBQ1BBLGFBQWFDLFFBQWIsR0FBd0IsVUFBU0MsS0FBVCxFQUFnQjtBQUN0QyxTQUFPQSxNQUFNQyxLQUFOLENBQVksdUJBQVosQ0FBUDtBQUNELENBRkQ7O0FBSU8sU0FBU0osYUFBVCxDQUF1QkssTUFBdkIsRUFBK0JDLE1BQS9CLEVBQXVDQyxRQUF2QyxFQUFpRDtBQUFFLFNBQU9OLGFBQWFPLElBQWIsQ0FBa0JILE1BQWxCLEVBQTBCQyxNQUExQixFQUFrQ0MsUUFBbEMsQ0FBUDtBQUFxRCIsImZpbGUiOiJzZW50ZW5jZS5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBEaWZmIGZyb20gJy4vYmFzZSc7XG5cblxuZXhwb3J0IGNvbnN0IHNlbnRlbmNlRGlmZiA9IG5ldyBEaWZmKCk7XG5zZW50ZW5jZURpZmYudG9rZW5pemUgPSBmdW5jdGlvbih2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUuc3BsaXQoLyhcXFMuKz9bLiE/XSkoPz1cXHMrfCQpLyk7XG59O1xuXG5leHBvcnQgZnVuY3Rpb24gZGlmZlNlbnRlbmNlcyhvbGRTdHIsIG5ld1N0ciwgY2FsbGJhY2spIHsgcmV0dXJuIHNlbnRlbmNlRGlmZi5kaWZmKG9sZFN0ciwgbmV3U3RyLCBjYWxsYmFjayk7IH1cbiJdfQ== 22 | -------------------------------------------------------------------------------- /modules/diff/util/array.js: -------------------------------------------------------------------------------- 1 | /*istanbul ignore start*/"use strict"; 2 | 3 | exports.__esModule = true; 4 | exports. /*istanbul ignore end*/arrayEqual = arrayEqual; 5 | /*istanbul ignore start*/exports. /*istanbul ignore end*/arrayStartsWith = arrayStartsWith; 6 | function arrayEqual(a, b) { 7 | if (a.length !== b.length) { 8 | return false; 9 | } 10 | 11 | return arrayStartsWith(a, b); 12 | } 13 | 14 | function arrayStartsWith(array, start) { 15 | if (start.length > array.length) { 16 | return false; 17 | } 18 | 19 | for (var i = 0; i < start.length; i++) { 20 | if (start[i] !== array[i]) { 21 | return false; 22 | } 23 | } 24 | 25 | return true; 26 | } 27 | //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91dGlsL2FycmF5LmpzIl0sIm5hbWVzIjpbImFycmF5RXF1YWwiLCJhcnJheVN0YXJ0c1dpdGgiLCJhIiwiYiIsImxlbmd0aCIsImFycmF5Iiwic3RhcnQiLCJpIl0sIm1hcHBpbmdzIjoiOzs7Z0NBQWdCQSxVLEdBQUFBLFU7eURBUUFDLGUsR0FBQUEsZTtBQVJULFNBQVNELFVBQVQsQ0FBb0JFLENBQXBCLEVBQXVCQyxDQUF2QixFQUEwQjtBQUMvQixNQUFJRCxFQUFFRSxNQUFGLEtBQWFELEVBQUVDLE1BQW5CLEVBQTJCO0FBQ3pCLFdBQU8sS0FBUDtBQUNEOztBQUVELFNBQU9ILGdCQUFnQkMsQ0FBaEIsRUFBbUJDLENBQW5CLENBQVA7QUFDRDs7QUFFTSxTQUFTRixlQUFULENBQXlCSSxLQUF6QixFQUFnQ0MsS0FBaEMsRUFBdUM7QUFDNUMsTUFBSUEsTUFBTUYsTUFBTixHQUFlQyxNQUFNRCxNQUF6QixFQUFpQztBQUMvQixXQUFPLEtBQVA7QUFDRDs7QUFFRCxPQUFLLElBQUlHLElBQUksQ0FBYixFQUFnQkEsSUFBSUQsTUFBTUYsTUFBMUIsRUFBa0NHLEdBQWxDLEVBQXVDO0FBQ3JDLFFBQUlELE1BQU1DLENBQU4sTUFBYUYsTUFBTUUsQ0FBTixDQUFqQixFQUEyQjtBQUN6QixhQUFPLEtBQVA7QUFDRDtBQUNGOztBQUVELFNBQU8sSUFBUDtBQUNEIiwiZmlsZSI6ImFycmF5LmpzIiwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0IGZ1bmN0aW9uIGFycmF5RXF1YWwoYSwgYikge1xuICBpZiAoYS5sZW5ndGggIT09IGIubGVuZ3RoKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgcmV0dXJuIGFycmF5U3RhcnRzV2l0aChhLCBiKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGFycmF5U3RhcnRzV2l0aChhcnJheSwgc3RhcnQpIHtcbiAgaWYgKHN0YXJ0Lmxlbmd0aCA+IGFycmF5Lmxlbmd0aCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgc3RhcnQubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoc3RhcnRbaV0gIT09IGFycmF5W2ldKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRydWU7XG59XG4iXX0= 28 | -------------------------------------------------------------------------------- /modules/diff/util/params.js: -------------------------------------------------------------------------------- 1 | /*istanbul ignore start*/'use strict'; 2 | 3 | exports.__esModule = true; 4 | exports. /*istanbul ignore end*/generateOptions = generateOptions; 5 | function generateOptions(options, defaults) { 6 | if (typeof options === 'function') { 7 | defaults.callback = options; 8 | } else if (options) { 9 | for (var name in options) { 10 | /* istanbul ignore else */ 11 | if (options.hasOwnProperty(name)) { 12 | defaults[name] = options[name]; 13 | } 14 | } 15 | } 16 | return defaults; 17 | } 18 | //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91dGlsL3BhcmFtcy5qcyJdLCJuYW1lcyI6WyJnZW5lcmF0ZU9wdGlvbnMiLCJvcHRpb25zIiwiZGVmYXVsdHMiLCJjYWxsYmFjayIsIm5hbWUiLCJoYXNPd25Qcm9wZXJ0eSJdLCJtYXBwaW5ncyI6Ijs7O2dDQUFnQkEsZSxHQUFBQSxlO0FBQVQsU0FBU0EsZUFBVCxDQUF5QkMsT0FBekIsRUFBa0NDLFFBQWxDLEVBQTRDO0FBQ2pELE1BQUksT0FBT0QsT0FBUCxLQUFtQixVQUF2QixFQUFtQztBQUNqQ0MsYUFBU0MsUUFBVCxHQUFvQkYsT0FBcEI7QUFDRCxHQUZELE1BRU8sSUFBSUEsT0FBSixFQUFhO0FBQ2xCLFNBQUssSUFBSUcsSUFBVCxJQUFpQkgsT0FBakIsRUFBMEI7QUFDeEI7QUFDQSxVQUFJQSxRQUFRSSxjQUFSLENBQXVCRCxJQUF2QixDQUFKLEVBQWtDO0FBQ2hDRixpQkFBU0UsSUFBVCxJQUFpQkgsUUFBUUcsSUFBUixDQUFqQjtBQUNEO0FBQ0Y7QUFDRjtBQUNELFNBQU9GLFFBQVA7QUFDRCIsImZpbGUiOiJwYXJhbXMuanMiLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgZnVuY3Rpb24gZ2VuZXJhdGVPcHRpb25zKG9wdGlvbnMsIGRlZmF1bHRzKSB7XG4gIGlmICh0eXBlb2Ygb3B0aW9ucyA9PT0gJ2Z1bmN0aW9uJykge1xuICAgIGRlZmF1bHRzLmNhbGxiYWNrID0gb3B0aW9ucztcbiAgfSBlbHNlIGlmIChvcHRpb25zKSB7XG4gICAgZm9yIChsZXQgbmFtZSBpbiBvcHRpb25zKSB7XG4gICAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgZWxzZSAqL1xuICAgICAgaWYgKG9wdGlvbnMuaGFzT3duUHJvcGVydHkobmFtZSkpIHtcbiAgICAgICAgZGVmYXVsdHNbbmFtZV0gPSBvcHRpb25zW25hbWVdO1xuICAgICAgfVxuICAgIH1cbiAgfVxuICByZXR1cm4gZGVmYXVsdHM7XG59XG4iXX0= 19 | -------------------------------------------------------------------------------- /modules/duplexer2/index.js: -------------------------------------------------------------------------------- 1 | var stream = require('readable-stream') 2 | 3 | function DuplexWrapper(options, writable, readable) { 4 | if (typeof readable === 'undefined') { 5 | readable = writable 6 | writable = options 7 | options = null 8 | } 9 | 10 | stream.Duplex.call(this, options) 11 | 12 | if (typeof readable.read !== 'function') { 13 | readable = new stream.Readable(options).wrap(readable) 14 | } 15 | 16 | this._writable = writable 17 | this._readable = readable 18 | this._waiting = false 19 | 20 | var self = this 21 | 22 | writable.once('finish', () => { 23 | self.end() 24 | }) 25 | 26 | this.once('finish', () => { 27 | writable.end() 28 | }) 29 | 30 | readable.on('readable', () => { 31 | if (self._waiting) { 32 | self._waiting = false 33 | self._read() 34 | } 35 | }) 36 | 37 | readable.once('end', () => { 38 | self.push(null) 39 | }) 40 | 41 | if ( 42 | !options || 43 | typeof options.bubbleErrors === 'undefined' || 44 | options.bubbleErrors 45 | ) { 46 | writable.on('error', err => { 47 | self.emit('error', err) 48 | }) 49 | 50 | readable.on('error', err => { 51 | self.emit('error', err) 52 | }) 53 | } 54 | } 55 | 56 | DuplexWrapper.prototype = Object.create(stream.Duplex.prototype, { 57 | constructor: {value: DuplexWrapper}, 58 | }) 59 | 60 | DuplexWrapper.prototype._write = function _write(input, encoding, done) { 61 | this._writable.write(input, encoding, done) 62 | } 63 | 64 | DuplexWrapper.prototype._read = function _read() { 65 | var buf 66 | var reads = 0 67 | while ((buf = this._readable.read()) !== null) { 68 | this.push(buf) 69 | reads++ 70 | } 71 | if (reads === 0) { 72 | this._waiting = true 73 | } 74 | } 75 | 76 | module.exports = function duplex2(options, writable, readable) { 77 | return new DuplexWrapper(options, writable, readable) 78 | } 79 | 80 | module.exports.DuplexWrapper = DuplexWrapper 81 | -------------------------------------------------------------------------------- /modules/escape-string-regexp/index.js: -------------------------------------------------------------------------------- 1 | var matchOperatorsRe = /[|\\{}()[\]^$+*?.]/g 2 | 3 | module.exports = function(str) { 4 | if (typeof str !== 'string') { 5 | throw new TypeError('Expected a string') 6 | } 7 | 8 | return str.replace(matchOperatorsRe, '\\$&') 9 | } 10 | -------------------------------------------------------------------------------- /modules/esutils/README.md: -------------------------------------------------------------------------------- 1 | https://github.com/estools/esutils 2 | -------------------------------------------------------------------------------- /modules/esutils/index.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./lib/utils') 2 | -------------------------------------------------------------------------------- /modules/esutils/lib/utils.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2013 Yusuke Suzuki 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are met: 5 | * Redistributions of source code must retain the above copyright 6 | notice, this list of conditions and the following disclaimer. 7 | * Redistributions in binary form must reproduce the above copyright 8 | notice, this list of conditions and the following disclaimer in the 9 | documentation and/or other materials provided with the distribution. 10 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 11 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 12 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 13 | ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 14 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 15 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 16 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 17 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 18 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 19 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 20 | */ 21 | 22 | (function() { 23 | exports.ast = require('./ast') 24 | exports.code = require('./code') 25 | exports.keyword = require('./keyword') 26 | })() 27 | /* vim: set sw=4 ts=4 et tw=80 : */ 28 | -------------------------------------------------------------------------------- /modules/expose-hidden/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fliphub/fliplog/b0a1581e749a41ab65731f88cc90f2c24d20247d/modules/expose-hidden/index.js -------------------------------------------------------------------------------- /modules/funwithflags/utils.js: -------------------------------------------------------------------------------- 1 | function hasKey(obj, keys) { 2 | var o = obj 3 | const sliced = keys.slice(0, -1) 4 | 5 | for (let i = 0; i < sliced.length; i++) { 6 | const key = sliced[i] 7 | o = o[key] || {} 8 | } 9 | 10 | var key = keys[keys.length - 1] 11 | 12 | return o[key] !== undefined 13 | } 14 | 15 | function isNum(x) { 16 | if (typeof x === 'number') return true 17 | if (/^0x[0-9a-f]+$/i.test(x) === true) return true 18 | return (/^[-+]?(?:\d+(?:\.\d*)?|\.\d+)(e[-+]?\d+)?$/).test(x) 19 | } 20 | 21 | // function isArr(x, type = 'array') { 22 | // if (type === 'array') { 23 | // if (typeof x === 'string' && x.includes) { 24 | // if (x.includes(',') === true) return x.split(',') 25 | // } 26 | // return [x] 27 | // } 28 | // } 29 | 30 | // function isNullOrUndef(x) { 31 | // if (/undefined/.test(x)) return undefined 32 | // if (/null/.test(x)) return null 33 | // } 34 | 35 | /** 36 | * @tutorial http://stackoverflow.com/questions/2970525/converting-any-string-into-camel-case 37 | * @tutorial https://github.com/sindresorhus/camelcase 38 | * @param {string} str 39 | * @return {string} 40 | * 41 | * s.charAt(0).toLowerCase() + string.slice(1) 42 | */ 43 | function camelCase(str) { 44 | return str 45 | .replace(/(?:^\w|[A-Z]|\b\w|\s+)/g, (match, index) => { 46 | if (+match === 0) return '' // or if (/\s+/.test(match)) for white spaces 47 | 48 | // needs to be a loose 0 or first char will be uc if first char is - 49 | // eslint-disable-next-line 50 | return index == 0 ? match.toLowerCase() : match.toUpperCase() 51 | }) 52 | .replace(/[-_]/g, '') 53 | } 54 | 55 | /** 56 | * @desc this duplicates keys, is simplest fastest 57 | * @NOTE mutates obj 58 | * @param {Object} obj 59 | * @return {Object} 60 | */ 61 | function camelCaseKeys(obj) { 62 | const keys = Object.keys(obj) 63 | const camelKeys = keys.map(camelCase) 64 | for (let i = 0; i < keys.length; i++) { 65 | const camel = camelKeys[i] 66 | // console.log({camel, camelKeys, i, keys, c: camelKeys[i], k: keys[i]}) 67 | if (camel.length === 0) continue 68 | obj[camel] = obj[keys[i]] 69 | } 70 | return obj 71 | } 72 | 73 | module.exports = {hasKey, isNum, camelCaseKeys} 74 | -------------------------------------------------------------------------------- /modules/indent-string/index.js: -------------------------------------------------------------------------------- 1 | // https://github.com/sindresorhus/indent-string/blob/master/index.js 2 | module.exports = function indentString(str, count, indent) { 3 | indent = indent === undefined ? ' ' : indent 4 | count = count === undefined ? 1 : count 5 | 6 | if (typeof str !== 'string') { 7 | throw new TypeError( 8 | `Expected \`input\` to be a \`string\`, got \`${typeof str}\`` 9 | ) 10 | } 11 | 12 | if (typeof count !== 'number') { 13 | throw new TypeError( 14 | `Expected \`count\` to be a \`number\`, got \`${typeof count}\`` 15 | ) 16 | } 17 | 18 | if (typeof indent !== 'string') { 19 | throw new TypeError( 20 | `Expected \`indent\` to be a \`string\`, got \`${typeof indent}\`` 21 | ) 22 | } 23 | 24 | if (count === 0) { 25 | return str 26 | } 27 | 28 | return str.replace(/^(?!\s*$)/gm, indent.repeat(count)) 29 | } 30 | -------------------------------------------------------------------------------- /modules/index.js: -------------------------------------------------------------------------------- 1 | const camelCase = require('./camel-case') 2 | 3 | // if dependency is already installed, use it, otherwise, fallback to inlined 4 | module.exports = function requireFromDepIfPossible(name) { 5 | const type = typeof name 6 | 7 | // allow returning an obj 8 | if (type !== 'string' && Array.isArray(name)) { 9 | const obj = {} 10 | name.forEach(n => { 11 | obj[camelCase(n)] = requireFromDepIfPossible(n) 12 | }) 13 | return obj 14 | } 15 | else if (type !== 'string' && type === 'object') { 16 | const obj = {} 17 | Object.keys(name).forEach(n => { 18 | obj[camelCase(n)] = requireFromDepIfPossible(n) 19 | }) 20 | return obj 21 | } 22 | 23 | try { 24 | require.resolve(name) 25 | const required = require(name) 26 | if (required) return required 27 | else throw Error('not required') 28 | } 29 | catch (e) { 30 | try { 31 | const dep = require('./' + name) 32 | return dep 33 | } 34 | catch (noModule) { 35 | return false 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /modules/inherits/README.md: -------------------------------------------------------------------------------- 1 | used by retro 2 | -------------------------------------------------------------------------------- /modules/inherits/index.js: -------------------------------------------------------------------------------- 1 | if (typeof Object.create === 'function') { 2 | // implementation from standard node.js 'util' module 3 | module.exports = function inherits(ctor, superCtor) { 4 | ctor.super_ = superCtor 5 | ctor.prototype = Object.create(superCtor.prototype, { 6 | constructor: { 7 | value: ctor, 8 | enumerable: false, 9 | writable: true, 10 | configurable: true, 11 | }, 12 | }) 13 | } 14 | } 15 | else { 16 | // old school shim for old browsers 17 | module.exports = function inherits(ctor, superCtor) { 18 | ctor.super_ = superCtor 19 | var TempCtor = function() {} 20 | TempCtor.prototype = superCtor.prototype 21 | ctor.prototype = new TempCtor() 22 | ctor.prototype.constructor = ctor 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /modules/inspector-gadget/README.md: -------------------------------------------------------------------------------- 1 | # inspector-gadget 🕵🗜⚙ 2 | 3 | [![NPM version][inspector-gadget-npm-image]][inspector-gadget-npm-url] 4 | [![MIT License][license-image]][license-url] 5 | [![fliphub][gitter-badge]][gitter-url] 6 | [![flipfam][flipfam-image]][flipfam-url] 7 | 8 | [inspector-gadget-npm-image]: https://img.shields.io/npm/v/inspector-gadget.svg 9 | [inspector-gadget-npm-url]: https://npmjs.org/package/inspector-gadget 10 | [license-image]: http://img.shields.io/badge/license-MIT-blue.svg?style=flat 11 | [license-url]: https://spdx.org/licenses/MIT 12 | [gitter-badge]: https://img.shields.io/gitter/room/fliphub/pink.svg 13 | [gitter-url]: https://gitter.im/fliphub/Lobby 14 | [flipfam-image]: https://img.shields.io/badge/%F0%9F%8F%97%20%F0%9F%92%A0-flipfam-9659F7.svg 15 | [flipfam-url]: https://www.npmjs.com/package/flipfam 16 | 17 | 18 | ![https://github.com/fliphub/fliphub]( https://cloud.githubusercontent.com/assets/4022631/24534601/e748baf2-1583-11e7-897b-d9707e3bcf53.png) 19 | 20 | 21 | 22 | > preconfigured nodejs util for inspecting, and customizing inspecting 23 | 24 | ## inspectorGadget 🗜 25 | configure what is exposed when inspecting 26 | 27 | ```js 28 | const {inspectorGadget} = require('inspector-gadget') 29 | class Eh { 30 | constructor() { 31 | this.inspect = inspectorGadget(this, ['property-to-ignore']) 32 | } 33 | } 34 | ``` 35 | 36 | ## inspector 🕵 37 | ```js 38 | const {inspector} = require('inspector-gadget') 39 | const inspected = inspector({ 40 | some: { 41 | super: { 42 | deep: { 43 | data: { 44 | with: { 45 | colors: function() { 46 | this.array = ['with inspection with colors pre configured'] 47 | } 48 | } 49 | } 50 | } 51 | } 52 | } 53 | }) 54 | console.log(inspected) 55 | ``` 56 | 57 | ## custom ⚙ 58 | ```js 59 | const {custom} = require('inspector-gadget') 60 | 61 | // disables 62 | custom(false) 63 | 64 | // re-enables 65 | custom(true) 66 | 67 | // changes to your value, be careful. 68 | custom(() => {}) 69 | ``` 70 | 71 | ### options 72 | - if it fails to inspect, it will [javascript-stringify](https://www.npmjs.com/package/javascript-stringify) 73 | - second arg is a number, how deep you want to go (default 30) 74 | - 3rd arg is options to override pre-configured [nodejs util inspect options](https://nodejs.org/api/util.html#util_util_inspect_object_options) 75 | - it also exports `util`, for your convenience in destructuring 76 | -------------------------------------------------------------------------------- /modules/inspector-gadget/_package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "inspector-gadget", 3 | "description": "preconfigured nodejs util for inspecting, and customizing inspecting", 4 | "version": "2.0.0", 5 | "main": "index.js", 6 | "files": [ 7 | "index.js", 8 | "inspector.js", 9 | "inspector-gadget.js" 10 | ], 11 | "keywords": [ 12 | "flip", 13 | "inspect", 14 | "helpers", 15 | "utils", 16 | "debugging", 17 | "nodejs", 18 | "fliphub", 19 | "flipbox" 20 | ], 21 | "author": "James ", 22 | "homepage": "https://github.com/fliphub/fliphub#readme", 23 | "repository": { 24 | "type": "git", 25 | "url": "git+https://github.com/fliphub/fliphub.git" 26 | }, 27 | "bugs": { 28 | "url": "https://github.com/fliphub/fliphub/issues" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /modules/inspector-gadget/cleaner/index.js: -------------------------------------------------------------------------------- 1 | const ChainedMap = require('chain-able/TraverseChain') 2 | // const traverse = require('./traverse') 3 | // const log = require('fliplog') 4 | 5 | let clone 6 | 7 | class Cleaner extends ChainedMap { 8 | /** 9 | * @param {Cleaner | Chainable | null} [parent=null] 10 | */ 11 | constructor(parent = null) { 12 | super(parent) 13 | this.data = this.obj.bind(this) 14 | this.clean = this.clean.bind(this) 15 | } 16 | 17 | /** 18 | * @param {Object | null} [obj=null] 19 | * @return {Cleaner} @chainable 20 | */ 21 | static init(obj = null) { 22 | if (obj === null) { 23 | return new Cleaner() 24 | } 25 | return new Cleaner().obj(obj).onMatch() 26 | } 27 | 28 | /** 29 | * @alias data 30 | * @param {Object | null} [obj=null] 31 | * @return {Cleaner} @chainable 32 | */ 33 | obj(obj = null) { 34 | if (!obj) return this 35 | return this.set('obj', obj) 36 | } 37 | 38 | /** 39 | * @desc clone the object - lodash.cloneDeep can infinitely loop so need a better one 40 | * @since fliplog:v0.3.0-beta6 41 | * @param {Object | any} [obj=null] 42 | * @return {Cleaner} @chainable 43 | */ 44 | clone(obj = null) { 45 | clone = clone || require('../../')('lodash.clonedeep') 46 | return this.set('obj', clone(obj)) 47 | } 48 | 49 | /** 50 | * @desc runs traverser, checks the tests, calls the onMatch 51 | * @modifies this.cleaned 52 | * @return {any} this.obj/data cleaned 53 | */ 54 | clean() { 55 | return this.set('cleaned', this.traverse(true)) 56 | } 57 | 58 | cleaned() { 59 | return this.get('cleaned') 60 | } 61 | } 62 | 63 | module.exports = Cleaner 64 | -------------------------------------------------------------------------------- /modules/inspector-gadget/cleaner/test.js: -------------------------------------------------------------------------------- 1 | const Cleaner = require('./') 2 | 3 | const eh = { 4 | me: true, 5 | nested: { 6 | really: { 7 | deep: { 8 | super: false, 9 | not: 'eh', 10 | canada: true, 11 | modules: [{parser: 'hi'}], 12 | }, 13 | matchme: 'minime', 14 | notme: 'eh', 15 | }, 16 | }, 17 | } 18 | 19 | const cleaned = Cleaner.init(eh) 20 | .keys([/super/, /parser/]) 21 | .vals([/minime/]) 22 | .clean() 23 | 24 | require('fliplog').quick(cleaned) 25 | -------------------------------------------------------------------------------- /modules/inspector-gadget/index.js: -------------------------------------------------------------------------------- 1 | const util = require('util') 2 | const inspector = require('./inspector') 3 | const inspectorGadget = require('./inspector-gadget') 4 | const cleaner = require('./cleaner') 5 | 6 | // for compatibility with nodejs + web 7 | let custom = function noop() {} 8 | if (util) { 9 | custom = util.inspect.defaultOptions.customInspect 10 | } 11 | 12 | module.exports = { 13 | cleaner, 14 | util, 15 | inspectorGadget, 16 | inspector, 17 | inspect: inspector, 18 | custom: (arg = false) => { 19 | if (arg !== true && arg !== false && arg !== null && arg !== undefined) { 20 | util.inspect.defaultOptions.customInspect = arg 21 | } 22 | else if (arg) { 23 | util.inspect.defaultOptions.customInspect = custom 24 | } 25 | else { 26 | util.inspect.defaultOptions.customInspect = false 27 | } 28 | return inspector 29 | }, 30 | } 31 | -------------------------------------------------------------------------------- /modules/inspector-gadget/inspector-gadget.js: -------------------------------------------------------------------------------- 1 | // https://www.bennadel.com/blog/2829-string-interpolation-using-util-format-and-util-inspect-in-node-js.htm 2 | const filter = [ 3 | 'helpers', 4 | 'addDebug', 5 | 'inspect', 6 | 'emit', 7 | 'on', 8 | 'debugFor', 9 | 'translator', 10 | 'appsByName', 11 | 12 | // these ones we might want to toggle on and off 13 | 'instance', 14 | 'api', 15 | 'evts', 16 | 'hubs', 17 | ] 18 | const inspectorGadget = (thisArg, moreFilters) => { 19 | return function(depth, options) { 20 | let toInspect = Object.keys(thisArg) 21 | .filter(key => !filter.includes(key)) 22 | 23 | if (Array.isArray(moreFilters)) 24 | toInspect = toInspect.filter(key => !moreFilters.includes(key)) 25 | // else if (typeof moreFilters === 'function') 26 | // toInspect = toInspect.map(key => moreFilters(key, this[key])) 27 | else if (typeof moreFilters === 'object') { 28 | // if (moreFilters.blacklist) 29 | if (moreFilters.whitelist) { 30 | toInspect = toInspect.filter(key => moreFilters.whitelist.includes(key)) 31 | } 32 | // if (moreFilters.val) { 33 | // return moreFilters.val 34 | // } 35 | // if (moreFilters.filter) 36 | // if (moreFilters.map) 37 | } 38 | 39 | let inspected = {} 40 | toInspect.forEach(key => { 41 | // @TODO: filter out .length on function... 42 | // let val = thisArg[key] 43 | // if (typeof val === 'function') 44 | inspected[key] = thisArg[key] 45 | }) 46 | return inspected 47 | } 48 | } 49 | 50 | module.exports = inspectorGadget 51 | -------------------------------------------------------------------------------- /modules/inspector-gadget/inspector.js: -------------------------------------------------------------------------------- 1 | const inspector = (msg, depth = 30, opts = {}) => { 2 | // allow taking in different depths 3 | if (!Number.isInteger(depth)) depth = 10 4 | const defaults = { 5 | depth, 6 | maxArrayLength: depth, 7 | showHidden: true, 8 | showProxy: true, 9 | colors: true, 10 | } 11 | opts = Object.assign(defaults, opts) 12 | 13 | const util = require('util') 14 | try { 15 | const inspected = util.inspect(msg, opts) 16 | return inspected 17 | } 18 | catch (e) { 19 | console.log(e) 20 | try { 21 | const stringify = require('../javascript-stringify') 22 | const stringified = stringify(msg, null, ' ') 23 | return stringified 24 | } 25 | catch (error) { 26 | return msg 27 | } 28 | } 29 | } 30 | 31 | module.exports = inspector 32 | -------------------------------------------------------------------------------- /modules/is-buffer/index.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Determine if an object is a Buffer 3 | * 4 | * @author Feross Aboukhadijeh 5 | * @license MIT 6 | */ 7 | 8 | // The _isBuffer check is for Safari 5-7 support, because it's missing 9 | // Object.prototype.constructor. Remove this eventually 10 | module.exports = function(obj) { 11 | return obj != null && (isBuffer(obj) || isSlowBuffer(obj) || !!obj._isBuffer) 12 | } 13 | 14 | function isBuffer(obj) { 15 | return ( 16 | !!obj.constructor && 17 | typeof obj.constructor.isBuffer === 'function' && 18 | obj.constructor.isBuffer(obj) 19 | ) 20 | } 21 | 22 | // For Node v0.10 support. Remove this eventually. 23 | function isSlowBuffer(obj) { 24 | return ( 25 | typeof obj.readFloatLE === 'function' && 26 | typeof obj.slice === 'function' && 27 | isBuffer(obj.slice(0, 0)) 28 | ) 29 | } 30 | -------------------------------------------------------------------------------- /modules/is-fullwidth-code-point/index.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable yoda */ 2 | module.exports = x => { 3 | if (Number.isNaN(x)) { 4 | return false 5 | } 6 | 7 | // code points are derived from: 8 | // http://www.unix.org/Public/UNIDATA/EastAsianWidth.txt 9 | if ( 10 | x >= 0x1100 && 11 | (x <= 0x115f || // Hangul Jamo 12 | x === 0x2329 || // LEFT-POINTING ANGLE BRACKET 13 | x === 0x232a || // RIGHT-POINTING ANGLE BRACKET 14 | // CJK Radicals Supplement .. Enclosed CJK Letters and Months 15 | (0x2e80 <= x && x <= 0x3247 && x !== 0x303f) || 16 | // Enclosed CJK Letters and Months .. CJK Unified Ideographs Extension A 17 | (0x3250 <= x && x <= 0x4dbf) || 18 | // CJK Unified Ideographs .. Yi Radicals 19 | (0x4e00 <= x && x <= 0xa4c6) || 20 | // Hangul Jamo Extended-A 21 | (0xa960 <= x && x <= 0xa97c) || 22 | // Hangul Syllables 23 | (0xac00 <= x && x <= 0xd7a3) || 24 | // CJK Compatibility Ideographs 25 | (0xf900 <= x && x <= 0xfaff) || 26 | // Vertical Forms 27 | (0xfe10 <= x && x <= 0xfe19) || 28 | // CJK Compatibility Forms .. Small Form Variants 29 | (0xfe30 <= x && x <= 0xfe6b) || 30 | // Halfwidth and Fullwidth Forms 31 | (0xff01 <= x && x <= 0xff60) || 32 | (0xffe0 <= x && x <= 0xffe6) || 33 | // Kana Supplement 34 | (0x1b000 <= x && x <= 0x1b001) || 35 | // Enclosed Ideographic Supplement 36 | (0x1f200 <= x && x <= 0x1f251) || 37 | // CJK Unified Ideographs Extension B .. Tertiary Ideographic Plane 38 | (0x20000 <= x && x <= 0x3fffd)) 39 | ) { 40 | return true 41 | } 42 | 43 | return false 44 | } 45 | -------------------------------------------------------------------------------- /modules/is-nodejs/index.js: -------------------------------------------------------------------------------- 1 | // const timer = require('fliptime') 2 | // this takes ~60 microseconds 3 | // timer.start('is-node-webworker-web') 4 | 5 | // http://stackoverflow.com/questions/4224606/how-to-check-whether-a-script-is-running-under-node-js 6 | const isNode = 7 | typeof process === 'object' && 8 | typeof process.release === 'object' && 9 | process.release.name === 'node' && 10 | typeof module !== 'undefined' && 11 | typeof global === 'object' 12 | 13 | // this.window = this // works 14 | const isWeb = !!(typeof this === 'object' && 15 | this.window && 16 | this.window === this) 17 | 18 | // http://stackoverflow.com/questions/7931182/reliably-detect-if-the-script-is-executing-in-a-web-worker 19 | const isWebWorker = 20 | isNode === false && 21 | typeof WorkerGlobalScope !== 'undefined' && 22 | typeof self !== 'undefined' && 23 | self instanceof WorkerGlobalScope // eslint-disable-line 24 | 25 | // could be polyfil 26 | const hasWindow = typeof window !== 'undefined' 27 | 28 | // timer.stop('is-node-webworker-web').log('is-node-webworker-web') 29 | 30 | module.exports = { 31 | isNode: isNode && !isWeb, 32 | isWeb, 33 | hasWindow, 34 | isWebWorker, 35 | } 36 | -------------------------------------------------------------------------------- /modules/is-number/index.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * is-number 3 | * 4 | * Copyright (c) 2014-2015, Jon Schlinkert. 5 | * Licensed under the MIT License. 6 | */ 7 | 8 | var typeOf = require('../')('kind-of') 9 | 10 | module.exports = function isNumber(num) { 11 | var type = typeOf(num) 12 | 13 | if (type === 'string') { 14 | if (!num.trim()) return false 15 | } 16 | else if (type !== 'number') { 17 | return false 18 | } 19 | 20 | return num - num + 1 >= 0 21 | } 22 | -------------------------------------------------------------------------------- /modules/kind-of/index.js: -------------------------------------------------------------------------------- 1 | // https://www.npmjs.com/package/kind-of 2 | var toString = Object.prototype.toString 3 | 4 | /** 5 | * @desc Get the native `typeof` a value. 6 | * @param {any} val 7 | * @return {string} Native javascript type 8 | */ 9 | module.exports = function kindOf(val) { 10 | const vtypeof = typeof val 11 | 12 | // primitivies 13 | if (vtypeof === 'undefined') { 14 | return 'undefined' 15 | } 16 | if (val === null) { 17 | return 'null' 18 | } 19 | if (val === true || val === false || val instanceof Boolean) { 20 | return 'boolean' 21 | } 22 | if (vtypeof === 'string' || val instanceof String) { 23 | return 'string' 24 | } 25 | if (vtypeof === 'number' || val instanceof Number) { 26 | return 'number' 27 | } 28 | // functions 29 | if (vtypeof === 'function' || val instanceof Function) { 30 | return 'function' 31 | } 32 | 33 | // array 34 | if (typeof Array.isArray !== 'undefined' && Array.isArray(val)) { 35 | return 'array' 36 | } 37 | 38 | // check for instances of RegExp and Date before calling `toString` 39 | if (val instanceof RegExp) { 40 | return 'regexp' 41 | } 42 | if (val instanceof Date) { 43 | return 'date' 44 | } 45 | 46 | if (val instanceof Set) { 47 | return 'set' 48 | } 49 | if (val instanceof Map) { 50 | return 'map' 51 | } 52 | 53 | // other objects 54 | var type = toString.call(val) 55 | 56 | if (type === '[object RegExp]') { 57 | return 'regexp' 58 | } 59 | if (type === '[object Date]') { 60 | return 'date' 61 | } 62 | if (type === '[object Arguments]') { 63 | return 'arguments' 64 | } 65 | if (type === '[object Error]') { 66 | return 'error' 67 | } 68 | if (type === '[object Promise]') { 69 | return 'promise' 70 | } 71 | 72 | // buffer 73 | if ( 74 | val != null && 75 | !!val.constructor && 76 | typeof val.constructor.isBuffer === 'function' && 77 | val.constructor.isBuffer(val) 78 | ) { 79 | return 'buffer' 80 | } 81 | 82 | // es6: Map, WeakMap, Set, WeakSet 83 | if (type === '[object WeakSet]') { 84 | return 'weakset' 85 | } 86 | if (type === '[object WeakMap]') { 87 | return 'weakmap' 88 | } 89 | if (type === '[object Symbol]') { 90 | return 'symbol' 91 | } 92 | 93 | // typed arrays 94 | if (type.includes('Array') === true) { 95 | return type 96 | .replace('[', '') 97 | .replace(']', '') 98 | .replace('object ', '') 99 | .toLowerCase() 100 | } 101 | 102 | // must be a plain object 103 | return 'object' 104 | } 105 | -------------------------------------------------------------------------------- /modules/log-symbols/index.js: -------------------------------------------------------------------------------- 1 | // https://github.com/sindresorhus/log-symbols/blob/master/index.js 2 | 3 | var chalk = require('../')('chalk') 4 | 5 | var main = { 6 | info: chalk.blue('ℹ'), 7 | success: chalk.green('✔'), 8 | warning: chalk.yellow('⚠'), 9 | error: chalk.red('✖'), 10 | } 11 | 12 | var win = { 13 | info: chalk.blue('i'), 14 | success: chalk.green('√'), 15 | warning: chalk.yellow('‼'), 16 | error: chalk.red('×'), 17 | } 18 | 19 | module.exports = process.platform === 'win32' ? win : main 20 | -------------------------------------------------------------------------------- /modules/log-update/index.js: -------------------------------------------------------------------------------- 1 | const ansiEscapes = require('../')('ansi-escapes') 2 | const cliCursor = require('../')('cli-cursor') 3 | const wrapAnsi = require('../')('wrap-ansi') 4 | 5 | // const {ansiEscapes, cliCursor, wrapAnsi} = require('../')([ 6 | // 'ansi-scapes', 7 | // 'cli-cursor', 8 | // 'wrap-ansi', 9 | // ]) 10 | 11 | const main = stream => { 12 | let prevLineCount = 0 13 | 14 | const render = function() { 15 | cliCursor.hide() 16 | let out = [].join.call(arguments, ' ') + '\n' 17 | out = wrapAnsi(out, process.stdout.columns || 80, {wordWrap: false}) 18 | stream.write(ansiEscapes.eraseLines(prevLineCount) + out) 19 | prevLineCount = out.split('\n').length 20 | } 21 | 22 | render.clear = () => { 23 | stream.write(ansiEscapes.eraseLines(prevLineCount)) 24 | prevLineCount = 0 25 | } 26 | 27 | render.done = () => { 28 | prevLineCount = 0 29 | cliCursor.show() 30 | } 31 | 32 | return render 33 | } 34 | 35 | module.exports = main(process.stdout) 36 | module.exports.stderr = main(process.stderr) 37 | module.exports.create = main 38 | -------------------------------------------------------------------------------- /modules/longest/index.js: -------------------------------------------------------------------------------- 1 | // https://github.com/jonschlinkert/longest/blob/master/index.js 2 | // should not be a while loop 3 | module.exports = function longest(arr) { 4 | if (!Array.isArray(arr)) { 5 | throw new TypeError('expected an array') 6 | } 7 | 8 | var len = arr.length 9 | if (len === 0) { 10 | return undefined 11 | } 12 | 13 | var val = arr[0] 14 | var longest = val.length 15 | var idx = 0 16 | 17 | while (++idx < len) { 18 | var ele = arr[idx] 19 | if (ele == null) { 20 | continue 21 | } 22 | 23 | var elen = ele.length 24 | if (typeof elen !== 'number') { 25 | continue 26 | } 27 | 28 | if (elen > longest) { 29 | longest = elen 30 | val = ele 31 | } 32 | } 33 | return val 34 | } 35 | -------------------------------------------------------------------------------- /modules/lpad-align/index.js: -------------------------------------------------------------------------------- 1 | const indentString = require('../indent-string') 2 | const longest = require('../longest') 3 | 4 | // https://github.com/kevva/lpad-align/blob/master/index.js 5 | module.exports = function lpadalign(str, arr, indent) { 6 | if (typeof str !== 'string') { 7 | throw new TypeError(`Expected a \`string\`, got \`${typeof str}\``) 8 | } 9 | 10 | if (!Array.isArray(arr)) { 11 | throw new TypeError(`Expected an \`Array\`, got \`${typeof arr}\``) 12 | } 13 | 14 | return indentString(str, (indent || 0) + longest(arr).length - str.length) 15 | } 16 | -------------------------------------------------------------------------------- /modules/mimic-fn/index.js: -------------------------------------------------------------------------------- 1 | // https://github.com/sindresorhus/mimic-fn/blob/master/index.js 2 | module.exports = (to, from) => { 3 | // TODO: use `Reflect.ownKeys()` when targeting Node.js 6 4 | for (const prop of Object.getOwnPropertyNames(from).concat( 5 | Object.getOwnPropertySymbols(from) 6 | )) { 7 | Object.defineProperty(to, prop, Object.getOwnPropertyDescriptor(from, prop)) 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /modules/multispinner/README.md: -------------------------------------------------------------------------------- 1 | https://github.com/codekirei/node-multispinner 2 | -------------------------------------------------------------------------------- /modules/multispinner/lib/constants.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | //---------------------------------------------------------- 4 | // Modules 5 | //---------------------------------------------------------- 6 | // NPM 7 | const logUpdate = require('../../log-update') 8 | const figures = require('../../figures') 9 | 10 | //---------------------------------------------------------- 11 | // Constants 12 | //---------------------------------------------------------- 13 | const states = { 14 | incomplete: 'incomplete', 15 | success: 'success', 16 | error: 'error', 17 | } 18 | 19 | const defaultProps = { 20 | //---------------------------------------------------------- 21 | // Configurable props 22 | //---------------------------------------------------------- 23 | // can be overwritten by opts in constructor 24 | 'autoStart': true, 25 | 'clear': false, 26 | 'frames': ['-', '\\', '|', '/'], 27 | 'indent': 2, 28 | 'interval': 80, 29 | 'postText': '', 30 | 'preText': '', 31 | get 'color'() { 32 | const colors = {} 33 | colors[states.incomplete] = 'blue' 34 | colors[states.success] = 'green' 35 | colors[states.error] = 'red' 36 | return colors 37 | }, 38 | get 'symbol'() { 39 | const symbols = {} 40 | // symbols[states.incomplete] = this.frames[0] 41 | // symbols[states.incomplete] = null 42 | symbols[states.success] = figures.tick 43 | symbols[states.error] = figures.cross 44 | return symbols 45 | }, 46 | 47 | //---------------------------------------------------------- 48 | // Internal props 49 | //---------------------------------------------------------- 50 | 'i': 0, 51 | 'update': logUpdate, 52 | } 53 | 54 | //---------------------------------------------------------- 55 | // Exports 56 | //---------------------------------------------------------- 57 | module.exports = { 58 | states, 59 | defaultProps, 60 | } 61 | -------------------------------------------------------------------------------- /modules/multispinner/lib/errs.js: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------- 2 | // Setup 3 | //---------------------------------------------------------- 4 | const name = 'node-multispinner' 5 | 6 | //---------------------------------------------------------- 7 | // validOpts errs 8 | //---------------------------------------------------------- 9 | /** 10 | * @func configurable 11 | * @desc Throws because opt is not a configurable prop. 12 | * @param {string} opt - opt that caused err 13 | * @throws Error 14 | */ 15 | function configurable(opt) { 16 | throw new Error( 17 | `${name}: ${opt} is not a configurable property` 18 | ) 19 | } 20 | 21 | /** 22 | * @func optType 23 | * @desc Throws because opt is incorrect type. 24 | * @param {string} opt - opt that caused err 25 | * @param {string} type - name of type that opt should be 26 | * @throws Error 27 | */ 28 | function optType(opt, type) { 29 | throw new Error( 30 | `${name}: ${opt} option must have a value of type ${type}` 31 | ) 32 | } 33 | 34 | /** 35 | * @func optsType 36 | * @desc Throws because opts is not an object. 37 | * @throws Error 38 | */ 39 | function optsType() { 40 | throw new Error( 41 | `${name}: opts param must be an object` 42 | ) 43 | } 44 | 45 | function negative(opt) { 46 | throw new Error( 47 | `${name}: ${opt} must be greater than or equal to 0` 48 | ) 49 | } 50 | 51 | //---------------------------------------------------------- 52 | // spinners errs 53 | //---------------------------------------------------------- 54 | /** 55 | * @func spinnersType 56 | * @desc Throws because spinners is not an object or array. 57 | * @throws Error 58 | */ 59 | function spinnersType() { 60 | throw new Error( 61 | `${name}: spinners param is not an object or array` 62 | ) 63 | } 64 | 65 | /** 66 | * @func spinnersEmpty 67 | * @desc Throws beacuse spinners is empty. 68 | * @throws Error 69 | */ 70 | function spinnersEmpty() { 71 | throw new Error( 72 | `${name}: object or array of spinners is empty` 73 | ) 74 | } 75 | 76 | function unique(spinner) { 77 | throw new Error( 78 | `${name}: there are multiple spinners with ID '${spinner}'` 79 | ) 80 | } 81 | 82 | //---------------------------------------------------------- 83 | // index errs 84 | //---------------------------------------------------------- 85 | /** 86 | * @func invalidState 87 | * @desc Throws because state is not a valid. 88 | * @param {string} state - invalid state that was used 89 | * @throws Error 90 | */ 91 | function invalidState(state) { 92 | throw new Error( 93 | `${name}: ${state} is not a valid spinner state` 94 | ) 95 | } 96 | 97 | //---------------------------------------------------------- 98 | // Export 99 | //---------------------------------------------------------- 100 | module.exports = { 101 | validOpts: { 102 | configurable, 103 | optType, 104 | optsType, 105 | negative, 106 | }, 107 | spinners: { 108 | spinnersType, 109 | spinnersEmpty, 110 | unique, 111 | }, 112 | index: { 113 | invalidState, 114 | }, 115 | } 116 | -------------------------------------------------------------------------------- /modules/multispinner/lib/validOpts.js: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------- 2 | // Modules 3 | //---------------------------------------------------------- 4 | // NPM 5 | const kindOf = require('../../')('kind-of') 6 | // Local 7 | const errs = require('./errs').validOpts 8 | const defaultProps = require('./constants').defaultProps 9 | 10 | //---------------------------------------------------------- 11 | // Logic 12 | //---------------------------------------------------------- 13 | /** 14 | * @func validOpts 15 | * @desc Check validity of options object. 16 | * @param {object} opts - options to check 17 | * @return {bool} true if opts are valid; else false 18 | */ 19 | module.exports = function validOptions(opts) { 20 | if (opts) { 21 | // throw if opts is not an object 22 | if (kindOf(opts) !== 'object') errs.optsType() 23 | 24 | Object.keys(opts).map(opt => { 25 | // throw if opt is not a configurable prop 26 | if (!defaultProps.hasOwnProperty(opt)) errs.configurable(opt) 27 | 28 | // throw if opt is not correct type 29 | const optType = kindOf(opts[opt]) 30 | const defaultType = kindOf(defaultProps[opt]) 31 | if (optType !== defaultType) errs.optType(opt, defaultType) 32 | 33 | // throw if opt is negative number 34 | if (optType === 'number' && opts[opt] < 0) errs.negative(opt) 35 | }) 36 | 37 | // opts are valid => return true 38 | return true 39 | } 40 | 41 | // no opts passed => return false 42 | return false 43 | } 44 | -------------------------------------------------------------------------------- /modules/nanoseconds/index.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * https://github.com/jonschlinkert/nanoseconds/blob/master/index.js 3 | * nanoseconds 4 | * 5 | * Copyright (c) 2015, Jon Schlinkert. 6 | * Licensed under the MIT License. 7 | */ 8 | 9 | module.exports = function nanoseconds(time) { 10 | if (!Array.isArray(time) || time.length !== 2) { 11 | throw new TypeError('expected an array from process.hrtime()') 12 | } 13 | return +time[0] * 1e9 + +time[1] 14 | } 15 | -------------------------------------------------------------------------------- /modules/node-notifier/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "semistandard", 3 | "env": { 4 | "node": true, 5 | "jest": true 6 | }, 7 | "rules": { 8 | "space-before-function-paren": 0, 9 | "no-control-regex": 0 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /modules/node-notifier/DECISION_FLOW.md: -------------------------------------------------------------------------------- 1 | # What reporting system is used? 2 | 3 | There are 5 different reporting systems: 4 | 5 | * Mac Notification Center 6 | * Linux notify-osd 7 | * Windows Toaster 8 | * Windows Balloons 9 | * Growl 10 | 11 | `node-notifier` tries to use the system that has the better 12 | experience but prefers native solutions. This means that 13 | Growl is prioritized over Windows Balloons (if Growl is 14 | active). 15 | 16 | See flow chart to see how the reporter is chosen. 17 | 18 | ![Flow Chart](./node-notifier_flow.png) -------------------------------------------------------------------------------- /modules/node-notifier/example/advanced.js: -------------------------------------------------------------------------------- 1 | var notifier = require('../'); 2 | var nc = new notifier.NotificationCenter(); 3 | var path = require('path'); 4 | 5 | nc.notify( 6 | { 7 | title: 'Phil Coulson', 8 | subtitle: 'Agent of S.H.I.E.L.D.', 9 | message: "If I come out, will you shoot me? 'Cause then I won't come out.", 10 | sound: 'Funk', 11 | // case sensitive 12 | wait: true, 13 | appIcon: path.join(__dirname, 'coulson.jpg'), 14 | contentImage: path.join(__dirname, 'coulson.jpg'), 15 | open: 'file://' + path.join(__dirname, 'coulson.jpg') 16 | }, 17 | function() { 18 | console.log(arguments); 19 | } 20 | ); 21 | -------------------------------------------------------------------------------- /modules/node-notifier/example/coulson.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fliphub/fliplog/b0a1581e749a41ab65731f88cc90f2c24d20247d/modules/node-notifier/example/coulson.jpg -------------------------------------------------------------------------------- /modules/node-notifier/example/growl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fliphub/fliplog/b0a1581e749a41ab65731f88cc90f2c24d20247d/modules/node-notifier/example/growl.png -------------------------------------------------------------------------------- /modules/node-notifier/example/input-example.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fliphub/fliplog/b0a1581e749a41ab65731f88cc90f2c24d20247d/modules/node-notifier/example/input-example.gif -------------------------------------------------------------------------------- /modules/node-notifier/example/mac.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fliphub/fliplog/b0a1581e749a41ab65731f88cc90f2c24d20247d/modules/node-notifier/example/mac.png -------------------------------------------------------------------------------- /modules/node-notifier/example/macInput.js: -------------------------------------------------------------------------------- 1 | var notifier = require('../'); 2 | var nc = new notifier.NotificationCenter(); 3 | 4 | var trueAnswer = 'Most def.'; 5 | 6 | nc.notify( 7 | { 8 | title: 'Notifications', 9 | message: 'Are they cool?', 10 | sound: 'Funk', 11 | // case sensitive 12 | closeLabel: 'Absolutely not', 13 | actions: trueAnswer 14 | }, 15 | function(err, response, metadata) { 16 | if (err) throw err; 17 | console.log(metadata); 18 | 19 | if (metadata.activationValue !== trueAnswer) { 20 | return; // No need to continue 21 | } 22 | 23 | nc.notify( 24 | { 25 | title: 'Notifications', 26 | message: 'Do you want to reply to them?', 27 | sound: 'Funk', 28 | // case sensitive 29 | reply: true 30 | }, 31 | function(err, response, metadata) { 32 | if (err) throw err; 33 | console.log(metadata); 34 | } 35 | ); 36 | } 37 | ); 38 | 39 | nc.on('replied', function(obj, options, metadata) { 40 | console.log('User replied', metadata); 41 | }); 42 | -------------------------------------------------------------------------------- /modules/node-notifier/example/message.js: -------------------------------------------------------------------------------- 1 | var notifier = require('../index'); 2 | 3 | notifier.notify({ message: 'Hello', wait: true }, function(err, data) { 4 | // Will also wait until notification is closed. 5 | console.log('Waited'); 6 | console.log(err, data); 7 | }).on('click', function() { 8 | console.log(arguments); 9 | }); 10 | -------------------------------------------------------------------------------- /modules/node-notifier/example/toaster.js: -------------------------------------------------------------------------------- 1 | var notifier = require('../index'); 2 | var path = require('path'); 3 | 4 | notifier.notify( 5 | { 6 | message: 'Hello. This is a longer text\nWith "some" newlines.', 7 | wait: true, 8 | icon: path.join(__dirname, 'coulson.jpg'), 9 | sound: true 10 | }, 11 | function(err, data) { 12 | // Will also wait until notification is closed. 13 | console.log('Waited'); 14 | console.log(err, data); 15 | } 16 | ); 17 | 18 | notifier.on('timeout', function() { 19 | console.log('Timed out!'); 20 | }); 21 | 22 | notifier.on('click', function() { 23 | console.log('Clicked!'); 24 | }); 25 | -------------------------------------------------------------------------------- /modules/node-notifier/example/windows.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fliphub/fliplog/b0a1581e749a41ab65731f88cc90f2c24d20247d/modules/node-notifier/example/windows.png -------------------------------------------------------------------------------- /modules/node-notifier/index.js: -------------------------------------------------------------------------------- 1 | var os = require('os'); 2 | var utils = require('./lib/utils'); 3 | 4 | // All notifiers 5 | var NotifySend = require('./notifiers/notifysend'); 6 | var NotificationCenter = require('./notifiers/notificationcenter'); 7 | var WindowsToaster = require('./notifiers/toaster'); 8 | var Growl = require('./notifiers/growl'); 9 | var WindowsBalloon = require('./notifiers/balloon'); 10 | 11 | var options = { withFallback: true }; 12 | 13 | switch (os.type()) { 14 | case 'Linux': 15 | module.exports = new NotifySend(options); 16 | module.exports.Notification = NotifySend; 17 | break; 18 | case 'Darwin': 19 | module.exports = new NotificationCenter(options); 20 | module.exports.Notification = NotificationCenter; 21 | break; 22 | case 'Windows_NT': 23 | if (utils.isLessThanWin8()) { 24 | module.exports = new WindowsBalloon(options); 25 | module.exports.Notification = WindowsBalloon; 26 | } else { 27 | module.exports = new WindowsToaster(options); 28 | module.exports.Notification = WindowsToaster; 29 | } 30 | break; 31 | default: 32 | if (os.type().match(/BSD$/)) { 33 | module.exports = new NotifySend(options); 34 | module.exports.Notification = NotifySend; 35 | } else { 36 | module.exports = new Growl(options); 37 | module.exports.Notification = Growl; 38 | } 39 | } 40 | 41 | // Expose notifiers to give full control. 42 | module.exports.NotifySend = NotifySend; 43 | module.exports.NotificationCenter = NotificationCenter; 44 | module.exports.WindowsToaster = WindowsToaster; 45 | module.exports.WindowsBalloon = WindowsBalloon; 46 | module.exports.Growl = Growl; 47 | -------------------------------------------------------------------------------- /modules/node-notifier/lib/checkGrowl.js: -------------------------------------------------------------------------------- 1 | var net = require('net'); 2 | 3 | var hasGrowl = false; 4 | module.exports = function(growlConfig, cb) { 5 | if (typeof cb === 'undefined') { 6 | cb = growlConfig; 7 | growlConfig = {}; 8 | } 9 | if (hasGrowl) return cb(hasGrowl); 10 | var port = growlConfig.port || 23053; 11 | var host = growlConfig.host || 'localhost'; 12 | var socket = net.connect(port, host); 13 | socket.setTimeout(100); 14 | 15 | socket.on('connect', function() { 16 | socket.end(); 17 | cb(true); 18 | }); 19 | 20 | socket.on('error', function() { 21 | socket.end(); 22 | cb(false); 23 | }); 24 | }; 25 | -------------------------------------------------------------------------------- /modules/node-notifier/notifiers/growl.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Wrapper for the growly module 3 | */ 4 | var checkGrowl = require('../lib/checkGrowl'); 5 | var utils = require('../lib/utils'); 6 | var requirePkg = require('../../') 7 | var growly = requirePkg('growly'); 8 | 9 | var EventEmitter = require('events').EventEmitter; 10 | var util = require('util'); 11 | 12 | var errorMessageNotFound = "Couldn't connect to growl (might be used as a fallback). Make sure it is running"; 13 | 14 | module.exports = Growl; 15 | 16 | var hasGrowl = void 0; 17 | 18 | function Growl(options) { 19 | options = utils.clone(options || {}); 20 | if (!(this instanceof Growl)) { 21 | return new Growl(options); 22 | } 23 | 24 | growly.appname = options.name || 'Node'; 25 | this.options = options; 26 | 27 | EventEmitter.call(this); 28 | } 29 | util.inherits(Growl, EventEmitter); 30 | 31 | Growl.prototype.notify = function(options, callback) { 32 | growly.setHost(this.options.host, this.options.port); 33 | options = utils.clone(options || {}); 34 | 35 | if (typeof options === 'string') { 36 | options = { title: 'node-notifier', message: options }; 37 | } 38 | 39 | callback = utils.actionJackerDecorator(this, options, callback, function( 40 | data 41 | ) { 42 | if (data === 'click') { 43 | return 'click'; 44 | } 45 | if (data === 'timedout') { 46 | return 'timeout'; 47 | } 48 | return false; 49 | }); 50 | 51 | options = utils.mapToGrowl(options); 52 | 53 | if (!options.message) { 54 | callback(new Error('Message is required.')); 55 | return this; 56 | } 57 | 58 | options.title = options.title || 'Node Notification:'; 59 | 60 | if (hasGrowl || !!options.wait) { 61 | var localCallback = options.wait ? callback : noop; 62 | growly.notify(options.message, options, localCallback); 63 | if (!options.wait) callback(); 64 | return this; 65 | } 66 | 67 | checkGrowl(growly, function(didHaveGrowl) { 68 | hasGrowl = didHaveGrowl; 69 | if (!didHaveGrowl) return callback(new Error(errorMessageNotFound)); 70 | growly.notify(options.message, options); 71 | callback(); 72 | }); 73 | return this; 74 | }; 75 | 76 | function noop() { 77 | } 78 | -------------------------------------------------------------------------------- /modules/node-notifier/notifiers/notifysend.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Node.js wrapper for "notify-send". 3 | */ 4 | var os = require('os'); 5 | var requirePkg = require('../../'); 6 | var which = requirePkg('which'); 7 | var utils = require('../lib/utils'); 8 | 9 | var EventEmitter = require('events').EventEmitter; 10 | var util = require('util'); 11 | 12 | var notifier = 'notify-send'; 13 | var hasNotifier = void 0; 14 | 15 | module.exports = NotifySend; 16 | 17 | function NotifySend(options) { 18 | options = utils.clone(options || {}); 19 | if (!(this instanceof NotifySend)) { 20 | return new NotifySend(options); 21 | } 22 | 23 | this.options = options; 24 | 25 | EventEmitter.call(this); 26 | } 27 | util.inherits(NotifySend, EventEmitter); 28 | 29 | function noop() { 30 | } 31 | NotifySend.prototype.notify = function(options, callback) { 32 | options = utils.clone(options || {}); 33 | callback = callback || noop; 34 | 35 | if (typeof callback !== 'function') { 36 | throw new TypeError( 37 | 'The second argument must be a function callback. You have passed ' + 38 | typeof callback 39 | ); 40 | } 41 | 42 | if (typeof options === 'string') { 43 | options = { title: 'node-notifier', message: options }; 44 | } 45 | 46 | if (!options.message) { 47 | callback(new Error('Message is required.')); 48 | return this; 49 | } 50 | 51 | if (os.type() !== 'Linux' && !os.type().match(/BSD$/)) { 52 | callback(new Error('Only supported on Linux and *BSD systems')); 53 | return this; 54 | } 55 | 56 | if (hasNotifier === false) { 57 | callback(new Error('notify-send must be installed on the system.')); 58 | return this; 59 | } 60 | 61 | if (hasNotifier || !!this.options.suppressOsdCheck) { 62 | doNotification(options, callback); 63 | return this; 64 | } 65 | 66 | try { 67 | hasNotifier = !!which.sync(notifier); 68 | doNotification(options, callback); 69 | } catch (err) { 70 | hasNotifier = false; 71 | return callback(err); 72 | } 73 | 74 | return this; 75 | }; 76 | 77 | var allowedArguments = [ 'urgency', 'expire-time', 'icon', 'category', 'hint' ]; 78 | 79 | function doNotification(options, callback) { 80 | var initial, argsList; 81 | 82 | options = utils.mapToNotifySend(options); 83 | options.title = options.title || 'Node Notification:'; 84 | 85 | initial = [ options.title, options.message ]; 86 | delete options.title; 87 | delete options.message; 88 | 89 | argsList = utils.constructArgumentList(options, { 90 | initial: initial, 91 | keyExtra: '-', 92 | allowedArguments: allowedArguments 93 | }); 94 | 95 | utils.command(notifier, argsList, callback); 96 | } 97 | -------------------------------------------------------------------------------- /modules/node-notifier/notifiers/toaster.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Wrapper for the toaster (https://github.com/nels-o/toaster) 3 | */ 4 | var path = require('path'); 5 | var notifier = path.resolve(__dirname, '../vendor/snoreToast/SnoreToast.exe'); 6 | var utils = require('../lib/utils'); 7 | var Balloon = require('./balloon'); 8 | 9 | var EventEmitter = require('events').EventEmitter; 10 | var util = require('util'); 11 | 12 | var fallback = void 0; 13 | 14 | module.exports = WindowsToaster; 15 | 16 | function WindowsToaster(options) { 17 | options = utils.clone(options || {}); 18 | if (!(this instanceof WindowsToaster)) { 19 | return new WindowsToaster(options); 20 | } 21 | 22 | this.options = options; 23 | 24 | EventEmitter.call(this); 25 | } 26 | util.inherits(WindowsToaster, EventEmitter); 27 | 28 | function noop() { 29 | } 30 | 31 | var timeoutMessage = 'the toast has timed out'; 32 | var successMessage = 'user clicked on the toast'; 33 | 34 | function hasText(str, txt) { 35 | return str && str.indexOf(txt) !== -1; 36 | } 37 | 38 | WindowsToaster.prototype.notify = function(options, callback) { 39 | options = utils.clone(options || {}); 40 | callback = callback || noop; 41 | 42 | if (typeof options === 'string') { 43 | options = { title: 'node-notifier', message: options }; 44 | } 45 | 46 | if (typeof callback !== 'function') { 47 | throw new TypeError( 48 | 'The second argument must be a function callback. You have passed ' + 49 | typeof fn 50 | ); 51 | } 52 | 53 | var actionJackedCallback = utils.actionJackerDecorator( 54 | this, 55 | options, 56 | function cb(err, data) { 57 | // Needs to filter out timeout. Not an actual error. 58 | if (err && hasText(data, timeoutMessage)) { 59 | return callback(null, data); 60 | } 61 | callback(err, data); 62 | }, 63 | function mapper(data) { 64 | if (hasText(data, successMessage)) { 65 | return 'click'; 66 | } 67 | if (hasText(data, timeoutMessage)) { 68 | return 'timeout'; 69 | } 70 | return false; 71 | } 72 | ); 73 | 74 | options.title = options.title || 'Node Notification:'; 75 | if ( 76 | typeof options.message === 'undefined' && 77 | typeof options.close === 'undefined' 78 | ) { 79 | callback(new Error('Message or ID to close is required.')); 80 | return this; 81 | } 82 | 83 | if (!utils.isWin8() && !!this.options.withFallback) { 84 | fallback = fallback || new Balloon(this.options); 85 | return fallback.notify(options, callback); 86 | } 87 | 88 | options = utils.mapToWin8(options); 89 | var argsList = utils.constructArgumentList(options, { 90 | explicitTrue: true, 91 | wrapper: '', 92 | keepNewlines: true, 93 | noEscape: true 94 | }); 95 | utils.fileCommand( 96 | this.options.customPath || notifier, 97 | argsList, 98 | actionJackedCallback 99 | ); 100 | return this; 101 | }; 102 | -------------------------------------------------------------------------------- /modules/node-notifier/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "node-notifier", 3 | "version": "5.1.2", 4 | "description": "A Node.js module for sending notifications on native Mac, Windows (post and pre 8) and Linux (or Growl as fallback)", 5 | "main": "index.js", 6 | "scripts": { 7 | "pretest": "npm run lint", 8 | "test": "jest", 9 | "example": "node ./example/message.js", 10 | "example:mac": "node ./example/advanced.js", 11 | "example:mac:input": "node ./example/macInput.js", 12 | "example:windows": "node ./example/toaster.js", 13 | "lint": "eslint example/*.js lib/*.js notifiers/*.js test/**/*.js index.js" 14 | }, 15 | "jest": { 16 | "testRegex": "/test/[^_]*.js", 17 | "testEnvironment": "node", 18 | "setupTestFrameworkScriptFile": "./test/_test-matchers.js" 19 | }, 20 | "repository": { 21 | "type": "git", 22 | "url": "git+ssh://git@github.com/mikaelbr/node-notifier.git" 23 | }, 24 | "keywords": [ 25 | "notification center", 26 | "mac os x 10.8", 27 | "notify", 28 | "terminal-notifier", 29 | "notify-send", 30 | "growl", 31 | "windows 8 notification", 32 | "toaster", 33 | "notification" 34 | ], 35 | "author": "Mikael Brevik", 36 | "license": "MIT", 37 | "devDependencies": { 38 | "eslint": "^3.13.1", 39 | "eslint-config-semistandard": "^7.0.0", 40 | "eslint-config-standard": "^6.2.1", 41 | "eslint-plugin-promise": "^3.4.0", 42 | "eslint-plugin-standard": "^2.0.1", 43 | "jest": "^18.1.0" 44 | }, 45 | "dependencies": { 46 | "growly": "^1.3.0", 47 | "semver": "^5.3.0", 48 | "shellwords": "^0.1.0", 49 | "which": "^1.2.12" 50 | }, 51 | "bugs": { 52 | "url": "https://github.com/mikaelbr/node-notifier/issues" 53 | }, 54 | "homepage": "https://github.com/mikaelbr/node-notifier#readme", 55 | "directories": { 56 | "example": "example", 57 | "test": "test" 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /modules/node-notifier/test/_test-matchers.js: -------------------------------------------------------------------------------- 1 | expect.extend({ 2 | toEndWith(received, actual) { 3 | const pass = endsWith(received, actual); 4 | const message = () => 5 | `expected ${received} ${pass ? 'not ' : ''} to end with ${actual}`; 6 | return { message, pass }; 7 | } 8 | }); 9 | 10 | function endsWith(subjectString, searchString, position) { 11 | if ( 12 | typeof position !== 'number' || 13 | !isFinite(position) || 14 | Math.floor(position) !== position || 15 | position > subjectString.length 16 | ) { 17 | position = subjectString.length; 18 | } 19 | position -= searchString.length; 20 | var lastIndex = subjectString.lastIndexOf(searchString, position); 21 | return lastIndex !== -1 && lastIndex === position; 22 | } 23 | -------------------------------------------------------------------------------- /modules/node-notifier/test/_test-utils.js: -------------------------------------------------------------------------------- 1 | module.exports.argsListHas = function argsListHas(args, field) { 2 | return args.filter(function(item) { 3 | return item === field; 4 | }).length > 0; 5 | }; 6 | 7 | module.exports.getOptionValue = function getOptionValue(args, field) { 8 | for (var i = 0; i < args.length; i++) { 9 | if (args[i] === field && i < args.length - 1) { 10 | return args[i + 1]; 11 | } 12 | } 13 | return void 0; 14 | }; 15 | -------------------------------------------------------------------------------- /modules/node-notifier/test/fixture/coulson.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fliphub/fliplog/b0a1581e749a41ab65731f88cc90f2c24d20247d/modules/node-notifier/test/fixture/coulson.jpg -------------------------------------------------------------------------------- /modules/node-notifier/test/fixture/listAll.txt: -------------------------------------------------------------------------------- 1 | GroupID Title Subtitle Message Delivered At 2 | (null) Terminal (null) Hello World 2014-05-27 15:23:11 +0000 3 | (null) Terminal (null) 2014-05-27 14:42:24 +0000 -------------------------------------------------------------------------------- /modules/node-notifier/test/fixture/removeAll.txt: -------------------------------------------------------------------------------- 1 | * Removing previously sent notification, which was sent on: 2014-05-27 15:23:11 +0000 2 | * Removing previously sent notification, which was sent on: 2014-05-27 14:42:24 +0000 -------------------------------------------------------------------------------- /modules/node-notifier/test/growl.js: -------------------------------------------------------------------------------- 1 | var Notify = require('../notifiers/growl'); 2 | var growly = require('growly'); 3 | 4 | describe('growl', function() { 5 | beforeEach(function() { 6 | this.original = growly.notify; 7 | }); 8 | 9 | afterEach(function() { 10 | growly.notify = this.original; 11 | }); 12 | 13 | it('should have overridable host and port', function() { 14 | var notifier = new Notify(); 15 | expect(notifier.options.host).toBeUndefined(); 16 | expect(notifier.options.port).toBeUndefined(); 17 | 18 | notifier = new Notify({ host: 'foo', port: 'bar' }); 19 | expect(notifier.options.host).toBe('foo'); 20 | expect(notifier.options.port).toBe('bar'); 21 | }); 22 | 23 | it('should pass host and port to growly', function(done) { 24 | growly.notify = function() { 25 | expect(this.host).toBe('foo'); 26 | expect(this.port).toBe('bar'); 27 | done(); 28 | }; 29 | 30 | var notifier = new Notify({ host: 'foo', port: 'bar' }); 31 | notifier.notify({ message: 'foo', wait: true }); 32 | }); 33 | 34 | it('should not override host/port if no options passed', function(done) { 35 | growly.notify = function() { 36 | expect(this.host).toBeUndefined(); 37 | expect(this.port).toBeUndefined(); 38 | done(); 39 | }; 40 | new Notify().notify({ message: 'foo', wait: true }); 41 | }); 42 | }); 43 | -------------------------------------------------------------------------------- /modules/node-notifier/test/index.js: -------------------------------------------------------------------------------- 1 | var notifier = require('../'); 2 | 3 | describe('constructors', function() { 4 | it('should expose a default selected instance', function() { 5 | expect(notifier.notify).toBeTruthy(); 6 | }); 7 | 8 | it('should expect only a function callback as second parameter', function() { 9 | function cb() { 10 | } 11 | expect(notifier.notify({ title: 'My notification' }, cb)).toBeTruthy(); 12 | }); 13 | 14 | it('should throw error when second parameter is not a function', function() { 15 | var wrongParamOne = 200; 16 | var wrongParamTwo = 'meaningless string'; 17 | var data = { title: 'My notification' }; 18 | 19 | var base = notifier.notify.bind(notifier, data); 20 | expect( 21 | base.bind(notifier, wrongParamOne) 22 | ).toThrowError(/^The second argument/); 23 | expect( 24 | base.bind(notifier, wrongParamTwo) 25 | ).toThrowError(/^The second argument/); 26 | }); 27 | 28 | it('should expose a default selected constructor function', function() { 29 | expect(notifier).toBeInstanceOf(notifier.Notification); 30 | }); 31 | 32 | it('should expose constructor for WindowsBalloon', function() { 33 | expect(notifier.WindowsBalloon).toBeTruthy(); 34 | }); 35 | 36 | it('should expose constructor for WindowsToaster', function() { 37 | expect(notifier.WindowsToaster).toBeTruthy(); 38 | }); 39 | 40 | it('should expose constructor for NotifySend', function() { 41 | expect(notifier.NotifySend).toBeTruthy(); 42 | }); 43 | 44 | it('should expose constructor for Growl', function() { 45 | expect(notifier.Growl).toBeTruthy(); 46 | }); 47 | }); 48 | -------------------------------------------------------------------------------- /modules/node-notifier/test/notify-send.js: -------------------------------------------------------------------------------- 1 | var Notify = require('../notifiers/notifysend'); 2 | var utils = require('../lib/utils'); 3 | var os = require('os'); 4 | 5 | describe('notify-send', function() { 6 | beforeEach(function() { 7 | this.original = utils.command; 8 | this.originalType = os.type; 9 | os.type = function() { 10 | return 'Linux'; 11 | }; 12 | }); 13 | 14 | afterEach(function() { 15 | utils.command = this.original; 16 | os.type = this.originalType; 17 | }); 18 | 19 | function expectArgsListToBe(expected, done) { 20 | utils.command = function(notifier, argsList, callback) { 21 | expect(argsList).toEqual(expected); 22 | done(); 23 | }; 24 | } 25 | 26 | it('should pass on title and body', function(done) { 27 | var expected = [ '"title"', '"body"' ]; 28 | expectArgsListToBe(expected, done); 29 | var notifier = new Notify({ suppressOsdCheck: true }); 30 | notifier.notify({ title: 'title', message: 'body' }); 31 | }); 32 | 33 | it('should pass have default title', function(done) { 34 | var expected = [ '"Node Notification:"', '"body"' ]; 35 | 36 | expectArgsListToBe(expected, done); 37 | var notifier = new Notify({ suppressOsdCheck: true }); 38 | notifier.notify({ message: 'body' }); 39 | }); 40 | 41 | it('should throw error if no message is passed', function(done) { 42 | utils.command = function(notifier, argsList, callback) { 43 | expect(argsList).toBeUndefined(); 44 | }; 45 | 46 | var notifier = new Notify({ suppressOsdCheck: true }); 47 | notifier.notify({}, function(err) { 48 | expect(err.message).toBe('Message is required.'); 49 | done(); 50 | }); 51 | }); 52 | 53 | it('should escape message input', function(done) { 54 | var excapedNewline = process.platform === 'win32' ? '\\r\\n' : '\\n'; 55 | var expected = [ 56 | '"Node Notification:"', 57 | '"some' + excapedNewline + ' \\"me\'ss\\`age\\`\\""' 58 | ]; 59 | 60 | expectArgsListToBe(expected, done); 61 | var notifier = new Notify({ suppressOsdCheck: true }); 62 | notifier.notify({ message: 'some\n "me\'ss`age`"' }); 63 | }); 64 | 65 | it('should send additional parameters as --"keyname"', function(done) { 66 | var expected = [ '"title"', '"body"', '--icon', '"icon-string"' ]; 67 | 68 | expectArgsListToBe(expected, done); 69 | var notifier = new Notify({ suppressOsdCheck: true }); 70 | notifier.notify({ title: 'title', message: 'body', icon: 'icon-string' }); 71 | }); 72 | 73 | it( 74 | 'should remove extra options that are not supported by notify-send', 75 | function(done) { 76 | var expected = [ '"title"', '"body"', '--icon', '"icon-string"' ]; 77 | 78 | expectArgsListToBe(expected, done); 79 | var notifier = new Notify({ suppressOsdCheck: true }); 80 | notifier.notify({ 81 | title: 'title', 82 | message: 'body', 83 | icon: 'icon-string', 84 | tullball: 'notValid' 85 | }); 86 | } 87 | ); 88 | }); 89 | -------------------------------------------------------------------------------- /modules/node-notifier/test/utils.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var fs = require('fs'); 3 | var _ = require('../lib/utils'); 4 | 5 | describe('utils', function() { 6 | describe('clone', function() { 7 | it('should clone nested objects', function() { 8 | var obj = { a: { b: 42 }, c: 123 }; 9 | var obj2 = _.clone(obj); 10 | 11 | expect(obj).toEqual(obj2); 12 | obj.a.b += 2; 13 | obj.c += 2; 14 | expect(obj).not.toEqual(obj2); 15 | }); 16 | }); 17 | 18 | describe('mapping', function() { 19 | it('should map icon for notify-send', function() { 20 | var expected = { title: 'Foo', message: 'Bar', icon: 'foobar' }; 21 | 22 | expect( 23 | _.mapToNotifySend({ title: 'Foo', message: 'Bar', appIcon: 'foobar' }) 24 | ).toEqual(expected); 25 | 26 | expect( 27 | _.mapToNotifySend({ title: 'Foo', message: 'Bar', i: 'foobar' }) 28 | ).toEqual(expected); 29 | }); 30 | 31 | it('should map short hand for notify-sned', function() { 32 | var expected = { 33 | urgency: 'a', 34 | 'expire-time': 'b', 35 | category: 'c', 36 | icon: 'd', 37 | hint: 'e' 38 | }; 39 | 40 | expect( 41 | _.mapToNotifySend({ u: 'a', e: 'b', c: 'c', i: 'd', h: 'e' }) 42 | ).toEqual(expected); 43 | }); 44 | 45 | it('should map icon for notification center', function() { 46 | var expected = { 47 | title: 'Foo', 48 | message: 'Bar', 49 | appIcon: 'foobar', 50 | json: true 51 | }; 52 | 53 | expect( 54 | _.mapToMac({ title: 'Foo', message: 'Bar', icon: 'foobar' }) 55 | ).toEqual(expected); 56 | 57 | expect( 58 | _.mapToMac({ title: 'Foo', message: 'Bar', i: 'foobar' }) 59 | ).toEqual(expected); 60 | }); 61 | 62 | it('should map icon for growl', function() { 63 | var icon = path.join(__dirname, 'fixture', 'coulson.jpg'); 64 | var iconRead = fs.readFileSync(icon); 65 | 66 | var expected = { title: 'Foo', message: 'Bar', icon: iconRead }; 67 | 68 | var obj = _.mapToGrowl({ title: 'Foo', message: 'Bar', icon: icon }); 69 | expect(obj).toEqual(expected); 70 | 71 | expect(obj.icon).toBeTruthy(); 72 | expect(Buffer.isBuffer(obj.icon)).toBeTruthy(); 73 | 74 | obj = _.mapToGrowl({ title: 'Foo', message: 'Bar', appIcon: icon }); 75 | 76 | expect(obj.icon).toBeTruthy(); 77 | expect(Buffer.isBuffer(obj.icon)).toBeTruthy(); 78 | }); 79 | 80 | it('should not map icon url for growl', function() { 81 | var icon = 'http://hostname.com/logo.png'; 82 | 83 | var expected = { title: 'Foo', message: 'Bar', icon: icon }; 84 | 85 | expect( 86 | _.mapToGrowl({ title: 'Foo', message: 'Bar', icon: icon }) 87 | ).toEqual(expected); 88 | 89 | expect( 90 | _.mapToGrowl({ title: 'Foo', message: 'Bar', appIcon: icon }) 91 | ).toEqual(expected); 92 | }); 93 | }); 94 | }); 95 | -------------------------------------------------------------------------------- /modules/node-notifier/vendor/notifu/notifu.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fliphub/fliplog/b0a1581e749a41ab65731f88cc90f2c24d20247d/modules/node-notifier/vendor/notifu/notifu.exe -------------------------------------------------------------------------------- /modules/node-notifier/vendor/notifu/notifu64.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fliphub/fliplog/b0a1581e749a41ab65731f88cc90f2c24d20247d/modules/node-notifier/vendor/notifu/notifu64.exe -------------------------------------------------------------------------------- /modules/node-notifier/vendor/snoreToast/SnoreToast.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fliphub/fliplog/b0a1581e749a41ab65731f88cc90f2c24d20247d/modules/node-notifier/vendor/snoreToast/SnoreToast.exe -------------------------------------------------------------------------------- /modules/node-notifier/vendor/terminal-notifier.app/Contents/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BuildMachineOSBuild 6 | 15G1004 7 | CFBundleDevelopmentRegion 8 | en 9 | CFBundleExecutable 10 | terminal-notifier 11 | CFBundleIconFile 12 | Terminal 13 | CFBundleIdentifier 14 | nl.superalloy.oss.terminal-notifier 15 | CFBundleInfoDictionaryVersion 16 | 6.0 17 | CFBundleName 18 | terminal-notifier 19 | CFBundlePackageType 20 | APPL 21 | CFBundleShortVersionString 22 | 1.7.1 23 | CFBundleSignature 24 | ???? 25 | CFBundleSupportedPlatforms 26 | 27 | MacOSX 28 | 29 | CFBundleVersion 30 | 16 31 | DTCompiler 32 | com.apple.compilers.llvm.clang.1_0 33 | DTPlatformBuild 34 | 8A218a 35 | DTPlatformVersion 36 | GM 37 | DTSDKBuild 38 | 16A300 39 | DTSDKName 40 | macosx10.12 41 | DTXcode 42 | 0800 43 | DTXcodeBuild 44 | 8A218a 45 | LSMinimumSystemVersion 46 | 10.8 47 | LSUIElement 48 | 49 | NSHumanReadableCopyright 50 | Copyright © 2012-2016 Eloy Durán, Julien Blanchard. All rights reserved. 51 | NSMainNibFile 52 | MainMenu 53 | NSPrincipalClass 54 | NSApplication 55 | NSUserNotificationAlertStyle 56 | alert 57 | 58 | 59 | -------------------------------------------------------------------------------- /modules/node-notifier/vendor/terminal-notifier.app/Contents/MacOS/terminal-notifier: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fliphub/fliplog/b0a1581e749a41ab65731f88cc90f2c24d20247d/modules/node-notifier/vendor/terminal-notifier.app/Contents/MacOS/terminal-notifier -------------------------------------------------------------------------------- /modules/node-notifier/vendor/terminal-notifier.app/Contents/PkgInfo: -------------------------------------------------------------------------------- 1 | APPL???? -------------------------------------------------------------------------------- /modules/node-notifier/vendor/terminal-notifier.app/Contents/Resources/Terminal.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fliphub/fliplog/b0a1581e749a41ab65731f88cc90f2c24d20247d/modules/node-notifier/vendor/terminal-notifier.app/Contents/Resources/Terminal.icns -------------------------------------------------------------------------------- /modules/node-notifier/vendor/terminal-notifier.app/Contents/Resources/en.lproj/Credits.rtf: -------------------------------------------------------------------------------- 1 | {\rtf0\ansi{\fonttbl\f0\fswiss Helvetica;} 2 | {\colortbl;\red255\green255\blue255;} 3 | \paperw9840\paperh8400 4 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural 5 | 6 | \f0\b\fs24 \cf0 Engineering: 7 | \b0 \ 8 | Some people\ 9 | \ 10 | 11 | \b Human Interface Design: 12 | \b0 \ 13 | Some other people\ 14 | \ 15 | 16 | \b Testing: 17 | \b0 \ 18 | Hopefully not nobody\ 19 | \ 20 | 21 | \b Documentation: 22 | \b0 \ 23 | Whoever\ 24 | \ 25 | 26 | \b With special thanks to: 27 | \b0 \ 28 | Mom\ 29 | } 30 | -------------------------------------------------------------------------------- /modules/node-notifier/vendor/terminal-notifier.app/Contents/Resources/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fliphub/fliplog/b0a1581e749a41ab65731f88cc90f2c24d20247d/modules/node-notifier/vendor/terminal-notifier.app/Contents/Resources/en.lproj/InfoPlist.strings -------------------------------------------------------------------------------- /modules/node-notifier/vendor/terminal-notifier.app/Contents/Resources/en.lproj/MainMenu.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fliphub/fliplog/b0a1581e749a41ab65731f88cc90f2c24d20247d/modules/node-notifier/vendor/terminal-notifier.app/Contents/Resources/en.lproj/MainMenu.nib -------------------------------------------------------------------------------- /modules/onetime/index.js: -------------------------------------------------------------------------------- 1 | // https://github.com/sindresorhus/onetime 2 | const mimicFn = require('../mimic-fn') 3 | 4 | module.exports = (fn, opts) => { 5 | // TODO: Remove this in v3 6 | if (opts === true) { 7 | throw new TypeError('The second argument is now an options object') 8 | } 9 | 10 | if (typeof fn !== 'function') { 11 | throw new TypeError('Expected a function') 12 | } 13 | 14 | opts = opts || {} 15 | 16 | let ret 17 | let called = false 18 | const fnName = fn.displayName || fn.name || '' 19 | 20 | const onetime = function() { 21 | if (called) { 22 | if (opts.throw === true) { 23 | throw new Error(`Function \`${fnName}\` can only be called once`) 24 | } 25 | 26 | return ret 27 | } 28 | 29 | called = true 30 | ret = fn.apply(this, arguments) 31 | fn = null 32 | 33 | return ret 34 | } 35 | 36 | mimicFn(onetime, fn) 37 | 38 | return onetime 39 | } 40 | -------------------------------------------------------------------------------- /modules/pretty-format/printString.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const ESCAPED_CHARACTERS = /(\\|\"|\')/g 4 | 5 | module.exports = function printString(val) { 6 | return val.replace(ESCAPED_CHARACTERS, '\\$1') 7 | } 8 | -------------------------------------------------------------------------------- /modules/pretty-time/index.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * pretty-time 3 | * 4 | * Copyright (c) 2015, Jon Schlinkert. 5 | * Licensed under the MIT License. 6 | */ 7 | 8 | var utils = require('./utils') 9 | var isNumber = require('../')('is-number') 10 | var nano = require('../')('nanoseconds') 11 | 12 | var scale = { 13 | w: 6048e11, 14 | d: 864e11, 15 | h: 36e11, 16 | m: 6e10, 17 | s: 1e9, 18 | ms: 1e6, 19 | μs: 1e3, 20 | ns: 1, 21 | } 22 | 23 | function pretty(time, smallest, digits) { 24 | if (!isNumber(time) && !Array.isArray(time)) { 25 | throw new TypeError('expected an array or number in nanoseconds') 26 | } 27 | if (Array.isArray(time) && time.length !== 2) { 28 | throw new TypeError('expected an array from process.hrtime()') 29 | } 30 | 31 | if (isNumber(smallest)) { 32 | digits = smallest 33 | smallest = null 34 | } 35 | 36 | var num = isNumber(time) ? time : nano(time) 37 | var res = '' 38 | var prev 39 | 40 | for (var uom in scale) { 41 | var step = scale[uom] 42 | var inc = num / step 43 | 44 | if (smallest && utils.isSmallest(uom, smallest)) { 45 | inc = utils.round(inc, digits) 46 | if (prev && inc === prev / step) --inc 47 | res += inc + uom 48 | return res.trim() 49 | } 50 | 51 | if (inc < 1) continue 52 | if (!smallest) { 53 | inc = utils.round(inc, digits) 54 | res += inc + uom 55 | return res 56 | } 57 | 58 | prev = step 59 | 60 | inc = Math.floor(inc) 61 | num -= inc * step 62 | res += inc + uom + ' ' 63 | } 64 | return res.trim() 65 | } 66 | 67 | module.exports = pretty 68 | -------------------------------------------------------------------------------- /modules/pretty-time/utils.js: -------------------------------------------------------------------------------- 1 | var isNumber = require('../')('is-number') 2 | 3 | /** 4 | * Expose `utils` 5 | */ 6 | 7 | var utils = module.exports 8 | 9 | utils.regex = { 10 | w: /^(w((ee)?k)?s?)$/, 11 | d: /^(d(ay)?s?)$/, 12 | h: /^(h((ou)?r)?s?)$/, 13 | m: /^(min(ute)?s?|m)$/, 14 | s: /^((sec(ond)?)s?|s)$/, 15 | ms: /^(milli(second)?s?|ms)$/, 16 | μs: /^(micro(second)?s?|μs)$/, 17 | ns: /^(nano(second)?s?|ns?)$/, 18 | } 19 | 20 | utils.isSmallest = function(uom, unit) { 21 | return utils.regex[uom].test(unit) 22 | } 23 | 24 | utils.round = function(num, digits) { 25 | num = Math.abs(num) 26 | if (isNumber(digits)) { 27 | return num.toFixed(digits) 28 | } 29 | return Math.round(num) 30 | } 31 | -------------------------------------------------------------------------------- /modules/prettyjson/utils.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Creates a string with the same length as `numSpaces` parameter 3 | **/ 4 | exports.indent = function indent(numSpaces) { 5 | return new Array(numSpaces + 1).join(' ') 6 | } 7 | 8 | /** 9 | * Gets the string length of the longer index in a hash 10 | **/ 11 | exports.getMaxIndexLength = function getMaxIndexLength(input) { 12 | var maxWidth = 0 13 | 14 | Object.getOwnPropertyNames(input).forEach(key => { 15 | // Skip undefined values. 16 | if (input[key] === undefined) { 17 | return 18 | } 19 | 20 | maxWidth = Math.max(maxWidth, key.length) 21 | }) 22 | return maxWidth 23 | } 24 | -------------------------------------------------------------------------------- /modules/prettysize/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2013, Yahoo! Inc. All rights reserved. 3 | Code licensed under the BSD License: 4 | http://yuilibrary.com/license/ 5 | */ 6 | 7 | var sizes = ['Bytes', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB'] 8 | 9 | /** 10 | Pretty print a size from bytes 11 | @method pretty 12 | @param {Number} size The number to pretty print 13 | @param {Boolean} [nospace=false] Don't print a space 14 | @param {Boolean} [one=false] Only print one character 15 | @param {Number} [places=1] Number of decimal places to return 16 | */ 17 | 18 | module.exports = function(size, nospace, one, places) { 19 | var mysize, f 20 | places = places || 1 21 | 22 | sizes.forEach((f, id) => { 23 | if (one) { 24 | f = f.slice(0, 1) 25 | } 26 | var s = Math.pow(1024, id), fixed 27 | if (size >= s) { 28 | fixed = String((size / s).toFixed(places)) 29 | if (fixed.indexOf('.0') === fixed.length - 2) { 30 | fixed = fixed.slice(0, -2) 31 | } 32 | mysize = fixed + (nospace ? '' : ' ') + f 33 | } 34 | }) 35 | 36 | // zero handling 37 | // always prints in Bytes 38 | if (!mysize) { 39 | f = one ? sizes[0].slice(0, 1) : sizes[0] 40 | mysize = '0' + (nospace ? '' : ' ') + f 41 | } 42 | 43 | return mysize 44 | } 45 | -------------------------------------------------------------------------------- /modules/restore-cursor/index.js: -------------------------------------------------------------------------------- 1 | const signalExit = require('../signal-exit') 2 | const onetime = require('../onetime') 3 | 4 | module.exports = onetime(() => { 5 | signalExit( 6 | () => { 7 | process.stderr.write('\u001b[?25h') 8 | }, 9 | {alwaysLast: true} 10 | ) 11 | }) 12 | -------------------------------------------------------------------------------- /modules/retro/examples/client.js: -------------------------------------------------------------------------------- 1 | var net = require('net') 2 | var host = process.argv[2] 3 | var port = Number(process.argv[3]) 4 | 5 | var c = net.connect(port, host) 6 | process.stdin.pipe(c).pipe(process.stdout) 7 | 8 | process.stdin.setRawMode(true) 9 | process.stdin.on('data', buf => { 10 | if (buf[0] === 3) c.end() 11 | }) 12 | 13 | c.on('end', () => { 14 | process.stdin.setRawMode(false) 15 | process.exit() 16 | }) 17 | -------------------------------------------------------------------------------- /modules/retro/examples/menu.js: -------------------------------------------------------------------------------- 1 | var Menu = require('../') 2 | var menu = Menu({width: 29, x: 4, y: 2}) 3 | menu.reset() 4 | menu.write('SERIOUS BUSINESS TERMINAL\n') 5 | menu.write('-------------------------\n') 6 | 7 | menu.add('ADD TRANSACTION INVOICE') 8 | menu.add('BUSINESS INTELLIGENCE') 9 | menu.add('ACCOUNTS PAYABLE', (label, index) => { 10 | menu.close() 11 | console.log('LABEL=', label) 12 | console.log('INDEX=', index) 13 | process.exit() 14 | }) 15 | menu.add('LEDGER BOOKINGS') 16 | menu.add('INDICATOR CHART METRICS') 17 | menu.add('BACKUP DATA TO FLOPPY DISK') 18 | menu.add('RESTORE FROM FLOPPY DISK') 19 | menu.add('欢迎来到substack的编码世界') 20 | menu.add('EXIT') 21 | 22 | menu.on('select', label => { 23 | menu.close() 24 | console.log('SELECTED: ' + label) 25 | }) 26 | process.stdin.pipe(menu.createStream()).pipe(process.stdout) 27 | 28 | process.stdin.setRawMode(true) 29 | menu.on('close', () => { 30 | process.stdin.setRawMode(false) 31 | process.stdin.end() 32 | }) 33 | -------------------------------------------------------------------------------- /modules/retro/examples/server.js: -------------------------------------------------------------------------------- 1 | var Menu = require('../') 2 | var net = require('net') 3 | 4 | var server = net.createServer(stream => { 5 | var menu = Menu({width: 60, x: 4, y: 2}) 6 | menu.reset() 7 | menu.write('SHALL WE PLAY A GAME?\n') 8 | menu.write('-------------------------\n') 9 | menu.add('CHESS') 10 | menu.add('POKER') 11 | menu.add('FIGHTER COMBAT') 12 | menu.add('GUERILLA ENGAGEMENT') 13 | menu.add('DESERT WARFARE') 14 | menu.add('AIR-TO-GROUND ACTIONS') 15 | menu.add('THEATERWIDE TACTICAL WARFARE') 16 | menu.add('THEATERWIDE BIOTOXIC AND CHEMICAL WARFARE') 17 | menu.add('GLOBAL THERMONUCLEAR WAR') 18 | menu.add('EXIT') 19 | 20 | menu.on('select', label => { 21 | menu.close() 22 | stream.end('\nTHE ONLY WINNING MOVE IS NOT TO PLAY.\n') 23 | }) 24 | stream.pipe(menu.createStream()).pipe(stream) 25 | }) 26 | server.listen(5000) 27 | -------------------------------------------------------------------------------- /modules/retro/examples/simple.js: -------------------------------------------------------------------------------- 1 | var Menu = require('../') 2 | var menu = Menu({width: 29, x: 4, y: 2}) 3 | menu.reset() 4 | menu.write('SERIOUS BUSINESS TERMINAL\n') 5 | menu.write('-------------------------\n') 6 | 7 | menu.add('ADD TRANSACTION INVOICE') 8 | menu.add('BUSINESS INTELLIGENCE') 9 | menu.add('ACCOUNTS PAYABLE') 10 | menu.add('LEDGER BOOKINGS') 11 | menu.add('INDICATOR CHART METRICS') 12 | menu.add('BACKUP DATA TO FLOPPY DISK') 13 | menu.add('RESTORE FROM FLOPPY DISK') 14 | menu.add('EXIT') 15 | 16 | menu.on('select', label => { 17 | menu.close() 18 | console.log('SELECTED: ' + label) 19 | }) 20 | process.stdin.pipe(menu.createStream()).pipe(process.stdout) 21 | 22 | process.stdin.setRawMode(true) 23 | menu.on('close', () => { 24 | process.stdin.setRawMode(false) 25 | process.stdin.end() 26 | }) 27 | -------------------------------------------------------------------------------- /modules/retro/index.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./retro') 2 | -------------------------------------------------------------------------------- /modules/semver/README.md: -------------------------------------------------------------------------------- 1 | used by node-notifier 2 | -------------------------------------------------------------------------------- /modules/shellwords/README.md: -------------------------------------------------------------------------------- 1 | used by node-notifier 2 | -------------------------------------------------------------------------------- /modules/shellwords/index.js: -------------------------------------------------------------------------------- 1 | // Generated by CoffeeScript 1.3.3 2 | (function() { 3 | var scan 4 | 5 | scan = function(string, pattern, callback) { 6 | var match, result 7 | result = '' 8 | while (string.length > 0) { 9 | match = string.match(pattern) 10 | if (match) { 11 | result += string.slice(0, match.index) 12 | result += callback(match) 13 | string = string.slice(match.index + match[0].length) 14 | } 15 | else { 16 | result += string 17 | string = '' 18 | } 19 | } 20 | return result 21 | } 22 | 23 | exports.split = function(line) { 24 | var field, words 25 | if (line == null) { 26 | line = '' 27 | } 28 | words = [] 29 | field = '' 30 | scan(line, /\s*(?:([^\s\\\'\"]+)|'((?:[^\'\\]|\\.)*)'|"((?:[^\"\\]|\\.)*)"|(\\.?)|(\S))(\s|$)?/, (match) => { 31 | var dq, escape, garbage, raw, seperator, sq, word 32 | raw = match[0], word = match[1], sq = match[2], dq = match[3], escape = match[4], garbage = match[5], seperator = match[6] 33 | if (garbage != null) { 34 | throw new Error('Unmatched quote') 35 | } 36 | field += word || (sq || dq || escape).replace(/\\(?=.)/, '') 37 | if (seperator != null) { 38 | words.push(field) 39 | return field = '' 40 | } 41 | }) 42 | if (field) { 43 | words.push(field) 44 | } 45 | return words 46 | } 47 | 48 | exports.escape = function(str) { 49 | if (str == null) { 50 | str = '' 51 | } 52 | if (str == null) { 53 | return '\'\'' 54 | } 55 | return str.replace(/([^A-Za-z0-9_\-.,:\/@\n])/g, '\\$1').replace(/\n/g, '\'\n\'') 56 | } 57 | }).call(this) 58 | -------------------------------------------------------------------------------- /modules/signal-exit/README.md: -------------------------------------------------------------------------------- 1 | https://github.com/tapjs/signal-exit/blob/master/signals.js 2 | -------------------------------------------------------------------------------- /modules/signal-exit/signals.js: -------------------------------------------------------------------------------- 1 | // This is not the set of all possible signals. 2 | // 3 | // It IS, however, the set of all signals that trigger 4 | // an exit on either Linux or BSD systems. Linux is a 5 | // superset of the signal names supported on BSD, and 6 | // the unknown signals just fail to register, so we can 7 | // catch that easily enough. 8 | // 9 | // Don't bother with SIGKILL. It's uncatchable, which 10 | // means that we can't fire any callbacks anyway. 11 | // 12 | // If a user does happen to register a handler on a non- 13 | // fatal signal like SIGWINCH or something, and then 14 | // exit, it'll end up firing `process.emit('exit')`, so 15 | // the handler will be fired anyway. 16 | // 17 | // SIGBUS, SIGFPE, SIGSEGV and SIGILL, when not raised 18 | // artificially, inherently leave the process in a 19 | // state from which it is not safe to try and enter JS 20 | // listeners. 21 | module.exports = ['SIGABRT', 'SIGALRM', 'SIGHUP', 'SIGINT', 'SIGTERM'] 22 | 23 | if (process.platform !== 'win32') { 24 | module.exports.push( 25 | 'SIGVTALRM', 26 | 'SIGXCPU', 27 | 'SIGXFSZ', 28 | 'SIGUSR2', 29 | 'SIGTRAP', 30 | 'SIGSYS', 31 | 'SIGQUIT', 32 | 'SIGIOT' 33 | // should detect profiler and enable/disable accordingly. 34 | // see #21 35 | // 'SIGPROF' 36 | ) 37 | } 38 | 39 | if (process.platform === 'linux') { 40 | module.exports.push('SIGIO', 'SIGPOLL', 'SIGPWR', 'SIGSTKFLT', 'SIGUNUSED') 41 | } 42 | -------------------------------------------------------------------------------- /modules/sleepfor/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number} sleepDuration 3 | * @return {Promise.resolve} 4 | */ 5 | module.exports = function sleepFor(sleepDuration) { 6 | var now = new Date().getTime() 7 | while (new Date().getTime() < now + sleepDuration) { 8 | /* do nothing */ 9 | } 10 | return Promise.resolve(sleepDuration) 11 | } 12 | -------------------------------------------------------------------------------- /modules/string-width/README.md: -------------------------------------------------------------------------------- 1 | used by fmt-obj 2 | -------------------------------------------------------------------------------- /modules/string-width/index.js: -------------------------------------------------------------------------------- 1 | const stripAnsi = require('../')('strip-ansi') 2 | const isFullwidthCodePoint = require('../')('is-fullwidth-code-point') 3 | 4 | module.exports = str => { 5 | if (typeof str !== 'string' || str.length === 0) { 6 | return 0 7 | } 8 | 9 | let width = 0 10 | 11 | str = stripAnsi(str) 12 | 13 | for (let i = 0; i < str.length; i++) { 14 | const code = str.codePointAt(i) 15 | 16 | // Ignore control characters 17 | if (code <= 0x1f || (code >= 0x7f && code <= 0x9f)) { 18 | continue 19 | } 20 | 21 | // Surrogates 22 | if (code >= 0x10000) { 23 | i++ 24 | } 25 | 26 | if (isFullwidthCodePoint(code)) { 27 | width += 2 28 | } 29 | else { 30 | width++ 31 | } 32 | } 33 | 34 | return width 35 | } 36 | -------------------------------------------------------------------------------- /modules/strip-ansi/index.js: -------------------------------------------------------------------------------- 1 | // https://github.com/chalk/ansi-regex/blob/master/index.js 2 | const ansiRegex = /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-PRZcf-nqry=><]/g 3 | const replaceAnsi = str => str.replace(ansiRegex, '') 4 | replaceAnsi.ansiRegex = ansiRegex 5 | replaceAnsi.stripAnsi = replaceAnsi 6 | module.exports = replaceAnsi 7 | -------------------------------------------------------------------------------- /modules/visualwidth/README.md: -------------------------------------------------------------------------------- 1 | used by retro 2 | -------------------------------------------------------------------------------- /modules/which/README.md: -------------------------------------------------------------------------------- 1 | used by node-notifier 2 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "_fliplog": [ 3 | "cli", 4 | "fun", 5 | "latest" 6 | ], 7 | "name": "fliplog", 8 | "version": "1.0.2", 9 | "main": "index.js", 10 | "description": "fluent logging with verbose insight, colors, tables, emoji, filtering, spinners, progress bars, timestamps, capturing, stack traces, clearing, & presets", 11 | "keywords": [ 12 | "fluent", 13 | "debug", 14 | "logging", 15 | "deep-diff", 16 | "deep", 17 | "emoji", 18 | "stack-trace", 19 | "spinner", 20 | "progress-bars", 21 | "filter", 22 | "tags", 23 | "colors", 24 | "tables", 25 | "capture", 26 | "output", 27 | "presets", 28 | "arithmetics" 29 | ], 30 | "files": [ 31 | "index.js", 32 | "deps/", 33 | "middleware/", 34 | "plugins/", 35 | "deps", 36 | "middleware", 37 | "plugins", 38 | "modules" 39 | ], 40 | "directories": [ 41 | "deps", 42 | "middleware", 43 | "plugins", 44 | "modules" 45 | ], 46 | "scripts": { 47 | "test": "node ./test/examples && node ./test/test", 48 | "test-all": "node ./test/examples && node ./test/test && node test/boxen && node test/filter && node test/progress && node test/slow && node test/formatter && node test/from && node test/pretty && node test/diff && node test/dept && node test/write && node test/fun && node test/quick", 49 | "_prepublish": "echo {} > ./deps/cache.json", 50 | "_magicpublish": "node ./dynamicTags.js", 51 | "_postinstall": "node ./index.js --postinstallcall", 52 | "test-flags": "node ./test/flags.js" 53 | }, 54 | "testingDependencies": { 55 | "clear-require": "*", 56 | "benchmark": "*" 57 | }, 58 | "_optionalDependencies": { 59 | "cli-spinners": "^1.0.0", 60 | "lodash.padend": "4.6.1", 61 | "read-pkg-up": "2.0.0" 62 | }, 63 | "dependencies": { 64 | "chain-able": "3.0.0" 65 | }, 66 | "license": "MIT", 67 | "author": "James ", 68 | "homepage": "https://github.com/fliphub/fliplog", 69 | "repository": { 70 | "type": "git", 71 | "url": "git+https://github.com/fliphub/fliplog.git" 72 | }, 73 | "bugs": { 74 | "url": "https://github.com/fliphub/fliplog/issues" 75 | }, 76 | "_devDependencies": { 77 | "babel-core": "^6.24.1", 78 | "babili": "^0.0.12", 79 | "fsbx": "^2.1.0-beta.4" 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /plugins/bar.js: -------------------------------------------------------------------------------- 1 | const {random, shuffle, chance} = require('../deps/fun') 2 | 3 | module.exports = { 4 | // deps: { 5 | // 'babar': '0.1.0', 6 | // }, 7 | 8 | reset() { 9 | this.barStyles() 10 | }, 11 | 12 | /** 13 | * @tutorial https://github.com/fliphub/fliplog#styles-and-bar 14 | * @param {any} styles 15 | * @return {FlipLog} 16 | */ 17 | barStyles(styles) { 18 | if (!styles) { 19 | styles = { 20 | color: 'green', 21 | width: 40, 22 | height: 10, 23 | maxY: 10, 24 | yFractions: 1, 25 | } 26 | } 27 | return this.set('barStyles', styles) 28 | }, 29 | 30 | /** 31 | * @todo https://github.com/substack/node-charm 32 | * @todo https://www.npmjs.com/package/cli-chart 33 | * 34 | * @param {any} [input=null] 35 | * @param {any} styles 36 | * @param {Boolean} [echo=false] 37 | * @return {FlipLog} 38 | */ 39 | bar(input = null, styles, echo = false) { 40 | styles = styles || this.get('barStyles') 41 | if (input === null) { 42 | input = [ 43 | [0, random(1, 10)], 44 | [1, random(0, 20)], 45 | [2, random(1, 5)], 46 | [3, random(0, 1)], 47 | [4, random(0, 15)], 48 | ] 49 | } 50 | const babar = this.requirePkg('babar') 51 | const data = babar(input, styles) 52 | return this.set('data', data) 53 | }, 54 | } 55 | -------------------------------------------------------------------------------- /plugins/beep.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | // deps: { 3 | // 'beeper': '1.1.1', 4 | // }, 5 | 6 | /** 7 | * @tutorial https://www.npmjs.com/package/beeper 8 | * @param {Number} [sequence=3] sequence to beep 9 | * @param {Boolean} [echo=false] echo right away or not 10 | * @return {Object} 11 | */ 12 | beep(sequence = 3, echo = false) { 13 | const beep = this.requirePkg('beeper') // eslint-disable-line 14 | 15 | const data = { 16 | inspect() { 17 | beep(sequence) 18 | return 'beeping! ' 19 | }, 20 | } 21 | 22 | if (echo !== false) { 23 | data.inspect() 24 | return this 25 | } 26 | 27 | return this.set('data', data) 28 | }, 29 | } 30 | -------------------------------------------------------------------------------- /plugins/box.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | deps: { 3 | boxen: '1.0.0', 4 | }, 5 | 6 | reset() { 7 | this.boxStyles() 8 | }, 9 | 10 | /** 11 | * @tutorial https://github.com/fliphub/fliplog#-box 12 | * @param {any} styles 13 | * @return {FlipLog} 14 | */ 15 | boxStyles(styles) { 16 | if (!styles) { 17 | styles = { 18 | padding: 1, 19 | margin: 1, 20 | borderStyle: 'double', 21 | default: true, 22 | } 23 | } 24 | 25 | return this.set('boxStyles', styles) 26 | }, 27 | 28 | /** 29 | * @tutorial https://github.com/fliphub/fliplog#-box 30 | * 31 | * @see FlipLog.boxStyles 32 | * @param {string | any} input 33 | * @param {object | any} options 34 | * @param {Boolean} [echo=false] 35 | * @return {FlipLog} 36 | */ 37 | box(input, options, echo = false) { 38 | const boxen = this.requirePkg('boxen') 39 | if (boxen === false) { 40 | return this 41 | } 42 | let opts = options || this.get('boxStyles') 43 | 44 | const box = boxen(input, opts) 45 | 46 | if (opts && opts.default === true) { 47 | this.text(box) 48 | } 49 | else { 50 | this.data(box) 51 | } 52 | 53 | if (echo !== false) return this.echo() 54 | return this 55 | }, 56 | } 57 | -------------------------------------------------------------------------------- /plugins/capture.js: -------------------------------------------------------------------------------- 1 | module.exports = function capturePlugin({shh}) { 2 | return { 3 | 4 | /** 5 | * @tutorial https://gist.github.com/pguillory/729616#gistcomment-332391 6 | * @param {any} data 7 | * @param {any} fileDescriptor not implemented 8 | * @return {FlipLog} @chainable 9 | */ 10 | saveLog(data, fileDescriptor) { 11 | this.fileDescriptor = fileDescriptor 12 | this.savedLog.push(data) 13 | return this 14 | }, 15 | 16 | /** 17 | * @tutorial https://github.com/fliphub/fliplog#-silencing 18 | * @desc by-reference mutates object property to silence all 19 | * @return {FlipLog} @chainable 20 | */ 21 | shush() { 22 | shh.shushed = true 23 | return this 24 | }, 25 | 26 | /** 27 | * @see FlipLog.shush 28 | * @desc inverse of shush 29 | * @return {FlipLog} @chainable 30 | */ 31 | unshush() { 32 | shh.shushed = false 33 | return this 34 | }, 35 | 36 | /** 37 | * @desc captures all stdout content 38 | * @tutorial https://github.com/fliphub/fliplog#capture-all 39 | * @param {Boolean} [output=false] 40 | * @return {FlipLog} @chainable 41 | */ 42 | startCapturing(output = false) { 43 | const saveLog = this.saveLog.bind(this) 44 | this.stdoutWriteRef = process.stdout.write 45 | process.stdout.write = (function(write) { 46 | return function(string, encoding, fileDescriptor) { 47 | saveLog(string, fileDescriptor) 48 | // write.apply(process.stdout, arguments) 49 | } 50 | })(process.stdout.write) 51 | return this 52 | }, 53 | 54 | /** 55 | * @desc restores original stdout 56 | * @see FlipLog.startCapturing 57 | * @return {FlipLog} @chainable 58 | */ 59 | stopCapturing() { 60 | process.stdout.write = this.stdoutWriteRef 61 | return this 62 | }, 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /plugins/chalk.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | /** 3 | * @since 0.0.1 4 | * @see chalk 5 | * @param {string} color 6 | * @return {FlipLog} 7 | */ 8 | color(color) { 9 | let clr = color 10 | 11 | if (this.has('color') === true) { 12 | clr = this.get('color') + '.' + color 13 | } 14 | 15 | return this.set('color', clr) 16 | }, 17 | 18 | /** 19 | * @since 0.2.2 20 | * @desc pass in text, return it colored 21 | * @param {string} msg 22 | * @param {string} [color=null] 23 | * @return {string} highlighted 24 | */ 25 | colored(msg, color = null) { 26 | if (color !== null) this.color(color) 27 | const colored = this.text(msg).logText() 28 | this.reset() 29 | return colored 30 | }, 31 | 32 | /** 33 | * @since 0.2.1 34 | * @see chalk 35 | * @return {Object} chalk 36 | */ 37 | chalk() { 38 | return this.requirePkg('chalk') 39 | }, 40 | } 41 | -------------------------------------------------------------------------------- /plugins/clear.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | /** 3 | * @tutorial https://github.com/fliphub/fliplog#-clear 4 | * @see cli-color 5 | * @see https://github.com/medikoo/cli-color/blob/master/reset.js 6 | * @return {FlipLog} @chainable 7 | */ 8 | clear() { 9 | process.stdout.write('\x1b[2J\x1b[0;0H') 10 | return this 11 | }, 12 | } 13 | -------------------------------------------------------------------------------- /plugins/diff.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | reset() { 3 | this.delete('diffs') 4 | 5 | return this 6 | }, 7 | 8 | /** 9 | * @desc 10 | * take in 2 things to diff 11 | * can pass in a diff1 and then call diff again to diff again 12 | * 13 | * @author https://github.com/challenger532 for this 14 | * @return {FlipLog} @chainable 15 | */ 16 | diff() { 17 | const clone = this.requirePkg('lodash.clonedeep') // eslint-disable-line 18 | 19 | if (this.has('diffs') === false) { 20 | this.set('diffs', []) 21 | } 22 | 23 | const diffs = this.get('diffs') 24 | const args = Array.from(arguments).map(arg => clone(arg)) 25 | 26 | this.set('diffs', diffs.concat(args)) 27 | 28 | this.formatter(() => { 29 | const differ = this.requirePkg('diffs') 30 | const result = differ(...this.get('diffs')) 31 | 32 | // console.log('result?', result) 33 | if (this.has('text') === false) { 34 | this.bold('diff:\n\n') 35 | } 36 | 37 | return result 38 | }) 39 | 40 | return this 41 | }, 42 | 43 | /** 44 | * @depreciated @depricated v0.3.0 45 | * @see FlipLog.diff 46 | * @tutorial https://github.com/fliphub/fliplog/blob/master/README.md#%EF%B8%8F-diff 47 | * @return {string} table of diffs 48 | */ 49 | diffs() { 50 | const differ = this.requirePkg('diffs') 51 | const result = differ(...this.get('diffs')) 52 | 53 | // console.log('result?', result) 54 | if (this.has('text') === false) { 55 | this.bold('diff:\n\n') 56 | } 57 | return this.data(result) 58 | }, 59 | } 60 | -------------------------------------------------------------------------------- /plugins/expose.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | /** 3 | * @since 0.3.0, 0.2.0 4 | * @tutorial https://www.npmjs.com/package/expose-hidden 5 | * @param {Boolean} [shouldExpose=true] 6 | * @return {FlipLog} 7 | */ 8 | expose(shouldExpose = true) { 9 | const expose = this.requirePkg('expose-hidden') 10 | return this.formatter(expose) 11 | }, 12 | } 13 | -------------------------------------------------------------------------------- /plugins/file.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | // ----------------------------- file ------------------ 3 | // https://gist.github.com/rtgibbons/7354879 4 | 5 | // using always will make every log go to the file 6 | // otherwise it is reset 7 | toFile(filename, always = false) { 8 | this.set('file', filename) 9 | return this 10 | }, 11 | 12 | writeToFile(contents) { 13 | const write = require('flipfile/write') 14 | write(filename, contents) 15 | return this 16 | }, 17 | } 18 | -------------------------------------------------------------------------------- /plugins/flags.js: -------------------------------------------------------------------------------- 1 | // const toarr = require('chain-able/deps/to-arr') 2 | 3 | let fwf 4 | 5 | module.exports = { 6 | reset() { 7 | if (!fwf) fwf = require('../modules/funwithflags') 8 | 9 | const argv = fwf(process.argv.slice(2), { 10 | number: ['DEBUG_DEPTH'], 11 | boolean: ['DEBUG_SHOW_HIDDEN', 'DEBUG_COLORS'], 12 | string: ['fliplog', 'DEBUG'], 13 | alias: { 14 | fliplog: ['flipdebug'], 15 | }, 16 | default: { 17 | DEBUG: false, 18 | DEBUG_DEPTH: 30, 19 | DEBUG_SHOW_HIDDEN: true, 20 | DEBUG_COLORS: true, 21 | }, 22 | }) 23 | 24 | const {DEBUG_DEPTH, DEBUG_SHOW_HIDDEN, DEBUG_COLORS, DEBUG} = argv 25 | 26 | if (DEBUG_COLORS === false) { 27 | this.strip() 28 | } 29 | 30 | this.set('argv.inspector', { 31 | depth: DEBUG_DEPTH, 32 | maxArrayLength: DEBUG_DEPTH, 33 | showHidden: DEBUG_SHOW_HIDDEN, 34 | showProxy: true, 35 | colors: DEBUG_COLORS, 36 | }) 37 | 38 | if (DEBUG) { 39 | this.delete('filter') 40 | this.filter(DEBUG) 41 | } 42 | // @TODO: filters 43 | // if (DEBUG) { 44 | // this.set('filter', DEBUG) 45 | // } 46 | 47 | return this 48 | }, 49 | } 50 | -------------------------------------------------------------------------------- /plugins/formatter.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | reset() { 3 | this.delete('formatter') 4 | return this 5 | }, 6 | 7 | /** 8 | * @tutorial https://github.com/fliphub/fliplog/blob/master/README.md#-formatter 9 | * @param {Function} [cb] callback with data, returns formatted data 10 | * @return {FlipLog} @chainable 11 | */ 12 | formatter(cb) { 13 | if (!cb) 14 | cb = arg => { 15 | if (arg && typeof arg === 'object') { 16 | Object.keys(arg).forEach(key => { 17 | if (typeof arg[key] === 'string') { 18 | arg[key] = arg[key].replace('', '') 19 | } 20 | else if (Array.isArray(arg[key])) { 21 | arg[key] = arg[key].map(a => cb(a)) 22 | } 23 | }) 24 | } 25 | return arg 26 | } 27 | 28 | // merge in formatters 29 | // if already array, append 30 | // otherwise, make an array 31 | if (this.has('formatter') === true) { 32 | const formatter = this.get('formatter') 33 | 34 | if (Array.isArray(formatter.fns)) { 35 | formatter.fns.push(cb) 36 | return this.set('formatter', formatter) 37 | } 38 | else { 39 | // go through them 40 | // if they return null, ignore it 41 | const formatterFn = arg => { 42 | const formatters = this.get('formatter').fns 43 | let data = arg 44 | formatters.forEach(fmtr => { 45 | data = fmtr(arg) 46 | if (data === null) data = arg 47 | }) 48 | return data 49 | } 50 | formatterFn.fns = [cb] 51 | 52 | return this.set('formatter', formatterFn) 53 | } 54 | } 55 | else { 56 | this.set('formatter', cb) 57 | } 58 | 59 | return this 60 | }, 61 | } 62 | -------------------------------------------------------------------------------- /plugins/highlight.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | // deps: { 3 | // 'cli-highlight': '^1.1.4', 4 | // }, 5 | 6 | reset() { 7 | this.delete('highlighter') 8 | }, 9 | 10 | /** 11 | * @tutorial https://github.com/fliphub/fliplog#-highlight 12 | * @TODO: should add as a middleware to highlight when called 13 | * 14 | * @param {string | any} [code=null] 15 | * @param {String} [language='javascript'] 16 | * @return {FlipLog} 17 | */ 18 | highlight(code = null, language = 'javascript') { 19 | const clihighlight = this.requirePkg('cli-highlight') 20 | 21 | if (clihighlight === false) return this 22 | 23 | const {highlight} = clihighlight 24 | const opts = {language, ignoreIllegals: false} 25 | 26 | return this.set('highlighter', data => { 27 | const tagged = highlight(data || this.get('data'), opts) 28 | return tagged.replace(/<\/?[^>]+(>|$)/g, '') + '\n' 29 | }) 30 | }, 31 | } 32 | -------------------------------------------------------------------------------- /plugins/index.js: -------------------------------------------------------------------------------- 1 | const ansi = require('./ansi') 2 | const boxen = require('./box') 3 | const beep = require('./beep') 4 | const bar = require('./bar') 5 | const capture = require('./capture') 6 | const chalk = require('./chalk') 7 | const clear = require('./clear') 8 | const diff = require('./diff') 9 | // const file = require('./file') 10 | const filter = require('./filter') 11 | const flags = require('./flags') 12 | const formatter = require('./formatter') 13 | const highlight = require('./highlight') 14 | const inspect = require('./inspect') 15 | const json = require('./json') 16 | const list = require('./list') 17 | const notify = require('./notify') 18 | const presets = require('./presets') 19 | const pretty = require('./pretty') 20 | const progress = require('./progress') 21 | const quick = require('./quick') 22 | const register = require('./register') 23 | const returnVals = require('./returnVals') 24 | const sleep = require('./sleep') 25 | const sparkly = require('./sparkly') 26 | const spinners = require('./spinners') 27 | // const story = require('./story') 28 | const stringify = require('./stringify') 29 | const table = require('./formatter') 30 | const templates = require('./text') 31 | const time = require('./time') 32 | const timer = require('./timer') 33 | const track = require('./track') 34 | const verbose = require('./verbose') 35 | const xterm = require('./xterm') 36 | const expose = require('./expose') 37 | 38 | module.exports = { 39 | ansi, 40 | boxen, 41 | beep, 42 | bar, 43 | capture, 44 | chalk, 45 | clear, 46 | diff, 47 | filter, 48 | flags, 49 | formatter, 50 | highlight, 51 | inspect, 52 | json, 53 | list, 54 | notify, 55 | presets, 56 | pretty, 57 | progress, 58 | quick, 59 | register, 60 | returnVals, 61 | sleep, 62 | sparkly, 63 | spinners, 64 | stringify, 65 | table, 66 | templates, 67 | time, 68 | timer, 69 | track, 70 | verbose, 71 | xterm, 72 | expose, 73 | } 74 | -------------------------------------------------------------------------------- /plugins/inspect.js: -------------------------------------------------------------------------------- 1 | const lib = require('../modules/inspector-gadget') 2 | 3 | module.exports = { 4 | // pass in options for cleaner and use .from? 5 | // clean(data) {} 6 | inspectorGadget() { 7 | return lib 8 | }, 9 | 10 | /** 11 | * @desc create a new cleaner, or return the lib 12 | * @see inspector-gadget/cleaner 13 | * @param {Object | boolean} [from=null] used to call methods on cleaner if needed, true returns as a lib 14 | * @return {Cleaner | FlipChain} has .echo bound to FlipChain 15 | */ 16 | cleaner(from = null) { 17 | if (from === true) { 18 | const cleaner = new lib.cleaner(this) 19 | cleaner.end = () => this.data(cleaner.get('cleaned')) 20 | cleaner.echo = () => this.data(cleaner.get('cleaned')).echo() 21 | return cleaner 22 | } 23 | 24 | const cleaner = new lib.cleaner(this).data(this.get('data')) 25 | 26 | if (from !== null && typeof from === 'object') { 27 | if (from.keys) cleaner.keys(from.keys) 28 | if (from.vals) cleaner.vals(from.vals) 29 | if (from.onMatch) cleaner.onMatch(from.onMatch) 30 | if (from.data) cleaner.data(from.data) 31 | } 32 | 33 | cleaner.log = this 34 | cleaner.end = () => this.data(cleaner.get('cleaned')) 35 | cleaner.echo = () => this.data(cleaner.get('cleaned')).echo() 36 | 37 | return cleaner 38 | }, 39 | inspector() { 40 | return lib.inspect 41 | }, 42 | customInspect() { 43 | return lib.customInspect 44 | }, 45 | } 46 | -------------------------------------------------------------------------------- /plugins/json.js: -------------------------------------------------------------------------------- 1 | const getDefaults = () => { 2 | return { 3 | keysColor: 'blue', 4 | dashColor: 'yellow', 5 | stringColor: 'italic', 6 | numberColor: 'green', 7 | } 8 | } 9 | module.exports = { 10 | // deps: { 11 | // 'prettyjson': '1.2.1', 12 | // }, 13 | 14 | prettyjson(data = null, opts = {}) { 15 | const options = Object.assign(getDefaults(), opts) 16 | const prettyjson = this.requirePkg('prettyjson') // eslint-disable-line 17 | if (data !== null) { 18 | return prettyjson.render(data, options) 19 | } 20 | return prettyjson 21 | }, 22 | 23 | /** 24 | * @tutorial https://github.com/fliphub/fliplog/blob/master/README.md#json 25 | * @param {Object | any} data 26 | * @param {Object} [opts={}] 27 | * @return {FlipLog} @chainable 28 | */ 29 | json(data, opts = {}) { 30 | if (typeof data !== 'object') { 31 | return this.data(data).verbose(5) 32 | } 33 | 34 | opts = Object.assign(getDefaults(), opts) 35 | 36 | // return this.data(this.prettyjson().render(data, opts)) 37 | return this.formatter(() => this.prettyjson().render(data, opts)).data(data) 38 | }, 39 | } 40 | -------------------------------------------------------------------------------- /plugins/list.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | // deps: { 3 | // listr: '0.11.0', 4 | // }, 5 | // reset() {}, 6 | addListItem(title, task, enabled, disabled) { 7 | if (this.has('list') === false) { 8 | this.set('list', []) 9 | } 10 | 11 | let item = {} 12 | 13 | // passing in an object 14 | if (typeof title === 'object' && typeof title !== 'function') { 15 | item = title 16 | } 17 | else { 18 | item = {title, task, enabled, disabled} 19 | } 20 | 21 | this.get('list').push(item) 22 | 23 | return this 24 | }, 25 | startListr() { 26 | const Listr = this.requirePkg('listr') 27 | const list = new Listr() 28 | list.run() 29 | 30 | // this.set('listr', list) 31 | this.delete('list') 32 | return this 33 | }, 34 | listr() { 35 | return this.requirePkg('listr') 36 | }, 37 | } 38 | -------------------------------------------------------------------------------- /plugins/notify.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | // deps: { 3 | // 'node-notifier': '5.1.2', 4 | // }, 5 | 6 | /** 7 | * @tutorial https://github.com/fliphub/fliplog#-notify 8 | * @tutorial https://github.com/mikaelbr/node-notifier 9 | * @todo alias as notification/notify 10 | * @TODO: put as formatter 11 | * 12 | * @param {string | boolean | any} options 13 | * @param {any} [msg=null] 14 | * @param {Boolean} [echo=false] 15 | * @return {FlipLog} 16 | */ 17 | notify(options, msg = null, echo = false) { 18 | const notifier = this.requirePkg('node-notifier') // eslint-disable-line 19 | 20 | if ( 21 | typeof options === 'string' && 22 | typeof msg === 'string' && 23 | echo === true 24 | ) { 25 | notifier.notify({ 26 | title: options, 27 | message: msg, 28 | }) 29 | } 30 | else if (typeof options === 'string' && msg === true) { 31 | notifier.notify(options) 32 | } 33 | else if (echo === true) { 34 | notifier.notify(options) 35 | } 36 | else { 37 | return this.set('data', { 38 | inspect() { 39 | notifier.notify(options) 40 | return '' 41 | }, 42 | }) 43 | } 44 | 45 | return this 46 | }, 47 | } 48 | -------------------------------------------------------------------------------- /plugins/presets.js: -------------------------------------------------------------------------------- 1 | // presets 2 | function presetError(chain) { 3 | return chain.text(chain.chalk().bgRed.black('🚨 error: ') + '\n\n').verbose(10) 4 | } 5 | function presetWarning(chain) { 6 | return chain.text('⚠ warning: ').color('bgYellow.black').verbose(10) 7 | } 8 | function presetInfo(chain) { 9 | return chain.text('ℹ️️ info:').color('blue') 10 | } 11 | function presetNote(chain) { 12 | return chain.text('📋️ note:').color('dim') 13 | } 14 | function presetImportant(chain) { 15 | return chain.text('❗ important:').color('red.bold') 16 | } 17 | 18 | const ignored = [ 19 | '__defineGetter__', 20 | '__defineSetter__', 21 | 'hasOwnProperty', 22 | '__lookupGetter__', 23 | '__lookupSetter__', 24 | 'propertyIsEnumerable', 25 | 'toString', 26 | 'toLocaleString', 27 | 'valueOf', 28 | 'isPrototypeOf', 29 | ] 30 | 31 | function presetHidden(chain) { 32 | /* prettier-ignore */ 33 | const allKeys = obj => 34 | Object 35 | .getOwnPropertyNames(obj) 36 | .concat(Object.getOwnPropertySymbols(obj)) 37 | // .concat(Object.keys(obj)) 38 | 39 | /* prettier-ignore */ 40 | const formatter = data => 41 | allKeys(Object.getPrototypeOf(data)) 42 | .concat(allKeys(data)) 43 | .filter(key => !ignored.includes(key)) 44 | .map(key => ({[key]: Object.getOwnPropertyDescriptor(data, key)})) 45 | 46 | return chain.verbose(100).formatter(formatter) 47 | } 48 | 49 | module.exports = { 50 | reset() { 51 | this.addPreset('error', presetError) 52 | this.addPreset('warning', presetWarning) 53 | this.addPreset('info', presetInfo) 54 | this.addPreset('note', presetNote) 55 | this.addPreset('important', presetImportant) 56 | this.addPreset('desc', presetHidden) 57 | }, 58 | 59 | /** 60 | * @param {string} name 61 | * @param {Object} preset 62 | * @return {FlipLog} 63 | */ 64 | addPreset(name, preset) { 65 | this.presets[name] = preset 66 | if (this[name] === undefined) { 67 | this[name] = () => this.preset(name) 68 | } 69 | return this 70 | }, 71 | 72 | /** 73 | * @tutorial https://github.com/fliphub/fliplog#-presets 74 | * @param {Array | Object} names 75 | * @return {FlipLog} 76 | */ 77 | preset(names) { 78 | if (!Array.isArray(names)) names = [names] 79 | 80 | Object.keys(names).forEach(index => { 81 | const name = names[index] 82 | this.presets[name](this) 83 | }) 84 | 85 | return this 86 | }, 87 | } 88 | -------------------------------------------------------------------------------- /plugins/progress.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | // deps: { 3 | // progress: '1.1.8', 4 | // }, 5 | 6 | /** 7 | * @tutorial https://github.com/fliphub/fliplog#-progress 8 | * 9 | * @TODO: 10 | * - [ ] do not echo right away 11 | * - [ ] https://www.npmjs.com/package/node-progress-bars 12 | * 13 | * @param {Number} [total=20] 14 | * @param {any} [cb=null] 15 | * @param {Number} [interval=100] 16 | * @return {FlipLog} @chainable 17 | */ 18 | progress(total = 20, cb = null, interval = 100) { 19 | if (!process.stdout.isTTY) return this 20 | const ProgressBar = this.requirePkg('progress') 21 | 22 | if (typeof total === 'string' && typeof cb === 'object') { 23 | this.progressBar = new ProgressBar(total, cb) 24 | if (typeof interval === 'function') { 25 | interval(this.progressBar) 26 | } 27 | return this 28 | } 29 | 30 | if (cb === null) { 31 | cb = bar => { 32 | bar.tick() 33 | if (bar.complete) clearInterval(this.progressCb) 34 | } 35 | } 36 | 37 | this.progressBar = new ProgressBar(' ╢:bar╟', { 38 | // complete: green, 39 | // incomplete: red, 40 | total, 41 | complete: '█', 42 | incomplete: '░', 43 | clear: true, 44 | 45 | // terminal columns - package name length - additional characters length 46 | width: (process.stdout.columns || 100) - 50 - 3, 47 | }) 48 | 49 | if (interval) { 50 | const cbcb = () => cb(this.progressBar, this.progressCb) 51 | this.progressCb = setInterval(cbcb, interval) 52 | } 53 | else { 54 | this.progressCb = cb(this.progressBar) 55 | } 56 | 57 | // this.progress = new Progress().init(100) 58 | return this 59 | }, 60 | } 61 | -------------------------------------------------------------------------------- /plugins/quick.js: -------------------------------------------------------------------------------- 1 | // ----------------------------- errors, catching, resetting ------------------ 2 | module.exports = { 3 | reset() { 4 | // so it can be called with 5 | // `.catch(log.catch)` 6 | this.catch = this.catch.bind(this) 7 | }, 8 | 9 | /** 10 | * @tutorial https://github.com/fliphub/fliplog#use-built-ins 11 | * @param {Error} error 12 | * @return {FlipLog} 13 | */ 14 | error(error) { 15 | if (arguments.length === 1) { 16 | return this.preset('error').verbose(5).data(error).echo() 17 | } 18 | 19 | for (const arg of arguments) { 20 | this.preset('error').verbose(5).data(arg).echo() 21 | } 22 | 23 | return this 24 | }, 25 | 26 | /** 27 | * just output some data quickly 28 | * @param {any} data 29 | * @return {FlipLog} 30 | */ 31 | just(data) { 32 | if (typeof data === 'string') this.text(data) 33 | else this.data(data) 34 | this.verbose(5) 35 | return this.echo() 36 | }, 37 | 38 | /** 39 | * @tutorial https://github.com/fliphub/fliplog#-quick 40 | * @param {any} arg 41 | * @return {FlipLog} 42 | */ 43 | quick(arg) { 44 | this.reset() 45 | console.log('\n') 46 | this.color('yellow.bold') 47 | .text('=========== 💨 quick 💨 ===========') 48 | .space(1) 49 | if (arguments.length === 1) return this.data(arg).verbose().exit() 50 | return this.data(arguments).verbose().exit() 51 | }, 52 | 53 | /** 54 | * @NOTE exits process 55 | * @param {Boolean} [log=true] false will not log that it exited 56 | */ 57 | exit(log = true) { 58 | // this.trace() 59 | this.echo() 60 | this.reset() 61 | if (log) console.log('🛑 exit \n') 62 | process.exit() 63 | }, 64 | 65 | /** 66 | * @param {Error} e 67 | * @param {*} arg2 68 | * @param {*} arg3 69 | * @tutorial https://github.com/fliphub/fliplog#-catch-errors 70 | * @see FlipLog.exit 71 | */ 72 | catch(e, arg2 = null, arg3 = null) { 73 | if (arg2 === null) { 74 | this.error(e).exit(1) 75 | } 76 | else { 77 | this.error(arguments).exit(1) 78 | } 79 | }, 80 | 81 | /** 82 | * @since 0.2.3 83 | * @param {Error} e 84 | * @tutorial https://github.com/fliphub/fliplog#-catch-errors 85 | * @see FlipLog.exit 86 | */ 87 | catchAndThrow(e) { 88 | this.error(e).echo() 89 | throw e 90 | }, 91 | } 92 | -------------------------------------------------------------------------------- /plugins/register.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | registerConsole() { 3 | console.verbose = (text, ...data) => this.verbose().data(...data).echo() 4 | console.info = (text, ...data) => 5 | this.emoji('info').verbose().data(...data).echo() 6 | console.error = (text, e) => this.preset('error').error(e).echo() 7 | console.track = () => this.trackConsole().echo() 8 | console.trace = () => this.trace().echo() 9 | console.note = (text, ...data) => 10 | this.preset('note').text(text).data(...data).echo() 11 | console.warning = (text, ...data) => 12 | this.preset('warning').text(text).data(...data).echo() 13 | console.spinner = (text, ...options) => this.spinner(text, ...options) 14 | 15 | console.time = name => this.timer.start(name).echo() 16 | console.timeLap = name => this.timer.lap(name) 17 | console.timeLapEcho = name => this.timer.lap(name).echo() 18 | console.timeEnd = name => this.fliptime().end(name).log(name) 19 | 20 | console.bold = (text, data = OFF) => this.bold(text).data(data).echo() 21 | console.red = (text, data = OFF) => this.red(text).data(data).echo() 22 | console.yellow = (text, data = OFF) => this.yellow(text).data(data).echo() 23 | console.cyan = (text, data = OFF) => this.cyan(text).data(data).echo() 24 | console.underline = (text, data = OFF) => 25 | this.underline(text).data(data).echo() 26 | console.magenta = (text, data = OFF) => this.magenta(text).data(data).echo() 27 | 28 | console.box = (...options) => this.box(...options).echo() 29 | console.beep = (...options) => this.beep(...options).echo() 30 | console.timer = (...options) => this.timer() 31 | console.table = (...options) => this.table(...options).echo() 32 | console.diff = (...options) => this.diff(...options) 33 | console.diffs = () => this.diffs().echo() 34 | console.stringify = (...data) => this.stringify(...data).echo() 35 | console.stack = (...data) => this.stack(...data).echo() 36 | console.json = (...data) => this.json(...data).echo() 37 | console.filter = (...data) => this.filter(...data).echo() 38 | console.tags = (...data) => this.tags(...data).echo() 39 | console.quick = (...data) => this.quick(...data).echo() 40 | console.exit = (...data) => this.exit(...data).echo() 41 | console.reset = (...data) => this.reset(...data).echo() 42 | console.sleep = (...data) => this.sleep(...data).echo() 43 | console.slow = (...data) => this.slow(...data).echo() 44 | 45 | return this 46 | }, 47 | 48 | // https://gist.github.com/benjamingr/0237932cee84712951a2 49 | registerCatch() { 50 | process.on('unhandledRejection', (reason, p) => { 51 | console.log('Possibly Unhandled Rejection at: Promise ', p, ' reason: ', reason) 52 | // this.red(p).echo() 53 | // this.error(reason).echo() 54 | process.exit(1) 55 | // this.catchAndThrow(reason, p) 56 | }) 57 | process.on('unhandledException', exception => { 58 | console.log('fliplog catching unhandledException') 59 | this.error(exception).echo() 60 | process.exit(1) 61 | // this.catchAndThrow(exception) 62 | }) 63 | }, 64 | } 65 | -------------------------------------------------------------------------------- /plugins/returnVals.js: -------------------------------------------------------------------------------- 1 | // https://www.youtube.com/watch?v=SwSle66O5sU 2 | const OFF = `${~315 >>> 3}@@` 3 | 4 | module.exports = { 5 | // ----------------------------- getting data ------------------ 6 | 7 | /** 8 | * @alias logText 9 | * @since 0.4.0 10 | * @return {string} text log 11 | */ 12 | getText() { 13 | const text = this.logText() 14 | return text === OFF ? '' : text 15 | }, 16 | /** 17 | * @alias logData 18 | * @since 0.4.0 19 | * @return {any} 20 | */ 21 | getData() { 22 | const data = this.logData() 23 | return data === OFF ? undefined : data 24 | }, 25 | 26 | /** 27 | * @since 0.2.0 28 | * @tutorial https://github.com/fliphub/fliplog#return 29 | * @return {ReturnVals} 30 | */ 31 | returnVals() { 32 | const text = this.logText() 33 | const datas = this.logData() 34 | 35 | if (datas !== OFF && text !== OFF) return {text, datas} 36 | else if (datas !== OFF) return {datas} 37 | else if (text !== OFF) return {text} 38 | else return {text, datas} 39 | }, 40 | 41 | /** 42 | * @tutorial https://github.com/fliphub/fliplog#return 43 | * @since 0.2.0 (added param 0.3.0) 44 | * @param {boolean} [textAndDataOnly=false] 45 | * @return {ReturnVal} 46 | */ 47 | return(textAndDataOnly = false) { 48 | if (textAndDataOnly === true) { 49 | return this.returnVals() 50 | } 51 | 52 | if (this.has('tags') === true) { 53 | this._filter() 54 | } 55 | const returnVals = this.returnVals() 56 | const entries = this.entries() 57 | this.reset() 58 | return Object.assign(entries, returnVals) 59 | }, 60 | } 61 | -------------------------------------------------------------------------------- /plugins/sleep.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @tutorial https://github.com/fliphub/fliplog#-slow 3 | */ 4 | module.exports = { 5 | // ----------------------------- sleeping ------------------ 6 | // deps: { 7 | // 'sleepfor': '*', 8 | // }, 9 | 10 | reset() { 11 | // @NOTE: this should not be deleted o.o 12 | // this.delete('sleepBetween') 13 | }, 14 | 15 | /** 16 | * @param {Number} [args=false] 17 | * @return {Function} sleepfor 18 | */ 19 | sleepfor(args = false) { 20 | const sleepfor = this.requirePkg('sleepfor') 21 | 22 | if (args !== false) sleepfor(args) 23 | 24 | return sleepfor 25 | }, 26 | 27 | /** 28 | * @param {Number} [time=1000] 29 | * @return {FlipLog} 30 | */ 31 | sleep(time = 1000) { 32 | this.sleepfor(time) 33 | return this 34 | }, 35 | 36 | /** 37 | * @param {Number} [time=100] 38 | * @return {FlipLog} 39 | */ 40 | slow(time = 100) { 41 | return this.set('sleepBetween', time) 42 | }, 43 | 44 | /** 45 | * @TODO: middleware... 46 | * @see FlipLog.slow 47 | * @return {FlipLog} 48 | */ 49 | sleepIfNeeded() { 50 | if (this.has('sleepBetween') === true) { 51 | this.sleepfor(this.get('sleepBetween')) 52 | } 53 | 54 | return this 55 | }, 56 | } 57 | -------------------------------------------------------------------------------- /plugins/sparkly.js: -------------------------------------------------------------------------------- 1 | const {random, shuffle, chance} = require('../deps/fun') 2 | 3 | module.exports = { 4 | // deps: { 5 | // 'sparkly': '3.1.2', 6 | // }, 7 | sparkly(input = null, options = null) { 8 | const sparkly = this.requirePkg('sparkly') 9 | if (!sparkly) return this 10 | 11 | if (input === null) { 12 | // order from random 13 | input = [ 14 | [0, 3, 5, 8, 4, 3, 4, 10], 15 | [1, 2, 3, 4, 5, 6, 7, 8], 16 | [1, 2, 3, 4, 5, 6, 7, 8], 17 | [1, 18, 9, 4, 10], 18 | ] 19 | input = shuffle(input).pop() 20 | } 21 | 22 | if (options === null && chance()) { 23 | options = {style: 'fire'} 24 | } 25 | 26 | return this.set('data', sparkly(input, options)) 27 | }, 28 | } 29 | -------------------------------------------------------------------------------- /plugins/story.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | // ----------------------------- story ------------------ 3 | 4 | // @TODO: 5 | story() { 6 | if (!this.mainStory) { 7 | const {mainStory} = require('storyboard') 8 | this.mainStory = mainStory 9 | } 10 | return this 11 | }, 12 | child(title) { 13 | const story = this.mainStory.child({title}) 14 | story.parent = this 15 | return story 16 | }, 17 | } 18 | -------------------------------------------------------------------------------- /plugins/stringify.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | // deps: { 3 | // 'javascript-stringify': '1.6.0', 4 | // }, 5 | 6 | jsStringify(data = null) { 7 | // const stringify = this.requirePkg('javascript-stringify') 8 | const stringify = require('../modules/javascript-stringify') 9 | if (data === null) return stringify 10 | 11 | const str = stringify(data) 12 | return str 13 | }, 14 | 15 | /** 16 | * @tutorial https://github.com/fliphub/fliplog#-stringifying 17 | * @param {any} data 18 | * @param {any} [replacer=null] 19 | * @param {String} [spacer=' '] 20 | * @param {any} [options=null] javascript-stringify options 21 | * @return {FlipLog} 22 | */ 23 | stringify(data, replacer = null, spacer = ' ', options = null) { 24 | const stringify = this.jsStringify() 25 | const prettified = stringify(data, replacer, spacer, options) 26 | return this.data(prettified) 27 | }, 28 | } 29 | -------------------------------------------------------------------------------- /plugins/table.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | deps: { 3 | 'cli-table2': '0.2.0', 4 | }, 5 | 6 | // reset() { 7 | // // this.delete('table') 8 | // }, 9 | 10 | /** 11 | * @tutorial https://github.com/fliphub/fliplog#-tables 12 | * @param {Array} head 13 | * @param {Array} data 14 | * @return {FlipLog} 15 | */ 16 | table(head, data) { 17 | const Table = this.requirePkg('cli-table2') 18 | 19 | this.row = row => this.Table.push(data) 20 | 21 | if (!data) { 22 | let table = new Table({head}) 23 | this.Table = table 24 | return this 25 | } 26 | 27 | let table = new Table({head}) 28 | table.push(data) 29 | this.Table = table 30 | 31 | return this.data(table.toString()) 32 | }, 33 | } 34 | -------------------------------------------------------------------------------- /plugins/time.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | reset() { 3 | // console.log(this.entries()) 4 | // console.log(this.get('time')) 5 | // persist the time logging 6 | if (this.get('time')) { 7 | this.time(true) 8 | } 9 | this.time(false) 10 | }, 11 | } 12 | -------------------------------------------------------------------------------- /plugins/timer.js: -------------------------------------------------------------------------------- 1 | let fliptime 2 | 3 | module.exports = { 4 | // deps: { 5 | // 'fliptime': '*', 6 | // }, 7 | 8 | // ----------------------------- timer ------------------ 9 | fliptime() { 10 | fliptime = fliptime || this.requirePkg('fliptime') 11 | return fliptime 12 | }, 13 | startTimer(name) { 14 | this.fliptime().start(name) 15 | return this 16 | }, 17 | stopTimer(name) { 18 | this.fliptime().stop(name) 19 | return this 20 | }, 21 | lapTimer(name) { 22 | this.fliptime().lap(name) 23 | return this 24 | }, 25 | echoTimer(name) { 26 | this.fliptime().log(name) 27 | return this 28 | }, 29 | stopAndEchoTimer(name) { 30 | this.fliptime().stop(name).log(name) 31 | return this 32 | }, 33 | } 34 | -------------------------------------------------------------------------------- /plugins/verbose.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fliphub/fliplog/b0a1581e749a41ab65731f88cc90f2c24d20247d/plugins/verbose.js -------------------------------------------------------------------------------- /plugins/web.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @TODO 3 | * - [ ] table (compat with node one) 4 | * - [ ] group 5 | * - [ ] warn, dir, error, log, debug 6 | * @type {Object} 7 | */ 8 | module.exports = { 9 | fontWeight(weight = 'bold') { 10 | return this.set('fontweight', weight) 11 | }, 12 | fontSize(size = 'x-large') { 13 | return this.set('fontsize', size) 14 | }, 15 | color(color, bgColor = null) { 16 | return this.set('color', color).set('bgColor', bgColor) 17 | }, 18 | dir() { 19 | return this.set('log', console.dir) 20 | }, 21 | table() { 22 | return this.set('log', console.table) 23 | }, 24 | 25 | /** 26 | * @TODO improve the returning function 27 | * @example console.log('%cLogChain', 'color: blue; font-size: x-large') 28 | * @see http://stackoverflow.com/questions/7505623/colors-in-javascript-console 29 | * @see https://developers.google.com/web/tools/chrome-devtools/console/console-write#styling_console_output_with_css 30 | * @return {Function} a function prototype bound to console to output in the correct location, needs work 31 | */ 32 | echo() { 33 | if (!this.parent || (this.parent && this.parent.get('debug') === true)) { 34 | let {data, text, color, fontsize, fontweight} = this.entries() 35 | let log = this.get('log') || console.log 36 | 37 | let fmt = '' 38 | if (color) fmt += 'color: ' + color + ';' 39 | if (fontweight) fmt += 'font-weight: ' + fontweight + ';' 40 | if (fontsize) fmt += 'font-size: ' + fontsize + ';' 41 | 42 | const args = [text, fmt, data] 43 | 44 | return Function.prototype.apply.bind(log, console, args) 45 | } 46 | 47 | // or noop if disabled 48 | return function noop() {} // eslint-disable-line 49 | }, 50 | 51 | data(data) { 52 | return this.set('data', data) 53 | }, 54 | 55 | text(string) { 56 | return this.set('text', '%c' + string) 57 | }, 58 | } 59 | -------------------------------------------------------------------------------- /plugins/weights.js: -------------------------------------------------------------------------------- 1 | // https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md 2 | // https://www.tutorialspoint.com/log4j/log4j_logging_levels.htm 3 | // @TODO: 4 | module.exports = { 5 | /** 6 | * @TODO: implement this 7 | * @example .filter('< debug < verbose') 8 | * @return {FlipLog} @chainable 9 | */ 10 | weights() { 11 | const defaults = { 12 | 11: ['verbose', 'all', '*'], 13 | 9: ['debug'], 14 | // some wiggle room ^ for better custom, 15 | // below is quite fixed & standard 16 | 6: ['notice', 'significant', ''], 17 | 5: ['info'], 18 | 4: ['warn', 'important'], 19 | 3: ['error', 'critical', 'exception'], 20 | 2: ['alert'], 21 | 1: ['emergency', 'fatal'], 22 | 0: ['silent', 'off'], 23 | } 24 | return this 25 | }, 26 | } 27 | -------------------------------------------------------------------------------- /plugins/xterm.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | // deps: { 3 | // 'cli-color': '1.2.0', 4 | // }, 5 | 6 | /** 7 | * @tutorial https://github.com/fliphub/fliplog/blob/master/README.md#xterm 8 | * @see cli-color 9 | * @param {number} color 10 | * @param {number} [bgColor] 11 | * @return {FlipLog} @chainable 12 | */ 13 | xterm(color, bgColor) { 14 | const clc = this.requirePkg('cli-color') 15 | 16 | if (!clc) return this 17 | 18 | if (typeof color === 'string' && color.includes('.')) { 19 | const colorArr = color.split('.') 20 | const txt = colorArr.shift() 21 | const bg = colorArr.pop() 22 | color = clc.xterm(txt).bgXterm(bg) 23 | } 24 | else if (color && bgColor) { 25 | color = clc.xterm(color).bgXterm(bgColor) 26 | } 27 | else if (Number.isInteger(color)) { 28 | color = clc.xterm(color) 29 | } 30 | else { 31 | color = clc.xterm(202).bgXterm(236) 32 | } 33 | 34 | return this.color(color) 35 | }, 36 | } 37 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | const pkg = require('./package') 2 | const nodeResolve = require('rollup-plugin-node-resolve') 3 | const commonjs = require('rollup-plugin-commonjs') 4 | 5 | export default { 6 | useStrict: false, 7 | entry: 'dist/index.js', 8 | 9 | plugins: [ 10 | nodeResolve({ 11 | jsnext: true, 12 | module: true, 13 | main: true, 14 | preferBuiltins: true, 15 | }), 16 | commonjs({ 17 | include: '**/**', 18 | }), 19 | ], 20 | targets: [ 21 | { 22 | dest: pkg.main, 23 | format: 'cjs', 24 | }, 25 | { 26 | dest: pkg.module, 27 | format: 'es', 28 | }, 29 | ], 30 | } 31 | -------------------------------------------------------------------------------- /test/_benchFilter.js: -------------------------------------------------------------------------------- 1 | var Benchmark = require('benchmark') 2 | var suite = new Benchmark.Suite() 3 | const newLogFn = require('../') 4 | const oldLogFn = require('./_old') 5 | 6 | const newFnFilter = () => { 7 | for (var i = 0; i < 10; i++) { 8 | newLogFn.filter('!me').text('me').tags('me').echo(false) 9 | newLogFn.filter('yup').text('yup').tags('yup').echo(false) 10 | } 11 | } 12 | 13 | const oldFnFilter = () => { 14 | for (var i = 0; i < 10; i++) { 15 | oldLogFn.filter('!me').text('me').tags('me').echo(false) 16 | oldLogFn.filter('yup').text('yup').tags('yup').echo(false) 17 | } 18 | } 19 | 20 | let cycles = [] 21 | 22 | suite 23 | .add('oldf', oldFnFilter) 24 | .add('newf', newFnFilter) 25 | .on('cycle', (event) => { 26 | console.log(String(event.target)) 27 | cycles.push(String(event.target)) 28 | }) 29 | .on('complete', function() { 30 | console.log('Fastest is ' + this.filter('fastest').map('name')) 31 | console.log('================') 32 | console.log(this.map(bnch => bnch.times.elapsed)) 33 | console.log(cycles) 34 | }) 35 | .run({'async': false}) 36 | -------------------------------------------------------------------------------- /test/_debug.js: -------------------------------------------------------------------------------- 1 | const argv = process.argv.slice(0) 2 | process.argv.push('--DEBUG_DEPTH=1') 3 | process.argv.push('--DEBUG_SHOW_HIDDEN=false') 4 | process.argv.push('--DEBUG_COLORS=false') 5 | 6 | process.argv.push(`--debug 'eh, !canada'`) 7 | 8 | const log = require('../') 9 | 10 | // log.quick(log) 11 | const obj = { 12 | debug: { 13 | eh: true, 14 | super: { 15 | deep: { 16 | nope: 0, 17 | }, 18 | }, 19 | }, 20 | } 21 | 22 | // disabled by flags 23 | log.prettyobj(obj).tag('canada').echo() 24 | log.data(obj).bold('ehn').tag('eh').echo() 25 | 26 | process.argv = argv 27 | 28 | // this should echo deep because argv is restored, 29 | // ...but even if it was not restored, 30 | // this will still go deep, but normal data inspecting does not 31 | // @TODO: lots of formatting/formatters that have to respect the flags... 32 | log.prettyobj(obj).bold('ehn').tag('eh').echo() 33 | -------------------------------------------------------------------------------- /test/_emptyMemory.js: -------------------------------------------------------------------------------- 1 | console.log(process.memoryUsage()) 2 | 3 | const os = require('os') 4 | 5 | 6 | console.log(os.freemem()) 7 | console.log(os.totalmem()) 8 | -------------------------------------------------------------------------------- /test/boxen.js: -------------------------------------------------------------------------------- 1 | const log = require('../') 2 | 3 | log.bold().box('fliplog').echo() 4 | 5 | // log.quick(log.box('fliplog').color('bold').returnVals()) 6 | 7 | // log.bold().box('fliplog').echo() 8 | 9 | // log.box('fliplog', true) 10 | log 11 | .boxStyles({borderColor: 'blue'}) 12 | .box('fliplog') 13 | .echo() 14 | 15 | // console.log(values) 16 | 17 | // const boxen = require('boxen') 18 | // console.log(boxen('fliplog', {padding: 1, margin: 1, borderStyle: 'double', borderColor: 'blue'})) 19 | -------------------------------------------------------------------------------- /test/capturing.js: -------------------------------------------------------------------------------- 1 | const log = require('../') 2 | 3 | log.startCapturing() 4 | console.log('ok') 5 | log.stopCapturing() 6 | 7 | console.log(log.savedLog) 8 | console.assert(log.savedLog.length > 0) 9 | -------------------------------------------------------------------------------- /test/charm.js: -------------------------------------------------------------------------------- 1 | let charm = require('../').requirePkg('charm')() 2 | charm.pipe(process.stdout) 3 | charm.reset() 4 | 5 | let colors = ['red', 'cyan', 'yellow', 'green', 'blue'] 6 | let text = 'Always after me lucky charms.' 7 | 8 | let offset = 0 9 | let iv = setInterval(() => { 10 | let y = 0, dy = 1 11 | for (let i = 0; i < 40; i++) { 12 | let color = colors[(i + offset) % colors.length] 13 | let c = text[(i + offset) % text.length] 14 | charm.move(1, dy).foreground(color).write(c) 15 | 16 | y += dy 17 | if (y <= 0 || y >= 5) dy *= -1 18 | } 19 | charm.position(0, 1) 20 | offset++ 21 | }, 150) 22 | -------------------------------------------------------------------------------- /test/dept.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fliphub/fliplog/b0a1581e749a41ab65731f88cc90f2c24d20247d/test/dept.js -------------------------------------------------------------------------------- /test/diff.js: -------------------------------------------------------------------------------- 1 | const log = require('../') 2 | 3 | const eh = { 4 | eh: true, 5 | } 6 | const two = { 7 | added: true, 8 | eh: false, 9 | } 10 | log.diff(eh, two).echo() 11 | log.diff('eh', 'ehoh').echo() 12 | 13 | const oneOne = {oneOne: 'was a race horse 🐎'} 14 | log.diff(oneOne) 15 | const twoTwo = Object.assign({twoTwo: 'was one too.'}) 16 | log.diff(twoTwo) 17 | log.echo() 18 | 19 | let oneOneTwoTwo = 'one-one was a race horse 🐎 ' 20 | log.diff(oneOneTwoTwo) 21 | log.diff(oneOneTwoTwo + '... two-two was one, two.') 22 | log.echo() 23 | 24 | log 25 | .bold('💸\n') 26 | .tree({ 27 | going: { 28 | down: { 29 | down: { 30 | down: '🔥', 31 | }, 32 | }, 33 | }, 34 | }) 35 | .echo() 36 | -------------------------------------------------------------------------------- /test/examples.js: -------------------------------------------------------------------------------- 1 | const log = require('../') 2 | 3 | // const factoried = log.factory() 4 | // 5 | // const dirMatch = new RegExp(__dirname, 'gmi') 6 | // const logger = (text, data) => { 7 | // const clean = log 8 | // .cleaner(true) 9 | // .vals([dirMatch, x => typeof x === 'string']) 10 | // .keys([dirMatch]) 11 | // .onMatch((arg, traverser) => arg.replace(dirMatch, 'funfunfun!')) 12 | // .onNonMatch(arg => { 13 | // // console.log({arg}, 'nonmatch') 14 | // }) 15 | // .data({data, text}) 16 | // .clean() 17 | // 18 | // const cleaned = clean.cleaned() 19 | // console.log(cleaned.text, cleaned.data) 20 | // } 21 | // 22 | // log 23 | // .preset('error') 24 | // .data(new Error('prettyfull!')) 25 | // .set('logger', logger) 26 | // .echo() 27 | 28 | function traceIt() { 29 | function stackIt() { 30 | function louder() { 31 | // require.main.filename = 'INTERNAL-TESTS/' + __filename 32 | const customError = new Error('prettyfull!') 33 | customError.stack = customError.stack.replace(/fliplog/, 'INTERNAL-TESTS') 34 | customError.eh = true 35 | customError.extraPretty = true 36 | Object.defineProperty(customError, 'prop', { 37 | configurable: true, 38 | enumerable: true, 39 | value: 'eh', 40 | }) 41 | // log.set('logger', logger) 42 | 43 | log.preset('error').data(customError).echo() 44 | } 45 | louder() 46 | } 47 | stackIt() 48 | } 49 | traceIt() 50 | 51 | log 52 | .text('\n========================================\n') 53 | .color('bold') 54 | .time(false) 55 | .echo() 56 | 57 | log.text('eh').data({some: 'data'}).echo() 58 | log.data('twoooo').verbose().echo() 59 | log.text('text').data({some: 'data!'}).verbose().echo() 60 | log.text('tosource').data({some: 'data!'}).tosource().echo() 61 | log.preset('warning').data(' this message will self destruct').echo() 62 | 63 | log.time(true).xterm(202, 236).text(' orange!!! ').echo() 64 | 65 | log 66 | .text('\n========================================\n') 67 | .color('bold') 68 | .time(false) 69 | .echo() 70 | 71 | log 72 | .color('cyan') 73 | .text('🕳 so deep, so colorful, so meta 🎨 ') 74 | .data(log) 75 | .verbose(10) 76 | .echo() 77 | -------------------------------------------------------------------------------- /test/filter-plus.js: -------------------------------------------------------------------------------- 1 | const log = require('../') 2 | 3 | // log.stats = { 4 | // process: process.memoryUsage(), 5 | // os: require('os').freemem(), 6 | // version: process.... 7 | // flags... 8 | // } 9 | 10 | log.filter('>= 1') 11 | log.level(1).blue('above 1... success').echo() 12 | log.level(0).red('not above 1...').echo() 13 | 14 | const log2 = log.factory() 15 | 16 | log.filter(['canada*']) 17 | log.tag('canada-eh').white('canadian, pass.').echo() 18 | 19 | log.filter(['eh*', '!warm', tag => (/ez/).test(tag)]) 20 | log.tag('eh').underline('eh').echo() 21 | log.tag('warm').red('warm').echo() 22 | log.tag('ez').yellow('ez').echo() 23 | // log.filter([0, 1, 2, 'matcher:*']) 24 | 25 | 26 | // log.namespace() 27 | // log.namespaces({ 28 | // 0: '> 0', 29 | // 1: 'silent', 30 | // 2: 'silent', 31 | // }) 32 | 33 | // log.filter({ 34 | // namespace... '> 0' 35 | // }) 36 | // log.lvl(1) 37 | // log.tag(0) 38 | -------------------------------------------------------------------------------- /test/filter.js: -------------------------------------------------------------------------------- 1 | // eslint func-names: OFF 2 | // eslint-disable-next-line 3 | 'use strict' 4 | 5 | const log = require('../') 6 | const enhanced = require('../deps/assert') 7 | const {Chain, toArr} = require('chain-able') 8 | 9 | // const log = require('../test/_old') 10 | 11 | // log.capture() 12 | // console.log('eh out') 13 | // log.stopCapturing() 14 | // console.assert(log.savedLog.length > 0, 'has saved logs') 15 | // process.exit() 16 | 17 | // - means no 18 | // + means yes: always 19 | // # for priority? 20 | // 21 | // 22 | // blank means yes, unless another tag overrides? 23 | // but that is silly since it is default 24 | 25 | const done = [] 26 | 27 | // .method('plan', function() { 28 | // console.log(this) 29 | // return this 30 | // }) 31 | Chain.prototype.method = function(name, fn) { 32 | this[name] = function(a, b, c, d, e) { 33 | return fn.call(this, a, b, c, d, e) 34 | } 35 | return this 36 | } 37 | Chain.prototype.methods = function(fns) { 38 | Object.keys(fns).forEach(key => { 39 | this[key] = fns[key].bind(this) 40 | }) 41 | return this 42 | } 43 | 44 | // const assert = require('assert') 45 | // const enhancedAssert = enhanced(assert) 46 | const powerAssert = require('power-assert') 47 | 48 | const planner = new Chain() 49 | .wrap(chain => chain.set('assertions', [])) 50 | .extendGetSet(['assertions']) 51 | .extend(['timeout']) 52 | .methods({ 53 | plan(times) { 54 | const cb = () => { 55 | try { 56 | powerAssert(this.get('assertions').filter(Boolean).length === times) 57 | } 58 | catch (e) { 59 | log.data(e).bold('did not have the same length assertions').echo() 60 | } 61 | } 62 | 63 | this.timeoutcb = cb 64 | this.resetTimeout = () => { 65 | clearTimeout(this.timeouts) 66 | this.timeouts = setTimeout(cb, this.get('timeout')) 67 | } 68 | 69 | this.resetTimeout() 70 | return this.set('plan', times) 71 | }, 72 | assert(assertion) { 73 | const assertions = toArr(assertion).map(powerAssert) 74 | return this 75 | .tap('assertions', arr => arr.concat(assertions)) 76 | .wrap(() => this.resetTimeout) 77 | }, 78 | }) 79 | 80 | // log.data(planner.plan()).exit() 81 | 82 | // planner.timeout(1).plan(3) 83 | 84 | log.filter(args => { 85 | if (planner.getAssertions().length === 2) { 86 | planner.assert(true) 87 | return true 88 | } 89 | else { 90 | planner.assert(typeof args === 'object') 91 | } 92 | 93 | return null 94 | }) 95 | 96 | const arg1 = log.tags('args,canada').text('args').echo() 97 | const arg2 = log.tags('me').text('me').echo() 98 | 99 | // ^ arg1 & arg2 make 2 assertions, this one is allowed 100 | const eh = log.blue('allowed').echo() 101 | 102 | // does not call filter, is forceEcho 103 | log.red('.forceEcho()').forceEcho() 104 | 105 | // .echo() 106 | 107 | // console.log(arg1, arg2) 108 | -------------------------------------------------------------------------------- /test/flags.js: -------------------------------------------------------------------------------- 1 | // cannot seem to pass flags into postinstall script when installing 2 | // e.g. FLIPLOG=TRUE npm install fliplog@0.2.0-beta.10 --save -- --fliplogs=true -- --fliplogs2=true -- --fliplogs3=true 3 | // 4 | // ways to achieve this: 5 | // 6 | // 1. add tags for feature flags, e.g., 7 | // - `npm publish --tag magic` 8 | // - `npm i --save fliplog@magic` 9 | // 2. postinstall hooks t 10 | // - to install dependencies dynamically 11 | // - then cache them 12 | // 13 | // 3. make users install the deps 14 | // 4. interactive cli on postinstall, but would cause issues on things like travis 15 | // 16 | console.log('ARGV FLAGS!!!') 17 | console.log(process.argv) 18 | console.log('----- ENV ----') 19 | console.log(process.env.FLIPLOG) 20 | -------------------------------------------------------------------------------- /test/formatter.js: -------------------------------------------------------------------------------- 1 | const log = require('../') 2 | 3 | function cb(data) { 4 | if (!data || typeof data !== 'object') return data 5 | 6 | Object 7 | .keys(data) 8 | .forEach(key => { 9 | if (typeof data[key] === 'string') 10 | data[key] = data[key].replace(/\s{2}/gmi, ' ') 11 | else if (Array.isArray(data[key])) 12 | data[key] = data[key].map(a => cb(a.name)) 13 | }) 14 | 15 | return data 16 | } 17 | 18 | const fixture = { 19 | str: 'I have too many spaces', 20 | arr: [{name: 'eh'}, {noname: 'just undefined'}], 21 | } 22 | 23 | log 24 | .formatter(cb) 25 | .data(fixture) 26 | .echo() 27 | -------------------------------------------------------------------------------- /test/from.js: -------------------------------------------------------------------------------- 1 | const log = require('../') 2 | 3 | // console.log(log) 4 | // log('???function...').echo() 5 | 6 | // log.trace() 7 | // log.verbose(5).data({eh: true}).echo() 8 | // log('eh!') 9 | 10 | log.from({ 11 | data: 'data', 12 | text: 'eh', 13 | color: 'bold', 14 | echo: true, 15 | }) 16 | -------------------------------------------------------------------------------- /test/fun.js: -------------------------------------------------------------------------------- 1 | const log = require('../') 2 | 3 | function highlitedWithColors() { return 'notice me' } 4 | log.data(highlitedWithColors).tosource().highlight().echo() 5 | 6 | log.sparkly().echo() 7 | log.notify('woot echo!').echo() 8 | log.notify('woot true!', true) 9 | log.notify('woot!', 'description').echo() 10 | log.bar().echo() 11 | log.beep(1).echo() 12 | // log.ora('spin baby spin').start() 13 | 14 | log 15 | .bar([[0, 1], [1, 5], [2, 5], [3, 1], [4, 6]]) 16 | .barStyles({colors: 'ascii'}) 17 | .echo() 18 | 19 | 20 | const points = [] 21 | for (let i = 0; i < Math.PI * 2; i += Math.PI / 1000) { 22 | points.push([i, Math.cos(i)]) 23 | } 24 | log.bar(points).echo() 25 | -------------------------------------------------------------------------------- /test/indent.js: -------------------------------------------------------------------------------- 1 | const log = require('../') 2 | 3 | log 4 | .indent(10) 5 | .bold('PRETTYOBJ') 6 | .prettyobj({ 7 | warnings: 0, 8 | apiStyle: 'Optimised numbers (Best performance)', 9 | target: 'server', 10 | uglify: true, 11 | removeExportsInterop: true, 12 | removeUseStrict: true, 13 | replaceProcessEnv: true, 14 | ensureES5: true, 15 | treeshake: true, 16 | nested: { 17 | deep: { 18 | deeper: { 19 | alltheway: [['array', 'of', 'arrays'], 'yup', ['mixed', 1, Infinity]], 20 | }, 21 | }, 22 | }, 23 | }) 24 | .echo() 25 | -------------------------------------------------------------------------------- /test/isnode.js: -------------------------------------------------------------------------------- 1 | require('jsdom-global')() 2 | const is = require('../modules/is-nodejs') 3 | 4 | console.log(is) 5 | const {isNode, isWeb, hasWindow, isWebWorker} = is 6 | console.log({isNode, isWeb, hasWindow, isWebWorker}) 7 | -------------------------------------------------------------------------------- /test/pretty.js: -------------------------------------------------------------------------------- 1 | const log = require('../') 2 | 3 | var obj = {property: {}} 4 | obj.circularReference = obj 5 | obj[Symbol('foo')] = 'foo' 6 | obj.map = new Map() 7 | obj.map.set('prop', 'value') 8 | obj.array = [1, NaN, Infinity] 9 | 10 | // log.bold('========= console ========').echo() 11 | // console.log(obj) 12 | // 13 | // console.log(require('pretty-format')(obj)) 14 | // console.log(log) 15 | // log.quick(log) 16 | console.log('\n') 17 | log.bold('========= prettyformat ========').echo() 18 | log.prettyformat(obj).echo() 19 | 20 | console.log('\n') 21 | log.bold('========= fmtobj ========').echo() 22 | const l = log.fmtobj(obj).echo() 23 | // log.quick(l.entries()) 24 | 25 | console.log('\n') 26 | log.bold('========= inspector ========').echo() 27 | 28 | log.factory().verbose(100).data(obj).echo() 29 | console.log('\n') 30 | 31 | log.bold('========= prettyobj ========').echo() 32 | 33 | log.factory().verbose(100).prettyobj(obj).echo() 34 | console.log('\n') 35 | 36 | log.bold('========= preset(desc) ========').echo() 37 | 38 | log.preset('desc').data(obj).echo() 39 | console.log('\n') 40 | 41 | // log.data(log.cleaner()).exit() 42 | console.log('\n') 43 | log.bold('========= cleaned obj ========').echo() 44 | 45 | // @TODO: put on its own file 46 | // @NOTE: this mutates! 47 | // CHAIN BACK UP TO LOG 48 | const cleaner = log 49 | .cleaner(true) 50 | .keys([/array|circularReference|map|property/]) 51 | .data(obj) 52 | .clean() 53 | .echo() 54 | 55 | // console.log('\n\n') 56 | log.bold('========= prettyjson ========').echo() 57 | 58 | // CAN'T REALLY stringify this to json 59 | const cheat = { 60 | 'property': {}, 61 | 'map': {prop: 'value'}, 62 | 'Symbol(\'foo\')': 'foo', 63 | 'array': [1, NaN, Infinity], 64 | 'foo': 'foo', 65 | } 66 | // cheat.circularReference = cheat 67 | 68 | console.log(log.prettyjson(cheat)) 69 | // log.json(JSON.stringify(cheat)).echo() 70 | // log.json(log.jsStringify(obj)).echo() 71 | console.log('\n') 72 | 73 | log.bold('========= tosource ========').echo() 74 | log.tosource().data(cheat).echo() 75 | // log.formatter(cleaner.clean).data(obj).echo() 76 | -------------------------------------------------------------------------------- /test/progress.js: -------------------------------------------------------------------------------- 1 | const log = require('../') 2 | 3 | log.progress() 4 | // log.progress(20, (bar, interval) => { 5 | // bar.tick() 6 | // if (bar.complete) clearInterval(interval) 7 | // }, 1000) 8 | // log.boxen().echo() 9 | 10 | let contentLength = 128 * 1024 11 | const bar = log.progress(' downloading [:bar] :percent :etas', { 12 | complete: '=', 13 | incomplete: ' ', 14 | width: 20, 15 | total: contentLength, 16 | }).progressBar 17 | 18 | function next() { 19 | if (!contentLength) return 20 | bar.tick(Math.random() * 10 * 1024) 21 | if (!bar.complete) setTimeout(next, Math.random() * 1000) 22 | } 23 | next() 24 | -------------------------------------------------------------------------------- /test/quick.js: -------------------------------------------------------------------------------- 1 | const log = require('../') 2 | 3 | log.emoji('phone').bold('eh').data({byefelicia: true}).echo() 4 | log.quick({experiment: true}) 5 | -------------------------------------------------------------------------------- /test/slow.js: -------------------------------------------------------------------------------- 1 | const log = require('../') 2 | log.slow(1000) 3 | log.emoji('snail').yellow('slow...').echo() 4 | const start = Date.now() 5 | log.emoji('snail').yellow('...slow').echo() 6 | const end = Date.now() - start 7 | console.assert(end >= 1000 && end <= 1010, 'timing was 1s') 8 | console.log('timing was 1s', end) 9 | -------------------------------------------------------------------------------- /test/spinner.js: -------------------------------------------------------------------------------- 1 | const log = require('../') 2 | 3 | // instance available on log.Spinner 4 | log.color('bold').spinner('spinner 1 msg') 5 | 6 | setTimeout(() => log.stopSpinner(), 5000) 7 | -------------------------------------------------------------------------------- /test/spinners-multi.js: -------------------------------------------------------------------------------- 1 | // modules 2 | const Multispinner = require('multispinner') 3 | 4 | // constants 5 | const spinners = ['task A', 'task B', 'task C'] 6 | const opts = { 7 | 'interval': 120, 8 | 'preText': 'Completing', 9 | // 'frames': [ 10 | // '[ ]', 11 | // '[* ]', 12 | // '[** ]', 13 | // '[ ** ]', 14 | // '[ ** ]', 15 | // '[ ** ]', 16 | // '[ **]', 17 | // '[ *]' 18 | // ], 19 | 'frames': [ 20 | '[ ]', 21 | '[. ]', 22 | '[.. ]', 23 | '[ ..]', 24 | '[ .]', 25 | '[ ]', 26 | '[= ]', 27 | '[== ]', 28 | '[ ==]', 29 | '[ =]', 30 | '[ ]', 31 | '[- ]', 32 | '[-- ]', 33 | '[ --]', 34 | '[ -]', 35 | '[ ]', 36 | '[~ ]', 37 | '[~~ ]', 38 | '[ ~~]', 39 | '[ ~]', 40 | '[ ]', 41 | '[* ]', 42 | '[** ]', 43 | '[ **]', 44 | '[ *]', 45 | ], 46 | } 47 | 48 | // initialize 49 | const m = new Multispinner(spinners, opts) 50 | 51 | // staggered completion 52 | const t = 1500 53 | let i = 0 54 | function loop() { 55 | setTimeout(() => { 56 | m.success(spinners[i]) 57 | i++ 58 | if (i < spinners.length) loop() 59 | }, t) 60 | } 61 | loop() 62 | -------------------------------------------------------------------------------- /test/spinners-ora.js: -------------------------------------------------------------------------------- 1 | const log = require('../') 2 | 3 | log.color('bold').ora('spinner 1 msg').start() 4 | 5 | setTimeout(() => log.Spinner.succeed(), 2000) 6 | // setTimeout(() => log.stopSpinner(), 2000) 7 | -------------------------------------------------------------------------------- /test/spinners.js: -------------------------------------------------------------------------------- 1 | const log = require('../') 2 | 3 | log 4 | .addSpinner('key1', 'spinner 1 msg') 5 | 6 | log.addSpinner('key2', 'spinner 2 msg') 7 | 8 | log.addSpinner('key3', 'spinner 3 msg') 9 | 10 | log.text('meh').echo() 11 | 12 | // log.quick(log.spinnerOpts, log.spinners) 13 | 14 | // arg is optionally a string for frames 15 | // or an object for multi-spinner options 16 | log.startSpinners() 17 | 18 | // string arg removes by name 19 | setTimeout(() => log.removeSpinner('key1'), 1000) 20 | 21 | // empty args removes all 22 | setTimeout(() => log.removeSpinner(), 20000) 23 | -------------------------------------------------------------------------------- /test/split.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fliphub/fliplog/b0a1581e749a41ab65731f88cc90f2c24d20247d/test/split.js -------------------------------------------------------------------------------- /test/strip.js: -------------------------------------------------------------------------------- 1 | const fliplog = require('../') 2 | 3 | const _log = (data, word) => { 4 | const stripAnsi = fliplog.requirePkg('strip-ansi') 5 | const {text, datas} = fliplog.text(word).prettyformat(data).returnVals() 6 | if (text) console.log(text) 7 | console.log(stripAnsi(datas)) 8 | } 9 | 10 | // _log({user: true}) 11 | 12 | 13 | fliplog.strip().bold('uncolor me').echo() 14 | fliplog.strip(fliplog.chalk().yellow('uncolor-me-too')).echo() 15 | -------------------------------------------------------------------------------- /test/test.js: -------------------------------------------------------------------------------- 1 | const log = require('../') 2 | 3 | // log.capture() 4 | // console.log('eh out') 5 | // log.stopCapturing() 6 | // console.assert(log.savedLog.length > 0, 'has saved logs') 7 | // process.exit() 8 | 9 | // log.filter('!args,!alien,has') 10 | // log.filter(['ehoh,!args,!alien,has']) 11 | 12 | // @NOTE: to avoid overhead of cloning, 13 | // these do have ref to each other so assertions needed to be earlier 14 | function testLog(_log) { 15 | const arg1 = _log 16 | .tags('args') 17 | .text('args') 18 | .return() 19 | .silent 20 | 21 | console.log({arg1}) 22 | const ehoh = _log 23 | .tags('ehoh') 24 | .text('ehoh') 25 | .return() 26 | .silent 27 | console.log({ehoh}) 28 | 29 | const args2 = _log 30 | .tags('args') 31 | .text('args') 32 | .return() 33 | .silent 34 | console.log({args2}) 35 | const has = _log 36 | .tags('has') 37 | .text('has') 38 | .return() 39 | .silent 40 | console.log(has) 41 | const alien = _log 42 | .tags('alien') 43 | .text('alien') 44 | .return() 45 | .silent 46 | console.log(alien) 47 | 48 | console.assert(arg1 === true, 'filtered is ignored') 49 | console.assert(ehoh !== true, 'non filtered is output') 50 | console.assert(has !== true, 'non filtered is output') 51 | console.assert(args2 === true, 'filtered is ignored after logging a non-filtered') 52 | console.assert(alien === true, 'a second filtered is ignored') 53 | console.log('all pass :-)') 54 | } 55 | 56 | const log1 = log.factory() 57 | const log2 = log.factory() 58 | log1.filter('!args,!alien,has') 59 | log2.filter(['!args', 'has', '!alien', 'ehoh']) 60 | 61 | testLog(log1) 62 | testLog(log2) 63 | -------------------------------------------------------------------------------- /test/time.js: -------------------------------------------------------------------------------- 1 | const log = require('../') 2 | 3 | log.time(true).bold('========= prettyformat ========').echo() 4 | 5 | log.time(true).text('eh').echo() 6 | // .text('wut') 7 | // .echo() 8 | -------------------------------------------------------------------------------- /test/treeify.js: -------------------------------------------------------------------------------- 1 | var log = require('../') 2 | 3 | console.log('\n\n\n\n') 4 | 5 | log 6 | .color('green') 7 | .text('🌲 treeify') 8 | .tree({ 9 | oranges: { 10 | mandarin: { 11 | clementine: null, 12 | tangerine: 'so cheap and juicy!', 13 | }, 14 | }, 15 | apples: { 16 | 'gala': null, 17 | 'pink lady': null, 18 | }, 19 | }) 20 | .echo() 21 | 22 | console.log('\n\n\n') 23 | -------------------------------------------------------------------------------- /test/treeify2.js: -------------------------------------------------------------------------------- 1 | var log = require('../') 2 | 3 | // Based on information taken from the Tree of Life web project 4 | // http://tolweb.org/Eukaryotes/3 5 | var Eukaryotes = { 6 | 'Archaeplastida (Plantae)': { 7 | 'Green plants': 'green algae & land plants', 8 | 'Rhodophyta': 'red algae', 9 | 'Glaucophytes': 'microalgae', 10 | }, 11 | 'Unikonts': { 12 | Opisthokonts: { 13 | Animals: null, 14 | Choanoflagellates: null, 15 | Filasterea: null, 16 | Ichthyosporea: null, 17 | Fungi: 'mushrooms, sac fungi, yeast, molds, etc', 18 | Nucleariidae: 'filose amoebae', 19 | }, 20 | Amoebozoa: 'amoebae, slime molds, and parasitic protists', 21 | }, 22 | 'Chromalveolates': { 23 | '': { 24 | Rhizaria: { 25 | Cercozoa: 'amoeboflagellates', 26 | Foraminifera: 'complex cells with reticulopodia', 27 | Radiolaria: null, 28 | }, 29 | Alveolates: 'dinoflagellates, ciliates and apicomplexan parasites', 30 | Stramenopiles: 'e.g. water molds, diatoms, brown algae', 31 | }, 32 | 'Hacrobia': 'Haptophyta, Cryptomonads, etc.', 33 | }, 34 | 'Excavates': { 35 | Malawimonads: null, 36 | Discicristates: { 37 | Euglenozoa: 'euglenids, diplonemids and kinetoplastids', 38 | Heterolobosea: 'amoeboflagellates with discoidal mitchondrial cristae', 39 | Jakobida: 'free-living, heterotrophic flagellates', 40 | }, 41 | Parabasalids: 'trichomonads and hypermastigotes', 42 | Fornicata: 'diplomonads and retortamonads', 43 | Preaxostyla: 'oxymonads and Trimastix', 44 | }, 45 | } 46 | 47 | // console.log('Eukaryotes') 48 | 49 | // log 50 | // .tree(Eukaryotes, line => { 51 | // console.log(line) 52 | // }) 53 | // .echo() 54 | 55 | log.color('bold').text('eh').tree(Eukaryotes).echo() 56 | -------------------------------------------------------------------------------- /test/write.js: -------------------------------------------------------------------------------- 1 | const log = require('../') 2 | 3 | // log 4 | // .ansi() 5 | // .buffer() 6 | // .bold() 7 | // .italic() 8 | // .write('eh') 9 | // .reset() 10 | // .red() 11 | // .write(' red') 12 | // .reset() 13 | // .write('\n') 14 | // .flush() 15 | 16 | const name = 'default' 17 | const files = `(0 files, 53 Bytes)` 18 | const size = `2.9 kB` 19 | const list = [`main.js`, `main.scss`] 20 | 21 | log 22 | .ansi(true) 23 | .write(`└──`) 24 | .green(name) 25 | .yellow(`${size} files`) 26 | .green(`${files}`) 27 | .echo() 28 | 29 | log 30 | .ansi(true) 31 | .write(`└──`) 32 | .red(name) 33 | .bold(`${size} files`) 34 | .write(`${files}`) 35 | .echo() 36 | 37 | // log.bold('reset').fmtobj({reset: true}).echo() 38 | -------------------------------------------------------------------------------- /todo/Progress.js: -------------------------------------------------------------------------------- 1 | const ProgressBar = require('progress') 2 | const padEnd = require('lodash.padend') 3 | 4 | // https://github.com/lerna/lerna/blob/master/src/progressBar.js 5 | module.exports = class ProgressBarController { 6 | constructor() { 7 | this.bar = null 8 | } 9 | 10 | init(total) { 11 | if (this.bar) { 12 | this.terminate() 13 | } 14 | 15 | // Intentionally a noop because node-progress doesn't work well in non-TTY 16 | // environments 17 | if (!process.stdout.isTTY) { 18 | return 19 | } 20 | 21 | // Don't do any of this while testing 22 | // if (process.env.NODE_ENV === 'lerna-test') { 23 | // return 24 | // } 25 | 26 | this.bar = new ProgressBar(':name ╢:bar╟', { 27 | total, 28 | complete: '█', 29 | incomplete: '░', 30 | clear: true, 31 | 32 | // terminal columns - package name length - additional characters length 33 | width: (process.stdout.columns || 100) - 50 - 3, 34 | }) 35 | } 36 | 37 | tick(name) { 38 | if (this.bar) { 39 | this.bar.tick({ 40 | name: padEnd(name.slice(0, 50), 50), 41 | }) 42 | } 43 | } 44 | 45 | clear() { 46 | if (this.bar) { 47 | this.bar.terminate() 48 | } 49 | } 50 | 51 | restore() { 52 | if (this.bar) { 53 | // This is a hack to get the bar to redraw it's last state. 54 | // See: https://github.com/tj/node-progress/blob/d47913502ba5b551fcaad9e94fe7b2f5876a7939/lib/node-progress.js#L154-L159 55 | this.bar.stream.write(this.bar.lastDraw) 56 | } 57 | } 58 | 59 | terminate() { 60 | this.clear() 61 | this.bar = null 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /todo/TODO.md: -------------------------------------------------------------------------------- 1 | 2 | https://www.ibm.com/blogs/bluemix/2015/03/node-js-better-logging/ 3 | # lightweight 4 | add lightweight mode (flipshake) 5 | 6 | dont list dependencies, 7 | install, 8 | read pkg json for config, 9 | then depflip, 10 | use babel style presets + plugins 11 | - if config is used, settings change, instead of failing, have safety 12 | try to require, if false, don't pass through the middleware/preset/plugin 13 | 14 | ```js 15 | "fliplog": { 16 | "todo": "", 17 | "presets": [ 18 | "light/production", 19 | "fun", 20 | "debugging", 21 | "latest" 22 | ], 23 | "use": [ 24 | "verbose", 25 | "color", 26 | "xterm", 27 | "chalk", 28 | 29 | "timer", 30 | "spinner", "ora", 31 | "multi-spinner", 32 | "box", 33 | "sparkly", 34 | "beep", 35 | "highlight", 36 | "!for-blacklist-instead-of-white", 37 | "table", "diff", 38 | "track", "trace", 39 | "json", "stringify", 40 | "sleep", "tosource", 41 | 42 | "register", "file", 43 | "story" 44 | ] 45 | }, 46 | ``` 47 | 48 | 49 | ----- 50 | 51 | // @TODO: 52 | // - [x] add debugFor filters here 53 | // - [ ] more formatting 54 | // - [ ] easy table 55 | // - [x] json 56 | // - [ ] storyline 57 | // - [ ] docs 58 | // - [x] emoji by name - checkout existing ones 59 | // - [ ] integrate an existing validator 60 | // - [x] https://www.npmjs.com/package/boxen 61 | // - [ ] https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md 62 | 63 | 64 | 65 | 66 | 67 | ----- 68 | 69 | 70 | 71 | 72 | - filter using .when with .whenFlag etc 73 | - add cli interface to do logs from flags 74 | - .level .setLevel for doing logs and filtering 75 | - should create reference-and-dereference and attach fliplog to obj property 76 | - `log.silent(this.get('debug'))` 77 | 78 | 79 | 80 | https://github.com/TooTallNate/ansi.js 81 | 82 | https://github.com/chjj/blessed 83 | https://github.com/sindresorhus/pkg-dir 84 | https://github.com/sindresorhus/filenamify 85 | https://github.com/yeoman/update-notifier 86 | https://github.com/mikaelbr/node-notifier 87 | https://github.com/jstrace/chart 88 | https://github.com/sindresorhus/sparkly 89 | https://github.com/visionmedia/node-progress 90 | https://github.com/SamVerschueren/listr 91 | https://www.npmjs.com/package/eazy-logger 92 | 93 | 94 | https://www.npmjs.com/package/tfunk 95 | https://www.npmjs.com/package/easy-table 96 | https://www.npmjs.com/package/cli-highlight 97 | https://github.com/AljoschaMeyer/vorpal-log 98 | https://github.com/vorpaljs/awesome-vorpal 99 | https://github.com/dthree/cash 100 | https://github.com/sindresorhus/boxen 101 | 102 | https://www.npmjs.com/package/beeper 103 | 104 | 105 | 106 | http://docs.graylog.org/en/2.2/pages/gelf.html 107 | 108 | psr-3, file formatting 109 | -------------------------------------------------------------------------------- /todo/deps-dynamic/cache.json: -------------------------------------------------------------------------------- 1 | {"time":1494402070552,"deps":["boxen","node-notifier","progress","cli-table2","multispinner","ora","sleepfor","fliptime","babar","prettyjson","javascript-stringify","cli-highlight","cli-color","sparkly","lodash.clonedeep","cli-table2","tosource","deep-diff","beeper","listr"]} -------------------------------------------------------------------------------- /todo/deps-dynamic/dynamicTags.js: -------------------------------------------------------------------------------- 1 | // @NOTE this file is not included in npm files 2 | const {execSync} = require('child_process') 3 | const {resolve} = require('path') 4 | const {writeFileSync} = require('fs') // readFileSync, existsSync 5 | let pkg = require('./package.json') 6 | 7 | const pkgPath = resolve(__dirname, './package.json') 8 | const ogPkg = JSON.stringify(pkg, null, 2) 9 | const ogPkgObj = JSON.parse(ogPkg) 10 | 11 | /** 12 | * @param {string} tag 13 | * @return {void} 14 | */ 15 | function dynamicTag(tag) { 16 | try { 17 | execSync(`echo "module.exports = '${tag}'" > ./tagged.js`, { 18 | stdio: 'inherit', 19 | }) 20 | pkg.version = ogPkgObj.version 21 | 22 | // @NOTE: ignoring this for now, 23 | // @example 0.2.0-beta.1 24 | // 25 | // so it would become 26 | // 0.2.0-beta.1-cli 27 | // 28 | // if (pkg.version.includes('-')) { 29 | // pkg.version = pkg.version.split('-').shift() 30 | // } 31 | 32 | // add tag to version 33 | pkg.version += '-' + tag 34 | 35 | // save pkg 36 | writeFileSync(pkgPath, JSON.stringify(pkg, null, 2), 'utf8') 37 | 38 | console.log({tag, version: pkg.version}) 39 | console.log(`npm publish --tag ${tag}`) 40 | 41 | // publish with tag 42 | execSync(`npm publish --tag ${tag}`, {stdio: 'inherit'}) 43 | } 44 | catch (e) { 45 | // restore original 46 | writeFileSync(pkgPath, ogPkg, 'utf8') 47 | } 48 | } 49 | 50 | function last() { 51 | console.log('restoring') 52 | 53 | // restore original 54 | writeFileSync(pkgPath, ogPkg, 'utf8') 55 | 56 | // empty the dynamicTag 57 | execSync(`echo "module.exports = false" > ./tagged.js`, {stdio: 'inherit'}) 58 | } 59 | 60 | ['fun', 'formatting', 'debugging', 'cli'].forEach(tag => dynamicTag(tag)) 61 | last() 62 | -------------------------------------------------------------------------------- /todo/deps-dynamic/getDep.js: -------------------------------------------------------------------------------- 1 | module.exports = function getDep(name) { 2 | try { 3 | require.resolve(name) 4 | return require(name) // eslint-disable-line 5 | } 6 | catch (e) { 7 | return false 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /todo/deps-dynamic/index.js: -------------------------------------------------------------------------------- 1 | const plugins = configs.exportee 2 | const shh = { 3 | shushed: false, 4 | } 5 | let shushed = {} 6 | let required = [] 7 | 8 | const log = new LogChain().new() 9 | 10 | const dd = new DynamicDeps(pkgDebug) 11 | for (let u = 0; u < plugins.length; u++) { 12 | if (pkgDebug === true) { 13 | console.log('using plugin', plugins[u]) 14 | } 15 | 16 | dd.use(plugins[u]) 17 | log.use(plugins[u]) 18 | } 19 | 20 | dd.installIfNeeded().clean() 21 | 22 | if (pkgDebug === true) { 23 | console.log('fliplog setup') 24 | } 25 | 26 | log.reset() 27 | log.pkg = configs.pkg 28 | -------------------------------------------------------------------------------- /todo/deps-dynamic/tagged.js: -------------------------------------------------------------------------------- 1 | module.exports = false 2 | -------------------------------------------------------------------------------- /todo/types.ts: -------------------------------------------------------------------------------- 1 | export type ReturnVals = { 2 | text: string, 3 | datas: any, 4 | } 5 | --------------------------------------------------------------------------------