create-docusaurus 3.9.2 → 3.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (25) hide show
  1. package/bin/index.js +5 -4
  2. package/lib/index.js +60 -39
  3. package/lib/prompts.d.ts +7 -0
  4. package/lib/prompts.js +23 -0
  5. package/lib/types.d.ts +7 -0
  6. package/lib/types.js +7 -0
  7. package/lib/utils.d.ts +23 -0
  8. package/lib/utils.js +50 -0
  9. package/package.json +4 -7
  10. package/templates/classic/package.json +6 -5
  11. package/templates/classic-typescript/package.json +9 -7
  12. package/templates/classic-typescript/tsconfig.json +6 -2
  13. package/templates/shared/blog/{2019-05-28-first-blog-post.md → 2019-05-28-first-blog-post.mdx} +1 -1
  14. package/templates/shared/blog/{2019-05-29-long-blog-post.md → 2019-05-29-long-blog-post.mdx} +2 -2
  15. package/templates/shared/blog/2021-08-26-welcome/{index.md → index.mdx} +1 -1
  16. package/templates/shared/docs/tutorial-basics/{congratulations.md → congratulations.mdx} +1 -1
  17. package/templates/shared/docs/tutorial-basics/markdown-features.mdx +24 -8
  18. /package/templates/shared/docs/{intro.md → intro.mdx} +0 -0
  19. /package/templates/shared/docs/tutorial-basics/{create-a-blog-post.md → create-a-blog-post.mdx} +0 -0
  20. /package/templates/shared/docs/tutorial-basics/{create-a-document.md → create-a-document.mdx} +0 -0
  21. /package/templates/shared/docs/tutorial-basics/{create-a-page.md → create-a-page.mdx} +0 -0
  22. /package/templates/shared/docs/tutorial-basics/{deploy-your-site.md → deploy-your-site.mdx} +0 -0
  23. /package/templates/shared/docs/tutorial-extras/{manage-docs-versions.md → manage-docs-versions.mdx} +0 -0
  24. /package/templates/shared/docs/tutorial-extras/{translate-your-site.md → translate-your-site.mdx} +0 -0
  25. /package/templates/shared/src/pages/{markdown-page.md → markdown-page.mdx} +0 -0
package/bin/index.js CHANGED
@@ -8,8 +8,9 @@
8
8
 
9
9
  // @ts-check
10
10
 
11
- import path from 'path';
12
- import {createRequire} from 'module';
11
+ import path from 'node:path';
12
+ import {inspect} from 'node:util';
13
+ import {createRequire} from 'node:module';
13
14
  import {logger} from '@docusaurus/logger';
14
15
  import semver from 'semver';
15
16
  import {program} from 'commander';
@@ -61,7 +62,7 @@ if (!process.argv.slice(1).length) {
61
62
  program.outputHelp();
62
63
  }
63
64
 
64
- process.on('unhandledRejection', (err) => {
65
- logger.error(err);
65
+ process.on('unhandledRejection', (error) => {
66
+ logger.error(inspect(error));
66
67
  process.exit(1);
67
68
  });
package/lib/index.js CHANGED
@@ -4,17 +4,17 @@
4
4
  * This source code is licensed under the MIT license found in the
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
- import fs from 'fs-extra';
8
- import { fileURLToPath } from 'url';
9
- import path from 'path';
10
- import _ from 'lodash';
7
+ import * as fs from 'node:fs/promises';
8
+ import { fileURLToPath } from 'node:url';
9
+ import path from 'node:path';
10
+ // KEEP DEPENDENCY SMALL HERE!
11
+ // create-docusaurus CLI should be as lightweight as possible
12
+ // TODO try to remove these third-party dependencies if possible
11
13
  import { logger } from '@docusaurus/logger';
12
- import execa from 'execa';
13
14
  import prompts from 'prompts';
14
15
  import supportsColor from 'supports-color';
15
- // TODO remove dependency on large @docusaurus/utils
16
- // would be better to have a new smaller @docusaurus/utils-cli package
17
- import { askPreferredLanguage } from '@docusaurus/utils';
16
+ import { runCommand, siteNameToPackageName } from './utils.js';
17
+ import { askPreferredLanguage } from './prompts.js';
18
18
  async function getLanguage(options) {
19
19
  if (options.typescript) {
20
20
  return 'typescript';
@@ -34,10 +34,16 @@ const lockfileNames = {
34
34
  bun: 'bun.lockb',
35
35
  };
36
36
  const packageManagers = Object.keys(lockfileNames);
37
+ function pathExists(filePath) {
38
+ return fs
39
+ .access(filePath, fs.constants.F_OK)
40
+ .then(() => true)
41
+ .catch(() => false);
42
+ }
37
43
  async function findPackageManagerFromLockFile(rootDir) {
38
44
  for (const packageManager of packageManagers) {
39
45
  const lockFilePath = path.join(rootDir, lockfileNames[packageManager]);
40
- if (await fs.pathExists(lockFilePath)) {
46
+ if (await pathExists(lockFilePath)) {
41
47
  return packageManager;
42
48
  }
43
49
  }
@@ -47,9 +53,9 @@ function findPackageManagerFromUserAgent() {
47
53
  return packageManagers.find((packageManager) => process.env.npm_config_user_agent?.startsWith(packageManager));
48
54
  }
49
55
  async function askForPackageManagerChoice() {
50
- const hasYarn = (await execa.command('yarn --version')).exitCode === 0;
51
- const hasPnpm = (await execa.command('pnpm --version')).exitCode === 0;
52
- const hasBun = (await execa.command('bun --version')).exitCode === 0;
56
+ const hasYarn = (await runCommand('yarn --version')) === 0;
57
+ const hasPnpm = (await runCommand('pnpm --version')) === 0;
58
+ const hasBun = (await runCommand('bun --version')) === 0;
53
59
  if (!hasYarn && !hasPnpm && !hasBun) {
54
60
  return 'npm';
55
61
  }
@@ -96,18 +102,29 @@ async function readTemplates() {
96
102
  return {
97
103
  name,
98
104
  path: path.join(templatesDir, name),
99
- tsVariantPath: (await fs.pathExists(tsVariantPath))
105
+ tsVariantPath: (await pathExists(tsVariantPath))
100
106
  ? tsVariantPath
101
107
  : undefined,
102
108
  };
103
109
  }));
104
110
  // Classic should be first in list!
105
- return _.sortBy(templates, (t) => t.name !== recommendedTemplate);
111
+ return templates.sort((a, b) => {
112
+ if (a.name === recommendedTemplate) {
113
+ return -1;
114
+ }
115
+ if (b.name === recommendedTemplate) {
116
+ return 1;
117
+ }
118
+ return 0;
119
+ });
106
120
  }
107
121
  async function copyTemplate(template, dest, language) {
108
- await fs.copy(path.join(templatesDir, 'shared'), dest);
122
+ await fs.cp(path.join(templatesDir, 'shared'), dest, {
123
+ recursive: true,
124
+ });
109
125
  const sourcePath = language === 'typescript' ? template.tsVariantPath : template.path;
110
- await fs.copy(sourcePath, dest, {
126
+ await fs.cp(sourcePath, dest, {
127
+ recursive: true,
111
128
  // Symlinks don't exist in published npm packages anymore, so this is only
112
129
  // to prevent errors during local testing
113
130
  filter: async (filePath) => !(await fs.lstat(filePath)).isSymbolicLink(),
@@ -176,7 +193,10 @@ async function getSiteName(reqName, rootDir) {
176
193
  return 'A website name is required.';
177
194
  }
178
195
  const dest = path.resolve(rootDir, siteName);
179
- if (await fs.pathExists(dest)) {
196
+ if (siteName === '.' && (await fs.readdir(dest)).length > 0) {
197
+ return logger.interpolate `Directory not empty at path=${dest}!`;
198
+ }
199
+ if (siteName !== '.' && (await pathExists(dest))) {
180
200
  return logger.interpolate `Directory already exists at path=${dest}!`;
181
201
  }
182
202
  return true;
@@ -236,7 +256,7 @@ async function getUserProvidedSource({ reqTemplate, templates, cliOptions, }) {
236
256
  strategy: cliOptions.gitStrategy ?? 'deep',
237
257
  };
238
258
  }
239
- if (await fs.pathExists(path.resolve(reqTemplate))) {
259
+ if (await pathExists(path.resolve(reqTemplate))) {
240
260
  return {
241
261
  type: 'local',
242
262
  path: path.resolve(reqTemplate),
@@ -303,7 +323,7 @@ async function askLocalSource() {
303
323
  validate: async (dir) => {
304
324
  if (dir) {
305
325
  const fullDir = path.resolve(dir);
306
- if (await fs.pathExists(fullDir)) {
326
+ if (await pathExists(fullDir)) {
307
327
  return true;
308
328
  }
309
329
  return logger.red(logger.interpolate `path=${fullDir} does not exist.`);
@@ -339,9 +359,10 @@ async function getSource(reqTemplate, templates, cliOptions) {
339
359
  });
340
360
  }
341
361
  async function updatePkg(pkgPath, obj) {
342
- const pkg = (await fs.readJSON(pkgPath));
362
+ const pkg = JSON.parse(await fs.readFile(pkgPath, 'utf8'));
343
363
  const newPkg = Object.assign(pkg, obj);
344
- await fs.outputFile(pkgPath, `${JSON.stringify(newPkg, null, 2)}\n`);
364
+ await fs.mkdir(path.dirname(pkgPath), { recursive: true });
365
+ await fs.writeFile(pkgPath, `${JSON.stringify(newPkg, null, 2)}\n`);
345
366
  }
346
367
  export default async function init(rootDir, reqName, reqTemplate, cliOptions = {}) {
347
368
  const [templates, siteName] = await Promise.all([
@@ -353,12 +374,15 @@ export default async function init(rootDir, reqName, reqTemplate, cliOptions = {
353
374
  logger.info('Creating new Docusaurus project...');
354
375
  if (source.type === 'git') {
355
376
  const gitCommand = await getGitCommand(source.strategy);
356
- if ((await execa(gitCommand, [source.url, dest])).exitCode !== 0) {
377
+ if ((await runCommand(gitCommand, [source.url, dest])) !== 0) {
357
378
  logger.error `Cloning Git template failed!`;
358
379
  process.exit(1);
359
380
  }
360
381
  if (source.strategy === 'copy') {
361
- await fs.remove(path.join(dest, '.git'));
382
+ await fs.rm(path.join(dest, '.git'), {
383
+ force: true,
384
+ recursive: true,
385
+ });
362
386
  }
363
387
  }
364
388
  else if (source.type === 'template') {
@@ -366,38 +390,35 @@ export default async function init(rootDir, reqName, reqTemplate, cliOptions = {
366
390
  await copyTemplate(source.template, dest, source.language);
367
391
  }
368
392
  catch (err) {
369
- logger.error `Copying Docusaurus template name=${source.template.name} failed!`;
370
- throw err;
393
+ throw new Error(logger.interpolate `Copying Docusaurus template name=${source.template.name} failed!`, { cause: err });
371
394
  }
372
395
  }
373
396
  else {
374
397
  try {
375
- await fs.copy(source.path, dest);
398
+ await fs.cp(source.path, dest, { recursive: true });
376
399
  }
377
400
  catch (err) {
378
- logger.error `Copying local template path=${source.path} failed!`;
379
- throw err;
401
+ throw new Error(logger.interpolate `Copying local template path=${source.path} failed!`, { cause: err });
380
402
  }
381
403
  }
382
404
  // Update package.json info.
383
405
  try {
384
406
  await updatePkg(path.join(dest, 'package.json'), {
385
- name: _.kebabCase(siteName),
407
+ name: siteNameToPackageName(siteName),
386
408
  version: '0.0.0',
387
409
  private: true,
388
410
  });
389
411
  }
390
412
  catch (err) {
391
- logger.error('Failed to update package.json.');
392
- throw err;
413
+ throw new Error('Failed to update package.json.', { cause: err });
393
414
  }
394
415
  // We need to rename the gitignore file to .gitignore
395
- if (!(await fs.pathExists(path.join(dest, '.gitignore'))) &&
396
- (await fs.pathExists(path.join(dest, 'gitignore')))) {
397
- await fs.move(path.join(dest, 'gitignore'), path.join(dest, '.gitignore'));
416
+ if (!(await pathExists(path.join(dest, '.gitignore'))) &&
417
+ (await pathExists(path.join(dest, 'gitignore')))) {
418
+ await fs.rename(path.join(dest, 'gitignore'), path.join(dest, '.gitignore'));
398
419
  }
399
- if (await fs.pathExists(path.join(dest, 'gitignore'))) {
400
- await fs.remove(path.join(dest, 'gitignore'));
420
+ if (await pathExists(path.join(dest, 'gitignore'))) {
421
+ await fs.rm(path.join(dest, 'gitignore'));
401
422
  }
402
423
  // Display the most elegant way to cd.
403
424
  const cdpath = path.relative('.', dest);
@@ -406,17 +427,17 @@ export default async function init(rootDir, reqName, reqTemplate, cliOptions = {
406
427
  process.chdir(dest);
407
428
  logger.info `Installing dependencies with name=${pkgManager}...`;
408
429
  // ...
409
- if ((await execa.command(pkgManager === 'yarn'
430
+ if ((await runCommand(pkgManager === 'yarn'
410
431
  ? 'yarn'
411
432
  : pkgManager === 'bun'
412
433
  ? 'bun install'
413
- : `${pkgManager} install --color always`, {
434
+ : `${pkgManager} install --color always`, [], {
414
435
  env: {
415
436
  ...process.env,
416
437
  // Force coloring the output
417
438
  ...(supportsColor.stdout ? { FORCE_COLOR: '1' } : {}),
418
439
  },
419
- })).exitCode !== 0) {
440
+ })) !== 0) {
420
441
  logger.error('Dependency installation failed.');
421
442
  logger.info `The site directory has already been created, and you can retry by typing:
422
443
 
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+ export declare function askPreferredLanguage(): Promise<'javascript' | 'typescript'>;
package/lib/prompts.js ADDED
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+ import prompts from 'prompts';
8
+ import { logger } from '@docusaurus/logger';
9
+ export async function askPreferredLanguage() {
10
+ const { language } = await prompts({
11
+ type: 'select',
12
+ name: 'language',
13
+ message: 'Which language do you want to use?',
14
+ choices: [
15
+ { title: logger.bold('JavaScript'), value: 'javascript' },
16
+ { title: logger.bold('TypeScript'), value: 'typescript' },
17
+ ],
18
+ });
19
+ if (!language) {
20
+ process.exit(0);
21
+ }
22
+ return language;
23
+ }
package/lib/types.d.ts ADDED
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+ export type PackageManager = 'npm' | 'yarn' | 'pnpm' | 'bun';
package/lib/types.js ADDED
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+ export {};
package/lib/utils.d.ts ADDED
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+ import type { SpawnOptions } from 'node:child_process';
8
+ /**
9
+ * Run a command, similar to execa(cmd,args) but simpler
10
+ * @param command
11
+ * @param args
12
+ * @param options
13
+ * @returns the command exit code
14
+ */
15
+ export declare function runCommand(command: string, args?: string[], options?: SpawnOptions): Promise<number>;
16
+ /**
17
+ * We use a simple kebab-case-like conversion
18
+ * It's not perfect, but good enough
19
+ * We don't want to depend on lodash in this package
20
+ * See https://github.com/facebook/docusaurus/pull/11653
21
+ * @param siteName
22
+ */
23
+ export declare function siteNameToPackageName(siteName: string): string;
package/lib/utils.js ADDED
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+ // @ts-expect-error: no types, but same as spawn()
8
+ import CrossSpawn from 'cross-spawn';
9
+ // We use cross-spawn instead of spawn because of Windows compatibility issues.
10
+ // For example, "yarn" doesn't work on Windows, it requires "yarn.cmd"
11
+ // Tools like execa() use cross-spawn under the hood, and "resolve" the command
12
+ const crossSpawn = CrossSpawn;
13
+ /**
14
+ * Run a command, similar to execa(cmd,args) but simpler
15
+ * @param command
16
+ * @param args
17
+ * @param options
18
+ * @returns the command exit code
19
+ */
20
+ export async function runCommand(command, args = [], options = {}) {
21
+ // This does something similar to execa.command()
22
+ // we split a string command (with optional args) into command+args
23
+ // this way it's compatible with spawn()
24
+ const [realCommand, ...baseArgs] = command.split(' ');
25
+ const allArgs = [...baseArgs, ...args];
26
+ if (!realCommand) {
27
+ throw new Error(`Invalid command: ${command}`);
28
+ }
29
+ return new Promise((resolve, reject) => {
30
+ const p = crossSpawn(realCommand, allArgs, { stdio: 'ignore', ...options });
31
+ p.on('error', reject);
32
+ p.on('close', (exitCode) => exitCode !== null
33
+ ? resolve(exitCode)
34
+ : reject(new Error(`No exit code for command ${command}`)));
35
+ });
36
+ }
37
+ /**
38
+ * We use a simple kebab-case-like conversion
39
+ * It's not perfect, but good enough
40
+ * We don't want to depend on lodash in this package
41
+ * See https://github.com/facebook/docusaurus/pull/11653
42
+ * @param siteName
43
+ */
44
+ export function siteNameToPackageName(siteName) {
45
+ const match = siteName.match(/[A-Z]{2,}(?=[A-Z][a-z]+\d*|\b|_)|[A-Z]?[a-z]+\d*|[A-Z]|\d+/g);
46
+ if (match) {
47
+ return match.map((x) => x.toLowerCase()).join('-');
48
+ }
49
+ return siteName;
50
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-docusaurus",
3
- "version": "3.9.2",
3
+ "version": "3.10.1",
4
4
  "description": "Create Docusaurus apps easily.",
5
5
  "type": "module",
6
6
  "repository": {
@@ -22,12 +22,9 @@
22
22
  },
23
23
  "license": "MIT",
24
24
  "dependencies": {
25
- "@docusaurus/logger": "3.9.2",
26
- "@docusaurus/utils": "3.9.2",
25
+ "@docusaurus/logger": "3.10.1",
27
26
  "commander": "^5.1.0",
28
- "execa": "5.1.1",
29
- "fs-extra": "^11.1.1",
30
- "lodash": "^4.17.21",
27
+ "cross-spawn": "^7.0.0",
31
28
  "prompts": "^2.4.2",
32
29
  "semver": "^7.5.4",
33
30
  "supports-color": "^9.4.0",
@@ -39,5 +36,5 @@
39
36
  "engines": {
40
37
  "node": ">=20.0"
41
38
  },
42
- "gitHead": "abfbe5621b08407bc3dcbe6111ff118d4c22f7a1"
39
+ "gitHead": "41c1a458ecb07d61b6df2761ea4bc1b13db49d12"
43
40
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "docusaurus-2-classic-template",
3
- "version": "3.9.2",
3
+ "version": "3.10.1",
4
4
  "private": true,
5
5
  "scripts": {
6
6
  "docusaurus": "docusaurus",
@@ -14,8 +14,9 @@
14
14
  "write-heading-ids": "docusaurus write-heading-ids"
15
15
  },
16
16
  "dependencies": {
17
- "@docusaurus/core": "3.9.2",
18
- "@docusaurus/preset-classic": "3.9.2",
17
+ "@docusaurus/core": "3.10.1",
18
+ "@docusaurus/faster": "3.10.1",
19
+ "@docusaurus/preset-classic": "3.10.1",
19
20
  "@mdx-js/react": "^3.0.0",
20
21
  "clsx": "^2.0.0",
21
22
  "prism-react-renderer": "^2.3.0",
@@ -23,8 +24,8 @@
23
24
  "react-dom": "^19.0.0"
24
25
  },
25
26
  "devDependencies": {
26
- "@docusaurus/module-type-aliases": "3.9.2",
27
- "@docusaurus/types": "3.9.2"
27
+ "@docusaurus/module-type-aliases": "3.10.1",
28
+ "@docusaurus/types": "3.10.1"
28
29
  },
29
30
  "browserslist": {
30
31
  "production": [
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "docusaurus-2-classic-typescript-template",
3
- "version": "3.9.2",
3
+ "version": "3.10.1",
4
4
  "private": true,
5
5
  "scripts": {
6
6
  "docusaurus": "docusaurus",
@@ -15,8 +15,9 @@
15
15
  "typecheck": "tsc"
16
16
  },
17
17
  "dependencies": {
18
- "@docusaurus/core": "3.9.2",
19
- "@docusaurus/preset-classic": "3.9.2",
18
+ "@docusaurus/core": "3.10.1",
19
+ "@docusaurus/faster": "3.10.1",
20
+ "@docusaurus/preset-classic": "3.10.1",
20
21
  "@mdx-js/react": "^3.0.0",
21
22
  "clsx": "^2.0.0",
22
23
  "prism-react-renderer": "^2.3.0",
@@ -24,10 +25,11 @@
24
25
  "react-dom": "^19.0.0"
25
26
  },
26
27
  "devDependencies": {
27
- "@docusaurus/module-type-aliases": "3.9.2",
28
- "@docusaurus/tsconfig": "3.9.2",
29
- "@docusaurus/types": "3.9.2",
30
- "typescript": "~5.6.2"
28
+ "@docusaurus/module-type-aliases": "3.10.1",
29
+ "@docusaurus/tsconfig": "3.10.1",
30
+ "@docusaurus/types": "3.10.1",
31
+ "@types/react": "^19.0.0",
32
+ "typescript": "~6.0.2"
31
33
  },
32
34
  "browserslist": {
33
35
  "production": [
@@ -1,8 +1,12 @@
1
+ // This file is not used by "docusaurus start/build" commands.
2
+ // It is here to improve your IDE experience (type-checking, autocompletion...),
3
+ // and can also run the package.json "typecheck" script manually.
1
4
  {
2
- // This file is not used in compilation. It is here just for a nice editor experience.
3
5
  "extends": "@docusaurus/tsconfig",
4
6
  "compilerOptions": {
5
- "baseUrl": "."
7
+ "baseUrl": ".",
8
+ "ignoreDeprecations": "6.0",
9
+ "strict": true
6
10
  },
7
11
  "exclude": [".docusaurus", "build"]
8
12
  }
@@ -7,6 +7,6 @@ tags: [hola, docusaurus]
7
7
 
8
8
  Lorem ipsum dolor sit amet...
9
9
 
10
- <!-- truncate -->
10
+ {/* truncate */}
11
11
 
12
12
  ...consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
@@ -7,9 +7,9 @@ tags: [hello, docusaurus]
7
7
 
8
8
  This is the summary of a very long blog post,
9
9
 
10
- Use a `<!--` `truncate` `-->` comment to limit blog post size in the list view.
10
+ Use a `{/*` `truncate` `*/}` comment to limit blog post size in the list view.
11
11
 
12
- <!-- truncate -->
12
+ {/* truncate */}
13
13
 
14
14
  Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
15
15
 
@@ -9,7 +9,7 @@ tags: [facebook, hello, docusaurus]
9
9
 
10
10
  Here are a few tips you might find useful.
11
11
 
12
- <!-- truncate -->
12
+ {/* truncate */}
13
13
 
14
14
  Simply add Markdown files (or folders) to the `blog` directory.
15
15
 
@@ -8,7 +8,7 @@ You have just learned the **basics of Docusaurus** and made some changes to the
8
8
 
9
9
  Docusaurus has **much more to offer**!
10
10
 
11
- Have **5 more minutes**? Take a look at **[versioning](../tutorial-extras/manage-docs-versions.md)** and **[i18n](../tutorial-extras/translate-your-site.md)**.
11
+ Have **5 more minutes**? Take a look at **[versioning](../tutorial-extras/manage-docs-versions.mdx)** and **[i18n](../tutorial-extras/translate-your-site.mdx)**.
12
12
 
13
13
  Anything **unclear** or **buggy** in this tutorial? [Please report it!](https://github.com/facebook/docusaurus/discussions/4610)
14
14
 
@@ -20,9 +20,25 @@ slug: /my-custom-url
20
20
  ---
21
21
  // highlight-end
22
22
 
23
- ## Markdown heading
23
+ Markdown content
24
+ ```
25
+
26
+ ## Headings {/* #my-heading-id */}
27
+
28
+ Markdown headings are supported using the standard “#” syntax and are automatically added to the table of contents. The number of `#` corresponds to the heading level.
29
+
30
+ ```md
31
+ ## Headings
24
32
 
25
- Markdown text with [links](./hello.md)
33
+ My text
34
+ ```
35
+
36
+ ### Heading Ids {/* #my-custom-id */}
37
+
38
+ Add `{/* #my-custom-id */}` after the heading text to assign it an explicit anchor id, used for linking.
39
+
40
+ ```md
41
+ ### Heading Ids {/_ #my-custom-id _/}
26
42
  ```
27
43
 
28
44
  ## Links
@@ -34,10 +50,10 @@ Let's see how to [Create a page](/create-a-page).
34
50
  ```
35
51
 
36
52
  ```md
37
- Let's see how to [Create a page](./create-a-page.md).
53
+ Let's see how to [Create a page](./create-a-page.mdx).
38
54
  ```
39
55
 
40
- **Result:** Let's see how to [Create a page](./create-a-page.md).
56
+ **Result:** Let's see how to [Create a page](./create-a-page.mdx).
41
57
 
42
58
  ## Images
43
59
 
@@ -80,26 +96,26 @@ function HelloDocusaurus() {
80
96
  Docusaurus has a special syntax to create admonitions and callouts:
81
97
 
82
98
  ```md
83
- :::tip My tip
99
+ :::tip[My tip]
84
100
 
85
101
  Use this awesome feature option
86
102
 
87
103
  :::
88
104
 
89
- :::danger Take care
105
+ :::danger[Take care]
90
106
 
91
107
  This action is dangerous
92
108
 
93
109
  :::
94
110
  ```
95
111
 
96
- :::tip My tip
112
+ :::tip[My tip]
97
113
 
98
114
  Use this awesome feature option
99
115
 
100
116
  :::
101
117
 
102
- :::danger Take care
118
+ :::danger[Take care]
103
119
 
104
120
  This action is dangerous
105
121
 
File without changes