├── .gitignore ├── .prettierrc ├── lib └── config.js ├── package.json ├── README.md └── bin └── main.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | package-lock.json 3 | yarn.lock 4 | .DS_Store 5 | .idea/ -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "trailingComma": "all", 4 | "printWidth": 100, 5 | "proseWrap": "never", 6 | "overrides": [ 7 | { 8 | "files": ".prettierrc", 9 | "options": { 10 | "parser": "json" 11 | } 12 | } 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /lib/config.js: -------------------------------------------------------------------------------- 1 | const homedir = process.env.HOME || require('os').homedir(); 2 | const chalk = require('chalk'); 3 | const path = require('path'); 4 | const fs = require('fs'); 5 | const configPath = path.resolve(homedir, '.flomorc'); 6 | 7 | const config = { 8 | async load(path = configPath) { 9 | const conf = {}; 10 | if (fs.existsSync(path) && fs.statSync(path).isFile()) { 11 | const content = fs.readFileSync(path, 'utf-8'); 12 | try { 13 | return JSON.parse(content.toString()); 14 | } catch (e) { 15 | return conf; 16 | } 17 | } else { 18 | return conf; 19 | } 20 | }, 21 | async write(options = {}, path = configPath) { 22 | const originOptions = await config.load(path); 23 | const mergedOptions = { ...originOptions, ...options }; 24 | const content = JSON.stringify(mergedOptions); 25 | try { 26 | fs.writeFileSync(path, content); 27 | console.log(chalk.green('Saved!')); 28 | return; 29 | } catch (error) { 30 | console.log(chalk.red('Failed!')); 31 | } 32 | return fs.writeFileSync(path, content); 33 | }, 34 | }; 35 | 36 | module.exports = config; 37 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "flomo-cli", 3 | "version": "0.1.2", 4 | "description": "A command line tool for the flomo app", 5 | "main": "index.js", 6 | "bin": { 7 | "flomo": "bin/main.js", 8 | "fm": "bin/main.js" 9 | }, 10 | "scripts": { 11 | "format": "prettier --write '**/*.{json,js,md,yml}'", 12 | "pretty-quick": "pretty-quick", 13 | "prepublishOnly": "np --no-cleanup --no-publish" 14 | }, 15 | "repository": { 16 | "type": "git", 17 | "url": "https://github.com/Mayandev/flomo-cli" 18 | }, 19 | "keywords": [ 20 | "flomo", 21 | "note", 22 | "cli" 23 | ], 24 | "author": "phillzou ", 25 | "license": "ISC", 26 | "bugs": { 27 | "url": "https://github.com/Mayandev/flomo-cli/issues" 28 | }, 29 | "homepage": "https://github.com/Mayandev/flomo-cli#readme", 30 | "dependencies": { 31 | "axios": "^0.21.1", 32 | "chalk": "^4.1.0", 33 | "command-exists": "^1.2.9", 34 | "commander": "^6.2.1", 35 | "execa": "^5.0.0", 36 | "inquirer": "^7.3.3", 37 | "lodash": "^4.17.20", 38 | "minimist": "^1.2.5", 39 | "ora": "^5.2.0" 40 | }, 41 | "devDependencies": { 42 | "eslint": "^7.17.0", 43 | "husky": "^4.3.7", 44 | "np": "^7.0.0", 45 | "prettier": "^2.2.1", 46 | "pretty-quick": "^3.1.0" 47 | }, 48 | "husky": { 49 | "hooks": { 50 | "pre-commit": "pretty-quick --staged" 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | flomo-cli 4 | 5 | # flomo-cli 6 | 7 | 为 [flomo 灵感笔记](https://flomoapp.com/)提供的命令行工具 8 | 9 |
10 | 11 | ## Install 12 | 13 | ```bash 14 | $ npm install flomo-cli -g 15 | # or yarn 16 | $ yarn global add flomo-cli 17 | ``` 18 | 19 | ## Usage 20 | 21 | ![flomo](https://mayandev.oss-cn-hangzhou.aliyuncs.com/uPic/flomo.png) 22 | 23 | 24 | ### Config 25 | 26 | 请先使用下面的命令进行配置 api。如果你在 flomo 的设置里更换了 api,也可以使用 `flomo config` 命令,重新设置 api 链接。 27 | 28 | [在哪里查看 api?](https://flomoapp.com/iwh/MjY3NDM/19a24a215dc051f29d8f8d9328a9b329/) 29 | 30 | ```bash 31 | $ flomo config 32 | ``` 33 | 34 | ### Normal 35 | 36 | ```bash 37 | $ flomo '#tag This is a flow momery from flomo-cli with hash tag.' 38 | # fm is also ok 39 | $ fm '#tag This is a flow momery from flomo-cli with hash tag.' 40 | ``` 41 | 42 | 普通模式下,默认将命令后的字符串内容上传到 flomo 到服务器。 43 | 44 | ### Editor 45 | 46 | ```bash 47 | $ flomo edit 48 | ``` 49 | 50 | 工具提供编辑器模式,输入 `flomo edit` 启动。 51 | 52 | [如何多行编辑?](https://github.com/Mayandev/flomo-cli/issues/1#issuecomment-781298951) 53 | 54 | ![github-flomo-cli-gif](https://mayandev.oss-cn-hangzhou.aliyuncs.com/uPic/github-flomo-cli-gif.gif) 55 | 56 | 57 | 58 | ![image-20210118105159846](https://mayandev.oss-cn-hangzhou.aliyuncs.com/uPic/image-20210118105159846.png) 59 | 60 | 61 | ## Reference 62 | 63 | 本工具由 [cli-template](https://github.com/Mayandev/cli-template) 提供支持。 64 | -------------------------------------------------------------------------------- /bin/main.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | const request = require('axios'); 3 | const chalk = require('chalk'); 4 | const config = require('../lib/config'); 5 | const inquirer = require('inquirer'); 6 | const minimist = require('minimist'); 7 | const ora = require('ora'); 8 | const program = require('commander'); 9 | const pkg = require('../package.json'); 10 | const _ = require('lodash'); 11 | 12 | const URL_REG = /[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)?/gi; 13 | 14 | program.version(pkg.version).action(() => { 15 | const content = program.args.join(' '); 16 | saveFlomo(content); 17 | }); 18 | 19 | program.on('--help', () => { 20 | console.log(''); 21 | console.log(chalk.green('Examples: ')); 22 | console.log(chalk.cyan(" $ flomo 'This is a flow momery from flomo-cli.'")); 23 | console.log( 24 | chalk.cyan(" $ flomo '#tag1 #tag2 This is a flow momery from flomo-cli with hash tag.'"), 25 | ); 26 | }); 27 | 28 | program 29 | .command('config') 30 | .description('Set the api config') 31 | .option('--api', 'Change flomo api link') 32 | .action((args) => { 33 | // input is 'flomo config' 34 | if (process.argv.length === 3) { 35 | return setConfig(); 36 | } 37 | // input is flomo config --api 'https://api...' 38 | const { api: apiURL } = minimist(process.argv.slice(2)); 39 | config.write({ apiURL }); 40 | }); 41 | 42 | program 43 | .command('edit') 44 | .description('Edit flomo content in vim editor') 45 | .action(async () => { 46 | const { content } = await inquirer.prompt([ 47 | { 48 | type: 'editor', 49 | message: 'Input flomo content:', 50 | name: 'content', 51 | }, 52 | ]); 53 | saveFlomo(content); 54 | }); 55 | 56 | program.parse(process.argv); 57 | 58 | // without param 59 | if (!process.argv.slice(2).length) { 60 | checkConfig(); 61 | } 62 | 63 | async function checkConfig() { 64 | const savedConfig = await config.load(); 65 | if (!_.isEmpty(savedConfig)) { 66 | program.help(); 67 | } 68 | setConfig(); 69 | } 70 | 71 | async function setConfig() { 72 | // inquire for a api link 73 | const { apiURL } = await inquirer.prompt([ 74 | { 75 | type: 'input', 76 | message: 'Config flomo api link: ', 77 | name: 'apiURL', 78 | validate: (ans) => { 79 | if (!ans.match(URL_REG)) { 80 | return 'Please input a valid flomo api link(See: https://flomoapp.com/mine?source=incoming_webhook)'; 81 | } 82 | return true; 83 | }, 84 | }, 85 | ]); 86 | config.write({ apiURL }); 87 | } 88 | 89 | async function saveFlomo(content) { 90 | if (_.isEmpty(content)) { 91 | return; 92 | } 93 | const savedConfig = await config.load(); 94 | const apiURL = _.get(savedConfig, 'apiURL', ''); 95 | if (!apiURL.match(URL_REG)) { 96 | console.log(chalk.red('Invalid URL, Please check you config.')); 97 | return; 98 | } 99 | const spinner = ora('Uploading flomo...').start(); 100 | // request post flomo 101 | try { 102 | await request.post(apiURL, { 103 | content, 104 | }); 105 | spinner.succeed('Flomo saved!'); 106 | } catch (e) { 107 | spinner.fail('Failed! Maybe you have reached the 100 limit'); 108 | console.log(e); 109 | } 110 | } 111 | --------------------------------------------------------------------------------