├── .editorconfig
├── .github
├── FUNDING.yml
└── workflows
│ └── ci.yml
├── .gitignore
├── README.md
├── index.d.ts
├── lib
├── cursor.js
├── index.js
└── utilities.js
├── package-lock.json
├── package.json
├── renovate.json
└── test
└── test.js
/.editorconfig:
--------------------------------------------------------------------------------
1 | # http://editorconfig.org
2 | root = true
3 |
4 | [*]
5 | indent_style = space
6 | indent_size = 2
7 | end_of_line = lf
8 | charset = utf-8
9 | trim_trailing_whitespace = true
10 | insert_final_newline = true
11 |
12 | [*.md]
13 | trim_trailing_whitespace = false
14 |
15 | [*.less]
16 | indent_style = space
17 | indent_size = 2
18 |
19 | [Makefile]
20 | indent_style = tab
21 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | # github: [jaywcjlove]
4 | # patreon: # Replace with a single Patreon username
5 | # open_collective: # Replace with a single Open Collective username
6 | # ko_fi: # Replace with a single Ko-fi username
7 | # tidelift: npm/xxx
8 | # community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
9 | custom: https://jaywcjlove.github.io/#/sponsor
10 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: Build
2 | on:
3 | push:
4 | branches:
5 | - master
6 |
7 | jobs:
8 | website:
9 | runs-on: ubuntu-latest
10 | permissions:
11 | contents: write
12 | id-token: write
13 | steps:
14 | - uses: actions/checkout@v3
15 | - uses: actions/setup-node@v3
16 | with:
17 | node-version: 18
18 | registry-url: 'https://registry.npmjs.org'
19 |
20 | # - run: mkdir -p build
21 | # - run: npm i markdown-to-html-cli -g
22 | # - run: markdown-to-html --output build/index.html
23 |
24 | - name: Create idoc config.
25 | run: |
26 | cat > idoc.yml << EOF
27 | site: "Image To URI {{version}}"
28 | menus:
29 | Home: index.html
30 | Sponsor: https://jaywcjlove.github.io/#/sponsor
31 | EOF
32 |
33 | - run: npm install idoc@1.27.2 -g
34 | - run: idoc --output="build"
35 |
36 | - name: Generate Contributors Images
37 | uses: jaywcjlove/github-action-contributors@main
38 | with:
39 | filter-author: (renovate\[bot\]|renovate-bot|dependabot\[bot\])
40 | output: build/CONTRIBUTORS.svg
41 | avatarSize: 42
42 |
43 | - name: Create Tag
44 | id: create_tag
45 | uses: jaywcjlove/create-tag-action@main
46 |
47 | - name: get tag version
48 | id: tag_version
49 | uses: jaywcjlove/changelog-generator@main
50 |
51 | - name: Deploy
52 | uses: peaceiris/actions-gh-pages@v3
53 | with:
54 | github_token: ${{ secrets.GITHUB_TOKEN }}
55 | publish_dir: ./build
56 |
57 | - name: Generate Changelog
58 | id: changelog
59 | uses: jaywcjlove/changelog-generator@main
60 | with:
61 | head-ref: ${{steps.create_tag.outputs.version}}
62 | filter-author: (renovate-bot|Renovate Bot)
63 | filter: '[R|r]elease[d]\s+[v|V]\d(\.\d+){0,2}'
64 |
65 | - name: Create Release
66 | uses: jaywcjlove/create-tag-action@main
67 | with:
68 | package-path: ./package.json
69 | release: true
70 | body: |
71 | [](https://jaywcjlove.github.io/#/sponsor) [](https://uiwjs.github.io/npm-unpkg/#/pkg/loading-cli@${{steps.changelog.outputs.version}}/file/README.md)
72 |
73 | Documentation ${{ steps.changelog.outputs.tag }}: https://raw.githack.com/uiwjs/react-md-editor/${{ steps.changelog.outputs.gh-pages-short-hash }}/index.html
74 | Comparing Changes: ${{ steps.changelog.outputs.compareurl }}
75 |
76 | ```bash
77 | npm i loading-cli@${{steps.changelog.outputs.version}}
78 | ```
79 |
80 | ${{ steps.changelog.outputs.changelog }}
81 |
82 | - run: npm publish --access public --provenance
83 | name: 📦 loading-cli publish to NPM
84 | continue-on-error: true
85 | env:
86 | NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}
87 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # loading-cli
2 |
3 | [](https://jaywcjlove.github.io/#/sponsor)
4 | [](https://www.npmjs.com/package/loading-cli)
5 | [](https://github.com/jaywcjlove/loading-cli/actions/workflows/ci.yml)
6 |
7 | Terminal loading effect.
8 |
9 |
10 |
11 | # Install
12 |
13 | ```bash
14 | $ npm install --save loading-cli
15 | ```
16 |
17 | # Usage
18 |
19 | ```js
20 | const loading = require('loading-cli');
21 | const load = loading("loading text!!").start()
22 |
23 | setTimeout(function(){
24 | load.color = 'yellow';
25 | load.text = ' Loading rainbows';
26 | },2000)
27 |
28 | // stop
29 | setTimeout(function(){
30 | load.stop()
31 | },3000)
32 | ```
33 |
34 | Custom text color [colors-cli](https://github.com/jaywcjlove/colors-cli)
35 |
36 | ```js
37 | const color = require('colors-cli/toxic');
38 | const loading = require('loading-cli');
39 |
40 | const load = loading("loading text!!".blue).start();
41 | // stop
42 | setTimeout(function(){
43 | load.stop()
44 | },3000)
45 | ```
46 |
47 | # API
48 |
49 | ## loading([options|text])
50 |
51 | ### options
52 |
53 | ```js
54 | load({
55 | "text":"loading text!!",
56 | "color":"yellow",
57 | "interval":100,
58 | "stream": process.stdout,
59 | "frames":["◰", "◳", "◲", "◱"]
60 | })
61 | ```
62 |
63 | ### text
64 |
65 | Type: string
66 | Text to display after the spinner.
67 |
68 | ```js
69 | loading("loading text!!")
70 | ```
71 |
72 | ## color
73 |
74 | Values:`black` `red` `green` `yellow` `blue` `magenta` `cyan` `white` `gray`
75 |
76 |
77 | ## frames
78 |
79 | ```bash
80 | ["◰", "◳", "◲", "◱"]
81 | ["◐", "◓", "◑", "◒"]
82 | [".", "o", "O", "°", "O", "o", "."]
83 | ["⊶", "⊷"]
84 | ["ဝ", "၀"]
85 | ["←", "↖", "↑", "↗", "→", "↘", "↓", "↙"]
86 | ["🕐 ", "🕑 ", "🕒 ", "🕓 ", "🕔 ", "🕕 ", "🕖 ", "🕗 ", "🕘 ", "🕙 ", "🕚 "]
87 | ```
88 |
89 | # Instance
90 |
91 | ## .start([text])
92 |
93 | Start the spinner. Returns the instance.
94 |
95 | ## .stop()
96 |
97 | Stop and clear the spinner. Returns the instance.
98 |
99 | ## .clear()
100 |
101 | Clear the spinner. Returns the instance.
102 |
103 | ## .succeed([text])
104 |
105 | Stop the spinner, change it to a green `✔` and persist the current text, or text if provided. Returns the instance. See the GIF below.
106 |
107 | ## .fail([text])
108 |
109 | Stop the spinner, change it to a red `✖` and persist the current text, or text if provided. Returns the instance. See the GIF below.
110 |
111 | ## .warn([text])
112 |
113 | Stop the spinner, change it to a yellow `⚠` and persist the current text, or text if provided. Returns the instance.
114 |
115 | ## .info([text])
116 |
117 | Stop the spinner, change it to a blue `ℹ` and persist the current text, or text if provided. Returns the instance.
118 |
119 | ## .render()
120 |
121 | Manually render a new frame. Returns the instance.
122 |
123 | ## .frame()
124 |
125 | Get a new frame.
126 |
127 | ```js
128 | const loading = require('loading-cli');
129 | const load = loading("loading text!!");
130 | load.frame(["◰", "◳", "◲", "◱"]);
131 | load.start();
132 | ```
133 |
134 | ## .text
135 |
136 | Change the text.
137 |
138 | ## .color
139 |
140 | Change the spinner color.
141 |
142 | ## Contributors
143 |
144 | As always, thanks to our amazing contributors!
145 |
146 |
147 |
148 |
149 |
150 | Made with [contributors](https://github.com/jaywcjlove/github-action-contributors).
151 |
152 | ## License
153 |
154 | Licensed under the MIT License.
155 |
--------------------------------------------------------------------------------
/index.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | declare namespace loading {
4 | interface Options {
5 | text?: string;
6 | color?: string;
7 | interval?: number;
8 | stream?: NodeJS.WritableStream;
9 | frames?: string[];
10 | }
11 | interface Loading {
12 | /**
13 | * Change the text after the spinner.
14 | */
15 | text: string;
16 | /**
17 | * Change the spinner color.
18 | */
19 | color: string;
20 | /**
21 | * Start the spinner.
22 | * @param text - Set the current text.
23 | */
24 | start(text?: string): Loading;
25 | /**
26 | * Stop and clear the spinner.
27 | * @returns The spinner instance.
28 | */
29 | stop(): Loading;
30 | /**
31 | * Clear the spinner.
32 | * @returns The spinner instance.
33 | */
34 | clear(): Loading;
35 | /**
36 | * Stop the spinner, change it to a green `✔` and persist the current text, or `text` if provided.
37 | * @param text - Will persist text if provided.
38 | * @returns The spinner instance.
39 | */
40 | succeed(text?: string): Loading;
41 |
42 | /**
43 | * Stop the spinner, change it to a red `✖` and persist the current text, or `text` if provided.
44 | * @param text - Will persist text if provided.
45 | * @returns The spinner instance.
46 | */
47 | fail(text?: string): Loading;
48 | /**
49 | * Stop the spinner, change it to a yellow `⚠` and persist the current text, or `text` if provided.
50 | * @param text - Will persist text if provided.
51 | * @returns The spinner instance.
52 | */
53 | warn(text?: string): Loading;
54 |
55 | /**
56 | * Stop the spinner, change it to a blue `ℹ` and persist the current text, or `text` if provided.
57 | * @param text - Will persist text if provided.
58 | * @returns The spinner instance.
59 | */
60 | info(text?: string): Loading;
61 |
62 | /**
63 | * Manually render a new frame.
64 | * @returns The spinner instance.
65 | */
66 | render(): Loading;
67 | /**
68 | * Get a new frame.
69 | * @returns The spinner instance text.
70 | */
71 | frame(): string;
72 | }
73 | }
74 |
75 | declare const loading: {
76 | (options?: loading.Options | string): loading.Loading;
77 | }
78 |
79 |
80 | export = loading;
81 |
--------------------------------------------------------------------------------
/lib/cursor.js:
--------------------------------------------------------------------------------
1 | /**
2 | * ANSI控制码的说明
3 | *
4 | * 33[0m 关闭所有属性
5 | * 33[1m 设置高亮度
6 | * 33[4m 下划线
7 | * 33[5m 闪烁
8 | * 33[7m 反显
9 | * 33[8m 消隐
10 | * 33[30m -- 33[37m 设置前景色
11 | * 33[40m -- 33[47m 设置背景色
12 | * 33[nA 光标上移n行
13 | * 33[nB 光标下移n行
14 | * 33[nC 光标右移n行
15 | * 33[nD 光标左移n行
16 | * 33[y;xH设置光标位置
17 | * 33[2J 清屏
18 | * 33[K 清除从光标到行尾的内容
19 | * 33[s 保存光标位置
20 | * 33[u 恢复光标位置
21 | * 33[?25l 隐藏光标
22 | * 33[?25h 显示光标
23 | */
24 | var hidden = false;
25 | exports.show = function (stream) {
26 | const s = stream || process.stderr;
27 | if (!s.isTTY) {
28 | return;
29 | }
30 | hidden = false;
31 | s.write('\u001b[?25h');
32 | };
33 | exports.hide = function (stream) {
34 | var s = stream || process.stderr;
35 | if (!s.isTTY) {
36 | return;
37 | }
38 | hidden = true;
39 | s.write('\u001b[?25l');
40 | };
41 | exports.toggle = function (force) {
42 | if (force !== undefined) {
43 | hidden = force;
44 | }
45 | if (hidden) {
46 | exports.show();
47 | } else {
48 | exports.hide();
49 | }
50 | };
51 |
--------------------------------------------------------------------------------
/lib/index.js:
--------------------------------------------------------------------------------
1 | var ut = require('./utilities');
2 | var cursor = require('./cursor');
3 | var color = require('colors-cli')
4 |
5 | function loading(options) {
6 | if (!(this instanceof loading)) {
7 | return new loading(options)
8 | }
9 | if (typeof options === 'string') {
10 | options = {
11 | text: options
12 | }
13 | }
14 |
15 | this.options = ut.extend(options, {
16 | text: '',
17 | color: 'cyan',
18 | stream: process.stderr,
19 | // stream: process.stdout
20 | // loading 样式
21 | frames: ["◜", "◠", "◝", "◞", "◡", "◟"]
22 | });
23 |
24 | // 文本显示
25 | this.text = this.options.text;
26 |
27 | // 颜色显示
28 | this.color = this.options.color;
29 |
30 | // 动画间隔时间
31 | this.interval = this.options.interval || 60;
32 | this.stream = this.options.stream;
33 |
34 | // loading 样式
35 | this.frames = this.options.frames;
36 |
37 | // 不存在
38 | this.id = null;
39 |
40 | // 要检查 Node 是否正在运行一个 TTY上下文 中
41 | // linux 中没有运行在 tty 下的进程是 守护进程
42 | this.enabled = this.options.enabled || ((this.stream && this.stream.isTTY) && !process.env.CI);
43 | this.frameIndex = 0;
44 | }
45 |
46 | loading.prototype.frame = function (frame) {
47 | if (frame) this.options.frames = frame;
48 | var frames = this.options.frames;
49 | // var frames = ["◜", "◠", "◝", "◞", "◡", "◟"];
50 | // var frames = ["◰", "◳", "◲", "◱"]
51 | // var frames = ["◐", "◓", "◑", "◒"]
52 | // var frames = [".", "o", "O", "°", "O", "o", "."]
53 | // var frames = ["⊶", "⊷"]
54 | // var frames = ["ဝ", "၀"]
55 | // var frames = ["←", "↖", "↑", "↗", "→", "↘", "↓", "↙"]
56 | // var frames = ["🕐 ", "🕑 ", "🕒 ", "🕓 ", "🕔 ", "🕕 ", "🕖 ", "🕗 ", "🕘 ", "🕙 ", "🕚 "]
57 | var frame = frames[this.frameIndex];
58 | if (this.color) {
59 | frame = color[this.color](frame);
60 | }
61 | this.frameIndex = ++this.frameIndex % frames.length;
62 | return frame + ' ' + this.text;
63 | }
64 |
65 | loading.prototype.clear = function () {
66 | if (!this.enabled) {
67 | return this;
68 | }
69 | this.stream.clearLine();
70 | this.stream.cursorTo(0);
71 | return this;
72 | }
73 |
74 | loading.prototype.render = function () {
75 | this.clear();
76 | this.stream.write(this.frame());
77 | return this;
78 | }
79 |
80 | loading.prototype.start = function (text) {
81 | if (text) this.text = text;
82 | if (!this.enabled || this.id) return this;
83 | this.clear();
84 | cursor.hide(this.stream);
85 | this.id = setInterval(this.render.bind(this), this.interval);
86 | return this;
87 | }
88 |
89 | loading.prototype.stop = function () {
90 | if (!this.enabled) return this;
91 | clearInterval(this.id);
92 | this.id = null;
93 | this.clear();
94 | cursor.show(this.stream);
95 | return this;
96 | }
97 |
98 | loading.prototype.succeed = function (text) {
99 | return this.stopAndPersist(color.green('✔'), text);
100 | }
101 | loading.prototype.fail = function (text) {
102 | return this.stopAndPersist(color.red('✖'), text);
103 | }
104 | loading.prototype.warn = function (text) {
105 | return this.stopAndPersist(color.yellow('⚠'), text);
106 | }
107 | loading.prototype.info = function (text) {
108 | return this.stopAndPersist(color.blue('ℹ'), text);
109 | }
110 | loading.prototype.stopAndPersist = function (symbol, text) {
111 | text = text || this.text
112 | this.stop();
113 | this.stream.write((symbol ? symbol + ' ' : ' ') + text + '\n');
114 | return this;
115 | }
116 |
117 | module.exports = loading
118 |
--------------------------------------------------------------------------------
/lib/utilities.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | extend:extend
3 | }
4 |
5 | // 合并对象
6 | function extend(des, src, override){
7 | if(src instanceof Array){
8 | for(var i = 0, len = src.length; i < len; i++)
9 | extend(des, src[i], override);
10 | }
11 | for( var i in src){
12 | if(override || !(i in des)){
13 | des[i] = src[i];
14 | }
15 | }
16 | return des;
17 | }
18 |
--------------------------------------------------------------------------------
/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "loading-cli",
3 | "version": "1.1.2",
4 | "lockfileVersion": 1,
5 | "requires": true,
6 | "dependencies": {
7 | "colors-cli": {
8 | "version": "1.0.33",
9 | "resolved": "https://registry.npmjs.org/colors-cli/-/colors-cli-1.0.33.tgz",
10 | "integrity": "sha512-PWGsmoJFdOB0t+BeHgmtuoRZUQucOLl5ii81NBzOOGVxlgE04muFNHlR5j8i8MKbOPELBl3243AI6lGBTj5ICQ=="
11 | }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "loading-cli",
3 | "version": "1.1.2",
4 | "description": "Terminal loading effect.",
5 | "homepage": "http://jaywcjlove.github.io/loading-cli",
6 | "funding": "https://jaywcjlove.github.io/#/sponsor",
7 | "main": "lib/index.js",
8 | "scripts": {
9 | "test": "node test/test.js"
10 | },
11 | "repository": {
12 | "type": "git",
13 | "url": "https://github.com/jaywcjlove/loading-cli"
14 | },
15 | "keywords": [
16 | "command",
17 | "loading-cli",
18 | "loading",
19 | "exit",
20 | "quit",
21 | "process",
22 | "graceful",
23 | "shutdown",
24 | "sigterm",
25 | "sigint",
26 | "cli",
27 | "cursor",
28 | "ansi",
29 | "term",
30 | "terminal",
31 | "console",
32 | "shell",
33 | "command-line"
34 | ],
35 | "files": [
36 | "lib",
37 | "index.d.ts"
38 | ],
39 | "author": "kenny wang ",
40 | "license": "MIT",
41 | "dependencies": {
42 | "colors-cli": "^1.0.26"
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/renovate.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": [
3 | "config:base"
4 | ]
5 | }
6 |
--------------------------------------------------------------------------------
/test/test.js:
--------------------------------------------------------------------------------
1 | var load = require('../');
2 | var st = load({
3 | "text":"loading text!!"
4 | })
5 |
6 | st.start()
7 |
8 | setTimeout(function(){
9 | // st.stop()
10 | st.frame(["◰", "◳", "◲", "◱"]);
11 | st.text = 'Loading rainbows';
12 | },1000)
13 |
14 | setTimeout(function(){
15 | st.stop()
16 | },3000)
17 |
18 |
--------------------------------------------------------------------------------