Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: unify log format with new logger utility #5994

Merged
merged 37 commits into from
Dec 20, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
c1bad8d
refactor: migrate from chalk to picocolors
Josh-Cena Nov 23, 2021
4660e46
Fix
Josh-Cena Nov 23, 2021
bc6645c
Migrate some packages to logger
Josh-Cena Nov 28, 2021
fe952e4
Merge branch 'main' into jc/picocolors
Josh-Cena Nov 28, 2021
77784f3
Fix package
Josh-Cena Nov 28, 2021
b111968
Interpolate messages
Josh-Cena Nov 28, 2021
f0c50ee
Fix TS
Josh-Cena Nov 28, 2021
2139b66
Fixes
Josh-Cena Nov 28, 2021
cfe7700
Better API
Josh-Cena Nov 28, 2021
9ff817d
Fix
Josh-Cena Nov 28, 2021
dd8f609
More migration
Josh-Cena Nov 28, 2021
2508609
Tweak
Josh-Cena Nov 28, 2021
1309520
Template tags!
Josh-Cena Nov 28, 2021
feaa03e
Complete migration
Josh-Cena Nov 28, 2021
f18d012
Write docs
Josh-Cena Nov 28, 2021
c25b60e
Fix docs
Josh-Cena Nov 28, 2021
46e6c9d
Migrate the rest
Josh-Cena Nov 28, 2021
7b1cc11
Fix snapshots
Josh-Cena Nov 28, 2021
9e2812c
tweaks
Josh-Cena Nov 28, 2021
bb9bebc
Tweak
Josh-Cena Nov 28, 2021
a0113a5
Add tests
Josh-Cena Nov 29, 2021
c52228b
Fix test
Josh-Cena Nov 29, 2021
446aa2c
Fix
Josh-Cena Nov 29, 2021
a7a99fc
Tweaks
Josh-Cena Nov 29, 2021
e757074
More friendly syntax
Josh-Cena Dec 3, 2021
8322a3d
id => name
Josh-Cena Dec 3, 2021
fc4b0ea
Refactor theme-translations
Josh-Cena Dec 3, 2021
0a706c0
Merge branch 'main' into jc/picocolors
Josh-Cena Dec 3, 2021
577713c
Fix lock
Josh-Cena Dec 3, 2021
689a5cd
Merge branch 'main' into jc/picocolors
Josh-Cena Dec 3, 2021
5e54822
Hail chalk
Josh-Cena Dec 4, 2021
496245f
Fix
Josh-Cena Dec 4, 2021
b484675
Merge branch 'main' into jc/picocolors
Josh-Cena Dec 18, 2021
326962a
Fix test
Josh-Cena Dec 18, 2021
55aded0
Fix tests
Josh-Cena Dec 18, 2021
47e25e7
Fixes
Josh-Cena Dec 19, 2021
ac3f1af
remove picocolors deps
slorber Dec 20, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ module.exports = {
'array-callback-return': WARNING,
camelcase: WARNING,
'no-restricted-syntax': WARNING,
'no-unused-expressions': WARNING,
'no-unused-expressions': [WARNING, {allowTaggedTemplates: true}],
'global-require': WARNING,
'prefer-destructuring': WARNING,
yoda: WARNING,
Expand Down
17 changes: 7 additions & 10 deletions packages/create-docusaurus/bin/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,27 +6,25 @@
* LICENSE file in the root directory of this source tree.
*/

const chalk = require('chalk');
// @ts-check

const logger = require('@docusaurus/logger').default;
const semver = require('semver');
const path = require('path');
const program = require('commander');
const {default: init} = require('../lib');
const requiredVersion = require('../package.json').engines.node;

if (!semver.satisfies(process.version, requiredVersion)) {
console.log(
chalk.red(`\nMinimum Node.js version not met :)`) +
chalk.yellow(
`\nYou are using Node.js ${process.version}, Requirement: Node.js ${requiredVersion}.\n`,
),
);
logger.error('Minimum Node.js version not met :(');
logger.info`You are using Node.js number=${process.version}, Requirement: Node.js number=${requiredVersion}.`;
process.exit(1);
}

function wrapCommand(fn) {
return (...args) =>
fn(...args).catch((err) => {
console.error(chalk.red(err.stack));
logger.error(err.stack);
process.exitCode = 1;
});
}
Expand Down Expand Up @@ -58,8 +56,7 @@ program

program.arguments('<command>').action((cmd) => {
program.outputHelp();
console.log(` ${chalk.red(`\n Unknown command ${chalk.yellow(cmd)}.`)}`);
console.log();
logger.error`Unknown command code=${cmd}.`;
});

program.parse(process.argv);
Expand Down
2 changes: 1 addition & 1 deletion packages/create-docusaurus/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
},
"license": "MIT",
"dependencies": {
"chalk": "^4.1.2",
"@docusaurus/logger": "2.0.0-beta.13",
"commander": "^5.1.0",
"fs-extra": "^10.0.0",
"lodash": "^4.17.20",
Expand Down
77 changes: 38 additions & 39 deletions packages/create-docusaurus/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* LICENSE file in the root directory of this source tree.
*/

import chalk from 'chalk';
import logger from '@docusaurus/logger';
import fs from 'fs-extra';
import {execSync} from 'child_process';
import prompts, {Choice} from 'prompts';
Expand Down Expand Up @@ -131,12 +131,14 @@ export default async function init(
}

if (!name) {
throw new Error(chalk.red('A website name is required.'));
logger.error('A website name is required.');
process.exit(1);
}

const dest = path.resolve(rootDir, name);
if (fs.existsSync(dest)) {
throw new Error(`Directory already exists at "${dest}"!`);
logger.error`Directory already exists at path=${dest}!`;
process.exit(1);
}

let template = reqTemplate;
Expand Down Expand Up @@ -171,10 +173,10 @@ export default async function init(
if (url && isValidGitRepoUrl(url)) {
return true;
}
return chalk.red(`Invalid repository URL`);
return logger.red('Invalid repository URL');
},
message:
'Enter a repository URL from GitHub, Bitbucket, GitLab, or any other public repo.\n(e.g: https://github.com/ownerName/repoName.git)',
message: logger.interpolate`Enter a repository URL from GitHub, Bitbucket, GitLab, or any other public repo.
(e.g: path=${'https://github.com/ownerName/repoName.git'})`,
});
template = repoPrompt.gitRepoUrl;
} else if (template === 'Local template') {
Expand All @@ -187,11 +189,11 @@ export default async function init(
if (fs.existsSync(fullDir)) {
return true;
}
return chalk.red(
`The path ${chalk.magenta(fullDir)} does not exist.`,
return logger.red(
logger.interpolate`path=${fullDir} does not exist.`,
);
}
return chalk.red('Please enter a valid path.');
return logger.red('Please enter a valid path.');
},
message:
'Enter a local folder path, relative to the current working directory.',
Expand All @@ -200,49 +202,47 @@ export default async function init(
}

if (!template) {
throw new Error('Template should not be empty');
logger.error('Template should not be empty');
process.exit(1);
}

console.log(`
${chalk.cyan('Creating new Docusaurus project...')}
`);
logger.info('Creating new Docusaurus project...');

if (isValidGitRepoUrl(template)) {
console.log(`Cloning Git template ${chalk.cyan(template)}...`);
logger.info`Cloning Git template path=${template}...`;
if (
shell.exec(`git clone --recursive ${template} ${dest}`, {silent: true})
.code !== 0
) {
throw new Error(chalk.red(`Cloning Git template ${template} failed!`));
logger.error`Cloning Git template name=${template} failed!`;
process.exit(1);
}
} else if (templates.includes(template)) {
// Docusaurus templates.
if (useTS) {
if (!hasTS(template)) {
throw new Error(
`Template ${template} doesn't provide the Typescript variant.`,
);
logger.error`Template name=${template} doesn't provide the Typescript variant.`;
process.exit(1);
}
template = `${template}${TypeScriptTemplateSuffix}`;
}
try {
await copyTemplate(templatesDir, template, dest);
} catch (err) {
console.log(
`Copying Docusaurus template ${chalk.cyan(template)} failed!`,
);
logger.error`Copying Docusaurus template name=${template} failed!`;
throw err;
}
} else if (fs.existsSync(path.resolve(process.cwd(), template))) {
const templateDir = path.resolve(process.cwd(), template);
try {
await fs.copy(templateDir, dest);
} catch (err) {
console.log(`Copying local template ${templateDir} failed!`);
logger.error`Copying local template path=${templateDir} failed!`;
throw err;
}
} else {
throw new Error('Invalid template.');
logger.error('Invalid template.');
process.exit(1);
}

// Update package.json info.
Expand All @@ -253,7 +253,7 @@ ${chalk.cyan('Creating new Docusaurus project...')}
private: true,
});
} catch (err) {
console.log(chalk.red('Failed to update package.json.'));
logger.error('Failed to update package.json.');
throw err;
}

Expand All @@ -275,7 +275,7 @@ ${chalk.cyan('Creating new Docusaurus project...')}
? name
: path.relative(process.cwd(), name);
if (!cliOptions.skipInstall) {
console.log(`Installing dependencies with ${chalk.cyan(pkgManager)}...`);
logger.info`Installing dependencies with name=${pkgManager}...`;
if (
shell.exec(
`cd "${name}" && ${useYarn ? 'yarn' : 'npm install --color always'}`,
Expand All @@ -288,36 +288,35 @@ ${chalk.cyan('Creating new Docusaurus project...')}
},
).code !== 0
) {
console.error(chalk.red('Dependency installation failed.'));
console.log(`The site directory has already been created, and you can retry by typing:
logger.error('Dependency installation failed.');
logger.info`The site directory has already been created, and you can retry by typing:

${chalk.cyan('cd')} ${cdpath}
${chalk.cyan(`${pkgManager} install`)}`);
code=${`cd ${cdpath}`}
code=${`${pkgManager} install`}`;
process.exit(0);
}
}

console.log(`
Successfully created "${chalk.cyan(cdpath)}".
Inside that directory, you can run several commands:
logger.success`Created path=${cdpath}.`;
logger.info`Inside that directory, you can run several commands:

${chalk.cyan(`${pkgManager} start`)}
code=${`${pkgManager} start`}
Starts the development server.

${chalk.cyan(`${pkgManager} ${useYarn ? '' : 'run '}build`)}
code=${`${pkgManager} ${useYarn ? '' : 'run '}build`}
Bundles your website into static files for production.

${chalk.cyan(`${pkgManager} ${useYarn ? '' : 'run '}serve`)}
code=${`${pkgManager} ${useYarn ? '' : 'run '}serve`}
Serves the built website locally.

${chalk.cyan(`${pkgManager} deploy`)}
code=${`${pkgManager} deploy`}
Publishes the website to GitHub pages.

We recommend that you begin by typing:

${chalk.cyan('cd')} ${cdpath}
${chalk.cyan(`${pkgManager} start`)}
code=${`cd ${cdpath}`}
code=${`${pkgManager} start`}

Happy building awesome websites!
`);
`;
}
4 changes: 4 additions & 0 deletions packages/docusaurus-logger/.npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
copyUntypedFiles.js
.tsbuildinfo
tsconfig*
__tests__
44 changes: 44 additions & 0 deletions packages/docusaurus-logger/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# `@docusaurus/logger`

An encapsulated logger for semantically formatting console messages.

## APIs

It exports a single object as default export: `logger`. `logger` has the following properties:

- Some useful colors.
- Formatters. These functions have the same signature as the formatters of `picocolors`. Note that their implementations are not guaranteed. You should only care about their semantics.
- `path`: formats a file path or URL.
- `id`: formats an identifier.
- `code`: formats a code snippet.
- `subdue`: subdues the text.
- `num`: formats a number.
- The `interpolate` function. It is a template literal tag.
- Logging functions. All logging functions can both be used as functions (in which it has the same usage as `console.log`) or template literal tags.
- `info`: prints information.
- `warn`: prints a warning that should be payed attention to.
- `error`: prints an error (not necessarily halting the program) that signals significant problems.
- `success`: prints a success message.

### Using the template literal tag

The template literal tag evaluates the template and expressions embedded. `interpolate` returns a new string, while other logging functions prints it. Below is a typical usage:

```js
logger.info`Hello name=${name}! You have number=${money} dollars. Here are the ${
items.length > 1 ? 'items' : 'item'
} on the shelf: ${items}
To buy anything, enter code=${'buy x'} where code=${'x'} is the item's name; to quit, press code=${'Ctrl + C'}.`;
```

An embedded expression is optionally preceded by a flag in the form `%[a-z]+` (a percentage sign followed by a few lowercase letters). If it's not preceded by any flag, it's printed out as-is. Otherwise, it's formatted with one of the formatters:

- `path=`: `path`
- `name=`: `id`
- `code=`: `code`
- `subdue=`: `subdue`
- `number=`: `num`

If the expression is an array, it's formatted by `` `\n- ${array.join('\n- ')}\n` `` (note it automatically gets a leading line end). Each member is formatted by itself and the bullet is not formatted. So you would see the above message printed as:

![demo](./demo.png)
Binary file added packages/docusaurus-logger/demo.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
32 changes: 32 additions & 0 deletions packages/docusaurus-logger/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"name": "@docusaurus/logger",
"version": "2.0.0-beta.13",
"description": "An encapsulated logger for semantically formatting console messages.",
"main": "./lib/index.js",
"repository": {
"type": "git",
"url": "https://github.com/facebook/docusaurus.git",
"directory": "packages/docusaurus-logger"
},
"bugs": {
"url": "https://github.com/facebook/docusaurus/issues"
},
"scripts": {
"build": "tsc",
"watch": "tsc --watch"
},
"publishConfig": {
"access": "public"
},
"license": "MIT",
"dependencies": {
"chalk": "^4.1.2",
"tslib": "^2.3.1"
},
"engines": {
"node": ">=14"
},
"devDependencies": {
"@types/supports-color": "^8.1.1"
}
}
11 changes: 11 additions & 0 deletions packages/docusaurus-logger/src/__mocks__/chalk.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

const chalk = require('chalk');

// Force coloring the output even in CI
module.exports = new chalk.Instance({level: 3});