Skip to content

Commit 4a47544

Browse files
Merge branch 'main' into dependabot/npm_and_yarn/commander-13.0.0
2 parents efafa13 + ec9a518 commit 4a47544

26 files changed

+493
-236
lines changed

.github/workflows/test.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,5 @@ jobs:
3737
node-version: ${{ matrix.node-version }}
3838

3939
- run: npm ci
40+
- run: npm run typecheck
4041
- run: npm run test:all

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ For the list of available translations, please refer to the main [tldr](https://
6262

6363
You can configure the `tldr` client by adding a `.tldrrc` file in your HOME directory. You can copy the contents of the `config.json` file from the repo to get the basic structure to start with, and modify it to suit your needs.
6464

65-
The default color theme is the one named `"simple"`. You can change the theme by assigning a different value to the `"theme"` variable -- either to one of the pre-configured themes, or to a new theme that you have previously created in the `"themes"` section. Note that the colors and text effects you can choose are limited. Refer to the [chalk documentation](https://github.com/chalk/chalk#styles) for all options.
65+
The default color theme is the one named `"simple"`. You can change the theme by assigning a different value to the `"theme"` variable -- either to one of the pre-configured themes, or to a new theme that you have previously created in the `"themes"` section. Note that the colors and text effects you can choose are limited. Refer to the [Node.js documentation](https://nodejs.org/api/util.html#modifiers) for all options.
6666

6767
```json
6868
{

lib/cache.js

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,21 @@ class Cache {
1414
this.cacheFolder = path.join(config.cache, 'cache');
1515
}
1616

17+
/**
18+
* Fetch stats from the cache folder for getting its last modified time
19+
* (mtime).
20+
*
21+
* @returns {Promise<any>} A promise with the stats of the cache folder.
22+
*/
1723
lastUpdated() {
1824
return fs.stat(this.cacheFolder);
1925
}
2026

27+
/**
28+
* Fetch a page from cache using preferred language and preferred platform.
29+
* @param {string} page
30+
* @returns {Promise<string>}
31+
*/
2132
getPage(page) {
2233
let preferredPlatform = platforms.getPreferredPlatformFolder(this.config);
2334
const preferredLanguage = process.env.LANG || 'en';
@@ -34,10 +45,20 @@ class Cache {
3445
});
3546
}
3647

48+
/**
49+
* Clean the cache folder.
50+
* @returns {Promise<any>} A promise when the remove is completed.
51+
*/
3752
clear() {
3853
return fs.remove(this.cacheFolder);
3954
}
4055

56+
/**
57+
* Update the cache folder using a temporary directory, update the index and
58+
* return it.
59+
*
60+
* @returns {Promise<any>} The index.
61+
*/
4162
update() {
4263
// Temporary folder path: /tmp/tldr/{randomName}
4364
const tempFolder = path.join(os.tmpdir(), 'tldr', utils.uniqueId());
@@ -65,7 +86,6 @@ class Cache {
6586
index.rebuildPagesIndex(),
6687
]);
6788
})
68-
6989
.then(([_, shortIndex]) => {
7090
return shortIndex;
7191
});

lib/completion.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ class Completion {
2222

2323
appendScript(script) {
2424
const rcFilePath = this.getFilePath();
25-
return new Promise((resolve, reject) => {
25+
return new Promise((/** @type {(v?: never) => void} */ resolve, reject) => {
2626
fs.appendFile(rcFilePath, `\n${script}\n`, (err) => {
2727
if (err) {
2828
reject((new CompletionScriptError(`Error appending to ${rcFilePath}: ${err.message}`)));
@@ -79,4 +79,4 @@ fi
7979
}
8080
}
8181

82-
module.exports = Completion;
82+
module.exports = Completion;

lib/config.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@ exports.get = () => {
1111
const DEFAULT = path.join(__dirname, '..', 'config.json');
1212
const CUSTOM = path.join(osHomedir(), '.tldrrc');
1313

14-
let defaultConfig = JSON.parse(fs.readFileSync(DEFAULT));
14+
let defaultConfig = JSON.parse(fs.readFileSync(DEFAULT, 'utf-8'));
1515
defaultConfig.cache = path.join(osHomedir(), '.tldr');
1616

1717
let customConfig = {};
1818
try {
19-
customConfig = JSON.parse(fs.readFileSync(CUSTOM));
19+
customConfig = JSON.parse(fs.readFileSync(CUSTOM, 'utf-8'));
2020
} catch (ex) {
2121
if (ex instanceof SyntaxError) {
2222
throw new Error('The content of .tldrrc is not a valid JSON object:\n' + ex);

lib/index.js

Lines changed: 47 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,12 @@ let shortIndex = null;
1010
const pagesPath = path.join(config.get().cache, 'cache');
1111
const shortIndexFile = path.join(pagesPath, 'shortIndex.json');
1212

13+
/**
14+
* @param {string} page
15+
* @param {string|undefined} preferredPlatform
16+
* @param {string} preferredLanguage
17+
* @returns {Promise<?string>}
18+
*/
1319
function findPage(page, preferredPlatform, preferredLanguage) {
1420
// Load the index
1521
return getShortIndex()
@@ -33,7 +39,7 @@ function findPage(page, preferredPlatform, preferredLanguage) {
3339
ll = preferredLanguage.substring(0, preferredLanguage.indexOf('_'));
3440
}
3541
if (!hasLang(targets, preferredLanguage)) {
36-
preferredLanguage = ll;
42+
preferredLanguage = /** @type {string} */ (ll);
3743
}
3844

3945
// Page resolution logic:
@@ -91,25 +97,38 @@ function hasLang(targets, preferredLanguage) {
9197
});
9298
}
9399

94-
// hasPage is always called after the index is created,
95-
// hence just return the variable in memory.
96-
// There is no need to re-read the index file again.
100+
/**
101+
* Check if a page is in the index.
102+
*
103+
* @returns {boolean} The presence of the page in the index.
104+
*/
97105
function hasPage(page) {
106+
// hasPage is always called after the index is created,
107+
// hence just return the variable in memory.
108+
// There is no need to re-read the index file again.
98109
if (!shortIndex) {
99110
return false;
100111
}
101112
return page in shortIndex;
102113
}
103114

104-
// Return all commands available in the local cache.
115+
/**
116+
* Return all commands available in the local index.
117+
* @returns {Promise<string[]>} A promise with the commands from the index.
118+
*/
105119
function commands() {
106120
return getShortIndex().then((idx) => {
107121
return Object.keys(idx).sort();
108122
});
109123
}
110124

111-
// Return all commands for a given platform.
112-
// P.S. - The platform 'common' is always included.
125+
/**
126+
* Return all commands for a given platform. The 'common' platform is always
127+
* included.
128+
*
129+
* @param {string} platform The desired platform.
130+
* @returns {Promise<string[]>} The commands for a given platform.
131+
*/
113132
function commandsFor(platform) {
114133
return getShortIndex()
115134
.then((idx) => {
@@ -124,7 +143,11 @@ function commandsFor(platform) {
124143
});
125144
}
126145

127-
// Delete the index file.
146+
/**
147+
* Delete the index file.
148+
*
149+
* @returns {Promise<any>} A promise when the remove is completed.
150+
*/
128151
function clearPagesIndex() {
129152
return fs.unlink(shortIndexFile)
130153
.then(() => {
@@ -139,7 +162,9 @@ function clearPagesIndex() {
139162
});
140163
}
141164

142-
// Set the shortIndex variable to null.
165+
/**
166+
* Set the shortIndex variable to null.
167+
*/
143168
function clearRuntimeIndex() {
144169
shortIndex = null;
145170
}
@@ -150,18 +175,26 @@ function rebuildPagesIndex() {
150175
});
151176
}
152177

153-
// If the variable is not set, read the file and set it.
154-
// Else, just return the variable.
178+
/**
179+
* Return the index, that contains all available commands with their target os
180+
* and platform. If the index is not loaded, read the file and load it.
181+
*
182+
* @returns {Promise<any>} The index entries.
183+
*/
155184
function getShortIndex() {
156185
if (shortIndex) {
157186
return Promise.resolve(shortIndex);
158187
}
159188
return readShortPagesIndex();
160189
}
161190

162-
// Read the index file, and load it into memory.
163-
// If the file does not exist, create the data structure, write the file,
164-
// and load it into memory.
191+
/**
192+
* Read the index file, and load it into memory.
193+
*
194+
* If the file does not exist, create the data structure, write the file,
195+
* and load it into memory.
196+
* @returns {Promise<any>} The index entries.
197+
*/
165198
function readShortPagesIndex() {
166199
return fs.readJson(shortIndexFile)
167200
.then((idx) => {

lib/parser.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
'use strict';
22

3+
const { styleText } = require('node:util');
34
const unescape = require('lodash/unescape');
45
const marked = require('marked');
5-
const chalk = require('chalk');
66
const index = require('./index');
77

88
const allElements = [
@@ -17,6 +17,7 @@ function unhtml(text){
1717

1818
exports.parse = (markdown) => {
1919
// Creating the page structure
20+
/** @type {Required<import('./tldr').TldrPage> & { examples: any[] }} */
2021
let page = {
2122
name: '',
2223
description: '',
@@ -70,11 +71,11 @@ exports.parse = (markdown) => {
7071
};
7172

7273
r.strong = (text) => {
73-
return chalk.bold(text);
74+
return styleText('bold', text);
7475
};
7576

7677
r.em = (text) => {
77-
return chalk.italic(text);
78+
return styleText('italic', text);
7879
};
7980

8081
r.listitem = (text) => {

lib/remote.js

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,12 @@ const unzip = require('adm-zip');
66
const config = require('./config');
77
const axios = require('axios');
88

9-
// Downloads the zip file from github and extracts it to folder
9+
/**
10+
* Download the zip file from GitHub and extract it to folder.
11+
* @param {string} loc Path to a directory on disk.
12+
* @param {string} lang Language/locale code.
13+
* @returns {Promise<void>} A promise when the operation is completed.
14+
*/
1015
exports.download = (loc, lang) => {
1116
// If the lang is english then keep the url simple, otherwise add language.
1217
const suffix = (lang === 'en' ? '' : '.' + lang);
@@ -21,12 +26,12 @@ exports.download = (loc, lang) => {
2126
headers: { 'User-Agent' : 'tldr-node-client' },
2227
timeout: REQUEST_TIMEOUT,
2328
}).then((response) => {
24-
return new Promise((resolve, reject) => {
29+
return new Promise((/** @type {(v?: never) => void} */ resolve, reject) => {
2530
let fileName = path.join(loc, 'download_' + lang + '.zip');
2631

2732
const writer = fs.createWriteStream(fileName);
2833
response.data.pipe(writer);
29-
34+
3035
writer.on('finish', () => {
3136
writer.end();
3237
const zip = new unzip(fileName);
@@ -41,4 +46,4 @@ exports.download = (loc, lang) => {
4146
}).catch((err) => {
4247
return Promise.reject(err);
4348
});
44-
};
49+
};

lib/render.js

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,14 @@
33
const Theme = require('./theme');
44
const he = require('he'); // Import the 'he' library
55

6-
// The page structure is passed to this function, and then the theme is applied
7-
// to different parts of the page and rendered to the console
6+
/**
7+
* Page structure is passed to this function, and then the theme is applied to
8+
* different parts of the page and rendered to the console.
9+
*
10+
* @param {import('./tldr').TldrPage} page
11+
* @param {any} config
12+
* @returns {string|void}
13+
*/
814
exports.toANSI = (page, config) => {
915
// Creating the theme object
1016
let themeOptions = config.themes[config.theme];

0 commit comments

Comments
 (0)