umberto 7.0.0 → 7.0.2

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.
package/CHANGELOG.md CHANGED
@@ -1,6 +1,22 @@
1
1
  Changelog
2
2
  =========
3
3
 
4
+ ## [7.0.2](https://github.com/cksource/umberto/compare/v7.0.1...v7.0.2) (2025-05-20)
5
+
6
+ ### Bug fixes
7
+
8
+ * Fixed an invalid protocol (should be `https://` instead of `https:/`) in the generated index sitemap file. Closes [#1277](https://github.com/cksource/umberto/issues/1277). ([commit](https://github.com/cksource/umberto/commit/6f59654e85b1230fbfe029efe68f708755ec6342))
9
+
10
+
11
+ ## [7.0.1](https://github.com/cksource/umberto/compare/v7.0.0...v7.0.1) (2025-05-14)
12
+
13
+ ### Other changes
14
+
15
+ * Updated the project dependencies. Closes [#1253](https://github.com/cksource/umberto/issues/1253). ([commit](https://github.com/cksource/umberto/commit/28d74364207ab055ad76c2857d58cccb1866559b))
16
+ * Removed dependencies that can be replaced with native APIs or other already used dependencies. ([commit](https://github.com/cksource/umberto/commit/28d74364207ab055ad76c2857d58cccb1866559b))
17
+ * Sitemaps will be generated separately for each project. Closes [#1254](https://github.com/cksource/umberto/issues/1254). ([commit](https://github.com/cksource/umberto/commit/7968755b2a4b1c23768a9420292eb1d168b898b3))
18
+
19
+
4
20
  ## [7.0.0](https://github.com/cksource/umberto/compare/v6.1.2...v7.0.0) (2025-05-05)
5
21
 
6
22
  ### BREAKING CHANGES
package/hexo-config.json CHANGED
@@ -15,16 +15,11 @@
15
15
  "pug": {
16
16
  "pretty": true
17
17
  },
18
- "highlight": {
19
- "enable": false
20
- },
21
- "prism": {
22
- "enable": false
23
- },
24
- "markdown_it_plus": {
25
- "highlight": false,
26
- "html": true,
27
- "breaks": true,
18
+ "syntax_highlighter": "",
19
+ "markdown_it_plus": {
20
+ "highlight": false,
21
+ "html": true,
22
+ "breaks": true,
28
23
  "linkify": false,
29
24
  "plugins": [
30
25
  {
@@ -42,19 +37,19 @@
42
37
  "plugin": {
43
38
  "name": "markdown-it-expand-tabs",
44
39
  "enable": true,
45
- "options": {
46
- "tabWidth": 4
40
+ "options": {
41
+ "tabWidth": 4
47
42
  }
48
43
  }
49
44
  }
50
45
  ]
51
46
  },
52
- "skip_render": [
53
- "**/*.css",
54
- "**/*.scss",
55
- "**/*.html",
56
- "**/*.json",
57
- "**/*.js",
58
- "**/*.txt"
47
+ "skip_render": [
48
+ "**/*.css",
49
+ "**/*.scss",
50
+ "**/*.html",
51
+ "**/*.json",
52
+ "**/*.js",
53
+ "**/*.txt"
59
54
  ]
60
55
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "umberto",
3
- "version": "7.0.0",
3
+ "version": "7.0.2",
4
4
  "description": "CKSource Documentation builder",
5
5
  "main": "src/index.js",
6
6
  "files": [
@@ -15,42 +15,36 @@
15
15
  ],
16
16
  "dependencies": {
17
17
  "@babel/core": "^7.18.10",
18
- "@babel/polyfill": "^7.12.1",
19
18
  "@babel/preset-env": "^7.18.10",
20
19
  "@ckeditor/jsdoc-plugins": "^43.0.0",
21
- "babel-loader": "^8.2.5",
22
- "chalk": "^4.1.0",
20
+ "babel-loader": "^10.0.0",
23
21
  "cheerio": "^1.0.0",
24
- "cpx": "^1.5.0",
25
- "del": "^6.1.1",
26
- "element-closest": "^3.0.2",
27
22
  "escape-string-regexp": "^4.0.0",
28
23
  "fs-extra": "^11.0.0",
29
- "fuse.js": "^6.6.2",
30
- "glob": "^7.2.3",
31
- "hexo": "^6.2.0",
32
- "hexo-generator-archive": "^1.0.0",
33
- "hexo-generator-category": "^1.0.0",
34
- "hexo-generator-index": "^1.0.0",
35
- "hexo-generator-tag": "^1.0.0",
24
+ "fuse.js": "^7.1.0",
25
+ "glob": "^11.0.2",
26
+ "hexo": "^7.3.0",
27
+ "hexo-generator-archive": "^2.0.0",
28
+ "hexo-generator-category": "^2.0.0",
29
+ "hexo-generator-index": "^4.0.0",
30
+ "hexo-generator-tag": "^2.0.0",
36
31
  "hexo-render-pug": "^2.1.4",
37
32
  "hexo-renderer-markdown-it-plus": "^1.0.5",
38
33
  "htmlparser2": "^10.0.0",
39
34
  "javascript-stringify": "^2.1.0",
40
- "jquery": "~3.6.0",
35
+ "jquery": "~3.7.1",
41
36
  "js-beautify": "^1.14.4",
42
37
  "lodash": "^4.17.21",
43
- "markdown-it": "^13.0.1",
38
+ "markdown-it": "^14.1.0",
44
39
  "markdown-it-expand-tabs": "^1.0.13",
45
40
  "markdown-it-toc-and-anchor": "^4.2.0",
46
41
  "medium-zoom": "^1.0.6",
47
- "minimatch": "^5.1.0",
48
- "mkdirp": "^1.0.4",
42
+ "minimatch": "^10.0.1",
49
43
  "moment": "^2.29.4",
50
- "nyc": "^15.1.0",
44
+ "nyc": "^17.1.0",
51
45
  "pug": "^3.0.2",
52
46
  "sass": "^1.54.0",
53
- "sitemap": "^7.1.1",
47
+ "sitemap": "^8.0.0",
54
48
  "tippy.js": "^6.3.7",
55
49
  "tree-model": "^1.0.7",
56
50
  "upath": "^2.0.1",
@@ -79,6 +73,6 @@
79
73
  "packages/**"
80
74
  ],
81
75
  "hexo": {
82
- "version": "6.3.0"
76
+ "version": "7.3.0"
83
77
  }
84
78
  }
@@ -5,8 +5,7 @@
5
5
 
6
6
  'use strict';
7
7
 
8
- const util = require( 'util' );
9
- const chalk = require( 'chalk' );
8
+ const { format, styleText } = require( 'util' );
10
9
 
11
10
  hexo.extend.filter.register( 'after_post_render', page => {
12
11
  if ( !hexo.projectGlobals.common || !hexo.projectGlobals.common.verbose ) {
@@ -17,11 +16,11 @@ hexo.extend.filter.register( 'after_post_render', page => {
17
16
  // Log only pages, which generates for longer than 1 second.
18
17
  if ( time[ 0 ] > 1 ) {
19
18
  console.log(
20
- util.format(
19
+ format(
21
20
  'Page: %s was processed in: %s.%ss.',
22
- chalk.cyanBright( page.source ),
23
- chalk.yellow( time[ 0 ] ),
24
- chalk.yellow( time[ 1 ] )
21
+ styleText( 'cyanBright', page.source ),
22
+ styleText( 'yellow', time[ 0 ] ),
23
+ styleText( 'yellow', time[ 1 ] )
25
24
  )
26
25
  );
27
26
  }
@@ -5,7 +5,7 @@
5
5
 
6
6
  'use strict';
7
7
 
8
- const minimatch = require( 'minimatch' );
8
+ const { minimatch } = require( 'minimatch' );
9
9
 
10
10
  /**
11
11
  * @param {Object} page A page object.
@@ -5,7 +5,7 @@
5
5
 
6
6
  'use strict';
7
7
 
8
- const chalk = require( 'chalk' );
8
+ const { styleText } = require( 'util' );
9
9
 
10
10
  /**
11
11
  * Logs an error message about a cross-project reference found in the parsed expression.
@@ -19,8 +19,8 @@ const chalk = require( 'chalk' );
19
19
  module.exports = function logCrossProjectReference( { expression, source } ) {
20
20
  process.exitCode = 1;
21
21
 
22
- const message = `${ chalk.red( 'Error:' ) } Failed while convert ${ chalk.cyanBright( expression ) } tag`;
23
- const messageLocation = source ? ` in ${ chalk.magentaBright( source ) }.` : '.';
22
+ const message = `${ styleText( 'red', 'Error:' ) } Failed while convert ${ styleText( 'cyanBright', expression ) } tag`;
23
+ const messageLocation = source ? ` in ${ styleText( 'magentaBright', source ) }.` : '.';
24
24
  const messageDescription = ' Cross-project references are not supported.';
25
25
 
26
26
  console.log( message + messageLocation + messageDescription );
@@ -5,9 +5,9 @@
5
5
 
6
6
  'use strict';
7
7
 
8
+ const { styleText } = require( 'util' );
8
9
  const upath = require( 'upath' );
9
10
  const splitLongname = require( '../../src/helpers/split-longname' );
10
- const chalk = require( 'chalk' );
11
11
 
12
12
  const LINK_REGEXP = /\\?{(?:@linkapi|@link|@linksdk|@linkexample)\s+[^{]+?({[^}]+})?[^{}]*\\?}/g;
13
13
 
@@ -127,7 +127,7 @@ function linkToApi( str, data, hexo, { relativeUrlHelper, isSilentError } ) {
127
127
  value: str,
128
128
  source: data.source,
129
129
  isSilent: isSilentError,
130
- description: `Project ${ chalk.redBright( data.projectName ) } is not defined.`
130
+ description: `Project ${ styleText( 'redBright', data.projectName ) } is not defined.`
131
131
  } );
132
132
  }
133
133
 
@@ -343,10 +343,16 @@ function onError( { value, source, isSilent, description } ) {
343
343
  if ( !isSilent ) {
344
344
  process.exitCode = 1;
345
345
 
346
- console.log(
347
- `${ chalk.red( 'Error: ' ) }Failed while convert ${ chalk.cyanBright( value ) } tag in ` +
348
- `${ chalk.magentaBright( source ) }.${ description ? chalk.italic( ' ' + description ) : '' }`
349
- );
346
+ const message = [
347
+ styleText( 'red', 'Error:' ),
348
+ `Failed to convert ${ styleText( 'cyanBright', value ) } tag`,
349
+ source && `in ${ styleText( 'magentaBright', source ) }`,
350
+ description && `because ${ styleText( 'italic', description ) }`
351
+ ]
352
+ .filter( Boolean )
353
+ .join( ' ' );
354
+
355
+ console.log( message );
350
356
  }
351
357
 
352
358
  return value;
@@ -5,9 +5,9 @@
5
5
 
6
6
  'use strict';
7
7
 
8
+ const { styleText } = require( 'util' );
8
9
  const cheerio = require( 'cheerio' );
9
10
  const splitLongname = require( '../../helpers/split-longname' );
10
- const chalk = require( 'chalk' );
11
11
  const macroReplacer = require( '../../tasks/macro-replacer' );
12
12
  const findTargetDoclet = require( '../utils/findtargetdoclet' );
13
13
  const { hasDedicatedApiPages, LONG_NAME_LABEL_REGEXP, LONG_NAME_MEMBER_SEPARATOR_REGEXP } = require( '../utils/utils' );
@@ -283,7 +283,7 @@ module.exports = class DescriptionParser {
283
283
  replaceToPhrase = `<a href="${ href }">${ linkContent }</a>`;
284
284
  } else {
285
285
  console.log(
286
- `${ chalk.yellow( 'Warning:' ) } Invalid link in API docs: ${ chalk.gray( fullMatch ) }.`,
286
+ `${ styleText( 'yellow', 'Warning:' ) } Invalid link in API docs: ${ styleText( 'gray', fullMatch ) }.`,
287
287
  'There is no doclet of the link target.'
288
288
  );
289
289
 
@@ -6,7 +6,7 @@
6
6
  'use strict';
7
7
 
8
8
  const upath = require( 'upath' );
9
- const glob = require( 'glob' );
9
+ const { globSync } = require( 'glob' );
10
10
 
11
11
  const utils = {
12
12
  /**
@@ -36,14 +36,15 @@ const utils = {
36
36
  * @returns {SnippetSource}
37
37
  */
38
38
  getSnippetSourcePaths( basePath, snippetName ) {
39
- const snippetPaths = glob.sync( upath.join( basePath, snippetName + '.*' ) );
40
39
  const files = {};
41
40
 
42
- snippetPaths.forEach( singlePath => {
43
- const fileExtension = upath.extname( singlePath ).slice( 1 );
41
+ globSync( upath.join( basePath, snippetName + '.*' ) )
42
+ .map( path => upath.normalize( path ) )
43
+ .forEach( singlePath => {
44
+ const fileExtension = upath.extname( singlePath ).slice( 1 );
44
45
 
45
- files[ fileExtension ] = singlePath;
46
- } );
46
+ files[ fileExtension ] = singlePath;
47
+ } );
47
48
 
48
49
  return files;
49
50
  },
@@ -6,7 +6,7 @@
6
6
  'use strict';
7
7
 
8
8
  const upath = require( 'upath' );
9
- const glob = require( 'glob' );
9
+ const { globSync } = require( 'glob' );
10
10
 
11
11
  module.exports = ( {
12
12
  rootPath,
@@ -18,10 +18,9 @@ module.exports = ( {
18
18
 
19
19
  for ( const item of packages ) {
20
20
  const packageRepoUrl = getRepoUrl( upath.join( rootPath, item.path ) );
21
- glob.sync( upath.join( rootPath, item.path, 'docs', '**', '*.md' ) )
22
- .map( p => {
23
- return p.replace( upath.join( rootPath, item.path, 'docs' ), '' );
24
- } )
21
+ globSync( upath.join( rootPath, item.path, 'docs', '**', '*.md' ) )
22
+ .map( p => upath.normalize( p ) )
23
+ .map( p => p.replace( upath.join( rootPath, item.path, 'docs' ), '' ) )
25
24
  .forEach( p => {
26
25
  guidesToRepos[ p ] = packageRepoUrl;
27
26
  } );
@@ -5,13 +5,13 @@
5
5
 
6
6
  'use strict';
7
7
 
8
+ const { styleText } = require( 'util' );
8
9
  const upath = require( 'upath' );
9
10
  const fs = require( 'fs-extra' );
10
- const getHexoConfig = require( './tasks/get-hexo-config' );
11
+ const { globSync } = require( 'glob' );
11
12
  const Hexo = require( '../hexo-shim' );
13
+ const getHexoConfig = require( './tasks/get-hexo-config' );
12
14
  const extendConfig = require( './hexo/filter/extend-config' );
13
- const chalk = require( 'chalk' );
14
- const glob = require( 'glob' );
15
15
 
16
16
  /**
17
17
  * Class used to initialize and control hexo.
@@ -106,7 +106,9 @@ class HexoManager {
106
106
  return this.hexo.exit();
107
107
  } )
108
108
  .catch( err => {
109
- console.log( `${ chalk.red( 'Error:' ) } ${ chalk.redBright( 'There was something wrong during hexo generation.' ) }` );
109
+ console.log(
110
+ `${ styleText( 'red', 'Error:' ) } ${ styleText( 'redBright', 'There was something wrong during hexo generation.' ) }`
111
+ );
110
112
  this.hexo.exit( err );
111
113
 
112
114
  throw err;
@@ -132,14 +134,16 @@ class HexoManager {
132
134
 
133
135
  cleanSymLinks() {
134
136
  const rootPath = this.config.public_dir;
135
- const pathsToCheck = glob.sync( upath.join( rootPath, '**', 'latest' ) ).concat( glob.sync( upath.join( rootPath, 'latest' ) ) );
136
- pathsToCheck.forEach( p => {
137
- const stat = fs.lstatSync( p );
138
-
139
- if ( stat.isSymbolicLink() ) {
140
- fs.unlinkSync( p );
141
- }
142
- } );
137
+ globSync( upath.join( rootPath, '**', 'latest' ) )
138
+ .concat( globSync( upath.join( rootPath, 'latest' ) ) )
139
+ .map( p => upath.normalize( p ) )
140
+ .forEach( p => {
141
+ const stat = fs.lstatSync( p );
142
+
143
+ if ( stat.isSymbolicLink() ) {
144
+ fs.unlinkSync( p );
145
+ }
146
+ } );
143
147
  }
144
148
 
145
149
  /**
package/src/index.js CHANGED
@@ -5,8 +5,8 @@
5
5
 
6
6
  'use strict';
7
7
 
8
+ const { styleText } = require( 'util' );
8
9
  const path = require( 'path' );
9
- const chalk = require( 'chalk' );
10
10
  const compileSass = require( './tasks/compile-sass' );
11
11
  const runWebpack = require( './tasks/run-webpack' );
12
12
  const copyAssets = require( './tasks/copy-assets' );
@@ -38,7 +38,7 @@ module.exports = {
38
38
 
39
39
  await buildAndWatch( options );
40
40
  } catch ( err ) {
41
- console.error( chalk.redBright( `Building documentation failed: ${ err.stack }` ) );
41
+ console.error( styleText( 'redBright', `Building documentation failed: ${ err.stack }` ) );
42
42
  process.exitCode = 1;
43
43
 
44
44
  throw err;
@@ -55,7 +55,7 @@ module.exports = {
55
55
  try {
56
56
  await buildAndWatch( options );
57
57
  } catch ( err ) {
58
- console.error( chalk.redBright( `Building documentation failed: ${ err.stack }` ) );
58
+ console.error( styleText( 'redBright', `Building documentation failed: ${ err.stack }` ) );
59
59
  process.exitCode = 1;
60
60
 
61
61
  throw err;
@@ -93,7 +93,7 @@ async function buildAndWatch( options ) {
93
93
 
94
94
  const [ time ] = process.hrtime( timer );
95
95
 
96
- console.log( chalk.greenBright( `Building documentation complete in ${ Math.floor( time / 60 ) }m ${ time % 60 }s.` ) );
96
+ console.log( styleText( 'greenBright', `Building documentation complete in ${ Math.floor( time / 60 ) }m ${ time % 60 }s.` ) );
97
97
 
98
98
  if ( options.watch ) {
99
99
  return watcher( hexoManager );
@@ -7,14 +7,15 @@
7
7
 
8
8
  const fs = require( 'fs' );
9
9
  const upath = require( 'upath' );
10
- const glob = require( 'glob' );
10
+ const { globSync } = require( 'glob' );
11
11
  const cheerio = require( 'cheerio' );
12
12
 
13
13
  const SDK_SELECTOR = 'meta[name="sdk-samples"]';
14
14
 
15
15
  module.exports = sourcePath => {
16
16
  const files = [];
17
- const filePaths = glob.sync( upath.join( sourcePath, '*.html' ) );
17
+ const filePaths = globSync( upath.join( sourcePath, '*.html' ) ).map( path => upath.normalize( path ) );
18
+
18
19
  for ( const filePath of filePaths ) {
19
20
  const content = fs.readFileSync( filePath, { encoding: 'utf8' } );
20
21
  const $ = cheerio.load( content, null, false );
@@ -22,11 +22,10 @@ const cacheFiles = require( './cache-files' );
22
22
  const overwriteApiGuides = require( './overwrite-api-guides' );
23
23
  const cacheDir = upath.join( __dirname, '../../temp/cache' );
24
24
  const validateLinks = require( './validate-links' );
25
- const createSitemap = require( './create-sitemap' );
25
+ const createSitemapStep = require( './create-sitemap-step' );
26
26
  const buildSnippets = require( './build-snippets' );
27
27
  const copyProjectIcons = require( './copy-project-icons' );
28
28
  const executeHooks = require( './execute-hooks' );
29
- const chalk = require( 'chalk' );
30
29
  const umbertoVersion = require( '../../package.json' ).version;
31
30
 
32
31
  const parseLink = require( '../../scripts/utils/parselinks' );
@@ -56,7 +55,6 @@ const getFilePatternsToProcess = require( '../helpers/get-file-patterns-to-proce
56
55
  * @param {Object} options.snippetOptions Additional options passed to snippetAdapter.
57
56
  * @param {Boolean} options.skipValidation Skip validating links.
58
57
  * @param {Boolean} options.skipGuides Skip processing guides. Useful for checking the layout changes.
59
- * @param {Boolean} options.skipSitemap Skip generating sitemap file. Useful when doing partial build.
60
58
  * @param {Boolean} options.verbose Provide more details during building documentation.
61
59
  * @param {Boolean} [options.watch] Flag which indicates that hexo should watch files.
62
60
  * @param {Array.<String>} [options.guides] An array containing names of guides that will be processed by Umberto. Useful when building
@@ -77,7 +75,6 @@ module.exports = options => {
77
75
  snippetOptions = {},
78
76
  skipValidation = false,
79
77
  skipGuides = false,
80
- skipSitemap = false,
81
78
  watch = false,
82
79
  verbose = false,
83
80
  guides = []
@@ -224,68 +221,11 @@ module.exports = options => {
224
221
  publicDir: hexoManager.getPublicDir()
225
222
  } );
226
223
  } )
227
- // Create sitemap.xml file.
228
224
  .then( async () => {
229
- let hostname;
230
- let dst = '';
231
225
  const projectConfigs = await getProjectConfigs( rootPath, projectPaths );
232
- const config = mainConfig.isSingleProject && projectConfigs && projectConfigs.length > 0 ?
233
- projectConfigs[ 0 ] : {};
234
- const sitemapConfig = mainConfig.sitemap ? mainConfig.sitemap : config.sitemap;
235
-
236
- // If available, use sitemap config from umberto-main.json.
237
- // Use sitemap config from umberto.json otherwise.
238
- if ( sitemapConfig && mainConfig.isSingleProject ) {
239
- hostname = sitemapConfig.hostname;
240
- dst = upath.join( config.slug, config.version );
241
- } else if ( sitemapConfig ) {
242
- hostname = sitemapConfig.hostname;
243
- } else {
244
- if ( verbose ) {
245
- console.log( chalk.yellow( 'Warning: ' ), 'Not enough data to create a sitemap.xml file.' );
246
- }
247
-
248
- return Promise.resolve();
249
- }
250
-
251
- // Get urls to be excluded from the sitemap.
252
- // Use excluded urls both from umberto-main.json and umberto.json.
253
- const excludedUrls = [];
254
-
255
- if ( mainConfig.sitemap && mainConfig.sitemap.excluded ) {
256
- excludedUrls.push( ...mainConfig.sitemap.excluded );
257
- }
258
-
259
- for ( const currentConfig of projectConfigs ) {
260
- if ( currentConfig.sitemap && currentConfig.sitemap.excluded ) {
261
- excludedUrls.push( ...currentConfig.sitemap.excluded );
262
- }
263
- }
264
226
 
265
- // Get extra sitemap settings per url. At the moment it's just custom priority for urls.
266
- // Use both umberto-main.json and umberto.json.
267
- const extraUrlSettings = [];
268
-
269
- if ( mainConfig.sitemap && mainConfig.sitemap.extraUrlSettings ) {
270
- extraUrlSettings.push( ...mainConfig.sitemap.extraUrlSettings );
271
- }
272
-
273
- for ( const currentConfig of projectConfigs ) {
274
- if ( currentConfig.sitemap && currentConfig.sitemap.extraUrlSettings ) {
275
- extraUrlSettings.push( ...currentConfig.sitemap.extraUrlSettings );
276
- }
277
- }
278
-
279
- if ( skipSitemap ) {
280
- return Promise.resolve();
281
- }
282
-
283
- return createSitemap( 'build/docs', hostname, dst, {
284
- excluded: excludedUrls,
285
- extraUrlSettings
286
- } );
227
+ return createSitemapStep( { projectConfigs, verbose, mainConfig } );
287
228
  } )
288
-
289
229
  .then( async () => {
290
230
  const configs = await getProjectConfigs( rootPath, projectPaths );
291
231
 
@@ -6,7 +6,7 @@
6
6
  'use strict';
7
7
 
8
8
  const upath = require( 'upath' );
9
- const glob = require( 'glob' );
9
+ const { globSync } = require( 'glob' );
10
10
  const fs = require( 'fs-extra' );
11
11
 
12
12
  /**
@@ -17,7 +17,7 @@ const fs = require( 'fs-extra' );
17
17
  * @returns {boolean}
18
18
  */
19
19
  module.exports = ( src, dst ) => {
20
- const sourcePaths = glob.sync( upath.join( src, '**', '*' ) );
20
+ const sourcePaths = globSync( upath.join( src, '**', '*' ) ).map( path => upath.normalize( path ) );
21
21
  let result = false;
22
22
 
23
23
  for ( const p of sourcePaths ) {
@@ -7,7 +7,7 @@
7
7
 
8
8
  const upath = require( 'upath' );
9
9
  const fs = require( 'fs-extra' );
10
- const glob = require( 'glob' );
10
+ const { globSync } = require( 'glob' );
11
11
  const globToRegexp = require( '../helpers/glob-to-regexp' );
12
12
 
13
13
  /**
@@ -64,10 +64,11 @@ module.exports = ( src, dst, options = {} ) => {
64
64
  // If the `src` is a path to a directory, copy files from the directory.
65
65
  const sourceGlobPath = upath.join( src, '**/*' );
66
66
 
67
- let sourceFilePaths = glob.sync( sourceGlobPath, {
67
+ let sourceFilePaths = globSync( sourceGlobPath, {
68
68
  ignore: ignored.map( ignoredPath => upath.join( src, ignoredPath ) ),
69
69
  nodir: true
70
- } );
70
+ } )
71
+ .map( path => upath.normalize( path ) );
71
72
 
72
73
  // If the `match` is an array, remove files that should not be processed.
73
74
  if ( match ) {
@@ -6,37 +6,29 @@
6
6
  'use strict';
7
7
 
8
8
  const upath = require( 'upath' );
9
- const mkdirp = require( 'mkdirp' );
10
- const copyFile = require( '../helpers/copy-file' );
9
+ const fs = require( 'fs-extra' );
11
10
 
12
11
  /**
13
- * @returns {Promise}
12
+ * @returns {Promise<void>}
14
13
  */
15
- module.exports = function copyProjectIcons( projectGlobals, buildDirectory ) {
14
+ module.exports = async function copyProjectIcons( projectGlobals, buildDirectory ) {
16
15
  const availableProjects = Object.keys( projectGlobals ).filter( projectName => projectName !== 'common' );
17
16
 
18
- let promise = Promise.resolve();
19
-
20
17
  for ( const project of availableProjects ) {
21
18
  const projectDetails = projectGlobals[ project ];
22
19
  const destinationIconsPath = upath.join( buildDirectory, projectDetails.BASE_PATH, 'assets', 'icons' );
23
20
 
24
- promise = promise.then( () => mkdirp( destinationIconsPath ) );
25
-
26
21
  for ( const [ sourceFile, destinationName ] of projectDetails._icons ) {
27
22
  const fullSourcePath = upath.join( projectDetails.config.projectRootPath, 'node_modules', sourceFile );
28
23
  const fullDestinationPath = upath.join( destinationIconsPath, destinationName );
29
24
 
30
- promise = promise.then( () => {
31
- return copyFile( fullSourcePath, fullDestinationPath )
32
- .catch( () => {
33
- console.warn(
34
- `⚠️ The "${ sourceFile }" icon cannot be copied because it does not exist in "${ fullSourcePath }".`
35
- );
36
- } );
37
- } );
25
+ try {
26
+ await fs.copy( fullSourcePath, fullDestinationPath );
27
+ } catch ( error ) {
28
+ console.warn(
29
+ `⚠️ The "${ sourceFile }" icon cannot be copied because it does not exist in "${ fullSourcePath }".`
30
+ );
31
+ }
38
32
  }
39
33
  }
40
-
41
- return promise;
42
34
  };
@@ -0,0 +1,47 @@
1
+ /**
2
+ * @license Copyright (c) 2017-2025, CKSource Holding sp. z o.o. All rights reserved.
3
+ * For licensing, see LICENSE.md.
4
+ */
5
+
6
+ const upath = require( 'upath' );
7
+ const fs = require( 'fs/promises' );
8
+
9
+ const XMLNS_STRINGS = [
10
+ 'xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"',
11
+ 'xmlns:news="http://www.google.com/schemas/sitemap-news/0.9"',
12
+ 'xmlns:xhtml="http://www.w3.org/1999/xhtml"',
13
+ 'xmlns:image="http://www.google.com/schemas/sitemap-image/1.1"',
14
+ 'xmlns:video="http://www.google.com/schemas/sitemap-video/1.1"'
15
+ ];
16
+
17
+ /**
18
+ * Creates a sitemap.xml file and saves it to build directory.
19
+ *
20
+ * @param {Object} options
21
+ * @param {String} options.buildPath Path to the build directory.
22
+ * @param {String} options.hostname Hostname of the website where the documentation will be hosted.
23
+ * @param {Array.<string>} options.sitemapPaths Paths to generated sitemap files.
24
+ * @returns {Promise}
25
+ */
26
+ module.exports = ( { buildPath, hostname, sitemapPaths } ) => {
27
+ const sitemapPath = upath.resolve( upath.join( buildPath, 'sitemap.xml' ) );
28
+ const sitemapIndexContent = [
29
+ '<?xml version="1.0" encoding="UTF-8"?>',
30
+ `<sitemapindex ${ XMLNS_STRINGS.join( ' ' ) }>`,
31
+
32
+ ...sitemapPaths.map( sitemapPath => {
33
+ const relativePath = sitemapPath.split( buildPath ).pop().replace( /^\/+/, '' );
34
+ const fullUrl = new URL( relativePath, hostname.endsWith( '/' ) ? hostname : hostname + '/' );
35
+
36
+ return [
37
+ '<sitemap>',
38
+ `<loc>${ fullUrl.toString() }</loc>`,
39
+ '</sitemap>'
40
+ ];
41
+ } ),
42
+
43
+ '</sitemapindex>'
44
+ ].flat().join( '' );
45
+
46
+ return fs.writeFile( sitemapPath, sitemapIndexContent, 'utf8' );
47
+ };
@@ -0,0 +1,106 @@
1
+ /**
2
+ * @license Copyright (c) 2017-2025, CKSource Holding sp. z o.o. All rights reserved.
3
+ * For licensing, see LICENSE.md.
4
+ */
5
+
6
+ const { styleText } = require( 'util' );
7
+ const createSitemap = require( './create-sitemap' );
8
+ const createSitemapIndex = require( './create-sitemap-index' );
9
+
10
+ const BUILD_PATH = 'build/docs';
11
+
12
+ /**
13
+ * This build step handles sitemap building.
14
+ *
15
+ * @param {Object} options
16
+ * @param {Object} options.mainConfig
17
+ * @param {Object} options.projectConfigs
18
+ * @param {Object} options.verbose
19
+ */
20
+ module.exports = async function createSitemapStep( { mainConfig, projectConfigs, verbose } ) {
21
+ if ( mainConfig.isSingleProject ) {
22
+ // If available, use sitemap config from umberto-main.json.
23
+ // Use sitemap config from umberto.json otherwise.
24
+ const config = projectConfigs && projectConfigs.length > 0 ? projectConfigs[ 0 ] : {};
25
+ const sitemapConfig = mainConfig.sitemap ? mainConfig.sitemap : config.sitemap;
26
+
27
+ if ( !sitemapConfig ) {
28
+ return missingSitemapWarning( verbose );
29
+ }
30
+
31
+ if ( !sitemapConfig.enabled ) {
32
+ if ( verbose ) {
33
+ console.log(
34
+ styleText( 'yellow', 'Warning: ' ),
35
+ 'To enable generating a sitemap.xml file, add the "enabled: true" property to "sitemap" configuration.'
36
+ );
37
+ }
38
+
39
+ return;
40
+ }
41
+
42
+ return createSitemap( {
43
+ buildPath: BUILD_PATH,
44
+ projectSlug: config.slug,
45
+ projectVersion: config.version,
46
+ hostname: sitemapConfig.hostname,
47
+ excluded: sitemapConfig.excluded || []
48
+ } );
49
+ }
50
+
51
+ if ( !mainConfig.sitemap ) {
52
+ return missingSitemapWarning( verbose );
53
+ }
54
+
55
+ const { hostname } = mainConfig.sitemap;
56
+
57
+ const promises = projectConfigs.map( projectConfig => {
58
+ const excluded = [];
59
+
60
+ if ( mainConfig.sitemap?.excluded ) {
61
+ excluded.push( ...mainConfig.sitemap.excluded );
62
+ }
63
+
64
+ if ( projectConfig.sitemap?.excluded ) {
65
+ excluded.push( ...projectConfig.sitemap.excluded );
66
+ }
67
+
68
+ return createSitemap( {
69
+ hostname,
70
+ projectSlug: projectConfig.slug,
71
+ projectVersion: projectConfig.version,
72
+ buildPath: BUILD_PATH,
73
+ excluded
74
+ } );
75
+ } );
76
+
77
+ const sitemapPaths = await Promise.all( promises );
78
+
79
+ // Generate the sitemap index only if all projects are being built.
80
+ if ( !mainConfig.ignoredProjects.length ) {
81
+ // To collect the HTML files from the build root directory.
82
+ const rootSitemap = await createSitemap( {
83
+ buildPath: BUILD_PATH,
84
+ hostname,
85
+ excluded: mainConfig.sitemap?.excluded || [],
86
+ fileName: 'sitemap-root.xml'
87
+ } );
88
+
89
+ await createSitemapIndex( {
90
+ buildPath: BUILD_PATH,
91
+ hostname,
92
+ sitemapPaths: [
93
+ rootSitemap,
94
+ ...sitemapPaths
95
+ ]
96
+ } );
97
+ }
98
+ };
99
+
100
+ function missingSitemapWarning( verbose ) {
101
+ if ( !verbose ) {
102
+ return;
103
+ }
104
+
105
+ console.log( styleText( 'yellow', 'Warning: ' ), 'Not enough data to create a sitemap.xml file.' );
106
+ }
@@ -5,53 +5,64 @@
5
5
 
6
6
  'use strict';
7
7
 
8
+ const fs = require( 'fs' );
9
+ const { globSync } = require( 'glob' );
8
10
  const upath = require( 'upath' );
9
- const glob = require( 'glob' );
11
+ const { URL } = require( 'url' );
10
12
  const { SitemapStream, streamToPromise } = require( 'sitemap' );
11
- const fs = require( 'fs' );
12
13
 
13
14
  /**
14
15
  * Creates a sitemap.xml file and saves it to build directory.
15
16
  *
16
- * @param {String} buildPath Path to the build directory.
17
- * @param {String} hostname Hostname of the website where the documentation will be hosted.
18
- * @param {String} dst Additional path in the build directory where to save the sitemap.xml.
19
- * @param {Object} options Additional options.
20
- * @param {Array.<String>} options.excludedUrls An array of urls to be excluded from the sitemap.
21
- * @param {Array.<Object>} options.extraUrlSettings An array of config objects per url. Currently used to set custom priority per url.
22
- * @returns {Promise}
17
+ * @param {Object} options
18
+ * @param {String} options.fileName
19
+ * @param {String} options.projectSlug
20
+ * @param {String} options.projectVersion
21
+ * @param {String} options.buildPath Path to the build directory.
22
+ * @param {String} options.hostname Hostname of the website where the documentation will be hosted.
23
+ * @param {Array.<String>} options.excluded An array of urls to be excluded from the sitemap.
24
+ * @returns {Promise.<string>} Path to the generated sitemap.
23
25
  */
24
- module.exports = ( buildPath, hostname, dst = '', options = {} ) => {
25
- const pattern = upath.join( buildPath, '**', '*.html' );
26
- const pathsToFiles = glob.sync( pattern );
27
- const sitemap = new SitemapStream( {
26
+ module.exports = options => {
27
+ const {
28
+ fileName = 'sitemap.xml',
29
+ projectSlug,
30
+ projectVersion,
31
+ buildPath,
28
32
  hostname,
33
+ excluded = []
34
+ } = options;
35
+
36
+ // The `sitemap` package expects that `hostname` will not include subdirectories.
37
+ // Let's split it and glue the destination URL manually.
38
+ const { origin, pathname } = new URL( hostname );
39
+
40
+ const { pattern, sitemapPath } = getSitemapData( { buildPath, projectSlug, fileName } );
41
+ const sitemap = new SitemapStream( {
42
+ hostname: origin,
29
43
  cacheTime: 600000
30
44
  } );
31
45
 
32
- for ( const filePath of pathsToFiles ) {
33
- const urlForSitemap = filePath.replace( buildPath, 'docs' ).replace( /(\/[^/]+\/)[^/]+\//, '$1latest/' );
34
- const excludedUrls = options.excluded || [];
35
- const extraUrlSettings = options.extraUrlSettings || [];
46
+ const pathToFiles = globSync( pattern ).map( path => upath.normalize( path ) );
47
+
48
+ for ( const filePath of pathToFiles ) {
49
+ let urlForSitemap = filePath.replace( buildPath, upath.normalizeTrim( pathname ) );
50
+
51
+ if ( projectVersion ) {
52
+ urlForSitemap = urlForSitemap.replace( `/${ projectVersion }/`, '/latest/' );
53
+ }
36
54
 
37
55
  if ( filePath.endsWith( '404.html' ) ) {
38
56
  continue;
39
57
  }
40
58
 
41
- if ( excludedUrls.find( excluded => filePath.includes( excluded ) ) ) {
59
+ if ( excluded.find( excluded => filePath.includes( excluded ) ) ) {
42
60
  continue;
43
61
  }
44
62
 
45
- const extraUrlSetting = extraUrlSettings.find( setting => filePath.includes( setting.url ) );
46
- const sitemapItem = {
63
+ sitemap.write( {
47
64
  url: urlForSitemap
48
- };
49
-
50
- if ( extraUrlSetting && extraUrlSetting.priority ) {
51
- sitemapItem.priority = Math.min( extraUrlSetting.priority, 1.0 );
52
- }
53
-
54
- sitemap.write( sitemapItem );
65
+ } );
55
66
  }
56
67
 
57
68
  sitemap.end();
@@ -59,13 +70,23 @@ module.exports = ( buildPath, hostname, dst = '', options = {} ) => {
59
70
  return streamToPromise( sitemap )
60
71
  .then( data => {
61
72
  return new Promise( ( resolve, reject ) => {
62
- fs.writeFile( upath.resolve( upath.join( buildPath, dst, 'sitemap.xml' ) ), data.toString(), err => {
73
+ fs.writeFile( sitemapPath, data.toString(), err => {
63
74
  if ( err ) {
64
75
  return reject( err );
65
76
  }
66
77
 
67
- return resolve();
78
+ return resolve( sitemapPath );
68
79
  } );
69
80
  } );
70
81
  } );
71
82
  };
83
+
84
+ function getSitemapData( { buildPath, projectSlug, fileName } ) {
85
+ return {
86
+ pattern: projectSlug ? upath.join( buildPath, projectSlug, '**', '*.html' ) : upath.join( buildPath, '*.html' ),
87
+
88
+ sitemapPath: upath.resolve(
89
+ projectSlug ? upath.join( buildPath, projectSlug, fileName ) : upath.join( buildPath, fileName )
90
+ )
91
+ };
92
+ }
@@ -5,10 +5,10 @@
5
5
 
6
6
  'use strict';
7
7
 
8
- const getProjectConfig = require( './get-project-config' );
9
- const upath = require( 'upath' );
8
+ const { styleText } = require( 'util' );
10
9
  const fs = require( 'fs' );
11
- const chalk = require( 'chalk' );
10
+ const upath = require( 'upath' );
11
+ const getProjectConfig = require( './get-project-config' );
12
12
 
13
13
  module.exports = async ( {
14
14
  mainConfig,
@@ -34,16 +34,16 @@ module.exports = async ( {
34
34
 
35
35
  return Promise.resolve();
36
36
 
37
- function createSymbolicLink( config ) {
38
- const destinationPath = upath.join( rootPath, 'build', 'docs', config.slug, 'latest' );
37
+ function createSymbolicLink( { slug, name, version } ) {
38
+ const destinationPath = upath.join( rootPath, 'build', 'docs', slug, 'latest' );
39
39
 
40
40
  if ( !fs.existsSync( destinationPath ) ) {
41
41
  // The 3rd argument to the fs.symlinkSync() method is the link type and it is only available
42
42
  // on Windows (it is ignored on other platforms). Creating a symlink to a directory with link
43
43
  // type = 'dir' requires admin privileges on Windows. The only way to create a directory symlink
44
44
  // without admin privileges on Windows is to use the 'junction' link type.
45
- fs.symlinkSync( config.version, destinationPath, 'junction' );
46
- console.log( `Symlink for ${ chalk.cyanBright( config.name ) } ${ chalk.magentaBright( './' + config.version ) } - created. ` );
45
+ fs.symlinkSync( version, destinationPath, 'junction' );
46
+ console.log( `Symlink for ${ styleText( 'cyanBright', name ) } ${ styleText( 'magentaBright', './' + version ) } - created.` );
47
47
  }
48
48
  }
49
49
  };
@@ -7,7 +7,7 @@
7
7
 
8
8
  const upath = require( 'upath' );
9
9
  const fs = require( 'fs' );
10
- const glob = require( 'glob' );
10
+ const { globSync } = require( 'glob' );
11
11
  const importModule = require( '../helpers/import-module' );
12
12
 
13
13
  const cache = new Map();
@@ -369,7 +369,8 @@ function getPackagesPathsInfo( rootPath, slug, directory ) {
369
369
  // CKEditor 5 can have packages that do not start with `ckeditor5-` prefix.
370
370
  const slugOrRegExp = slug === 'ckeditor5' ? /ckeditor5?-/ : `${ slug }-`;
371
371
 
372
- return glob.sync( upath.resolve( rootPath, directory ) )
372
+ return globSync( upath.resolve( rootPath, directory ) )
373
+ .map( p => upath.normalize( p ) )
373
374
  .map( p => {
374
375
  const relativePath = p.replace( rootPath + '/', '' );
375
376
 
@@ -6,7 +6,7 @@
6
6
  'use strict';
7
7
 
8
8
  const upath = require( 'upath' );
9
- const glob = require( 'glob' );
9
+ const { globSync } = require( 'glob' );
10
10
  const fs = require( 'fs-extra' );
11
11
 
12
12
  /**
@@ -17,7 +17,7 @@ const fs = require( 'fs-extra' );
17
17
  * @param dst
18
18
  */
19
19
  module.exports = ( src, dst ) => {
20
- const sourcePaths = glob.sync( upath.join( src, '**', '*' ) );
20
+ const sourcePaths = globSync( upath.join( src, '**', '*' ) ).map( path => upath.normalize( path ) );
21
21
 
22
22
  for ( const p of sourcePaths ) {
23
23
  const strippedPath = p.replace( src, '' );
@@ -7,7 +7,7 @@
7
7
 
8
8
  const upath = require( 'upath' );
9
9
  const fs = require( 'fs' );
10
- const glob = require( 'glob' );
10
+ const { globSync } = require( 'glob' );
11
11
  const DOC_FORMATS = require( '../helpers/doc-formats' );
12
12
 
13
13
  /**
@@ -18,7 +18,7 @@ const DOC_FORMATS = require( '../helpers/doc-formats' );
18
18
  * @returns {Array}
19
19
  */
20
20
  module.exports = ( sourcePath, type ) => {
21
- const fileNames = glob.sync( upath.join( sourcePath, `**/*.${ DOC_FORMATS[ type ] }` ) );
21
+ const fileNames = globSync( upath.join( sourcePath, `**/*.${ DOC_FORMATS[ type ] }` ) ).map( path => upath.normalize( path ) );
22
22
  const files = [];
23
23
 
24
24
  for ( const fileName of fileNames ) {
@@ -5,15 +5,15 @@
5
5
 
6
6
  'use strict';
7
7
 
8
+ const { styleText } = require( 'util' );
8
9
  const upath = require( 'upath' );
9
10
  const fs = require( 'fs-extra' );
10
- const glob = require( 'glob' );
11
- const chalk = require( 'chalk' );
11
+ const { globSync } = require( 'glob' );
12
12
  const { parseDocument } = require( 'htmlparser2' );
13
13
 
14
14
  module.exports = ( buildPath, options = {} ) => {
15
15
  const pattern = upath.join( buildPath, '**', '*' );
16
- let pathsToFiles = glob.sync( pattern );
16
+ let pathsToFiles = globSync( pattern ).map( path => upath.normalize( path ) );
17
17
 
18
18
  const links = new Set();
19
19
 
@@ -108,10 +108,13 @@ module.exports = ( buildPath, options = {} ) => {
108
108
 
109
109
  if ( invalidHrefs.size ) {
110
110
  process.exitCode = 1;
111
- console.log( `${ chalk.red( 'Error: ' ) }Invalid internal links in ${ chalk.magenta( filePath.replace( buildPath, '' ) ) }:` );
111
+ console.log(
112
+ styleText( 'red', 'Error: ' ) +
113
+ `Invalid internal links in ${ styleText( 'magenta', filePath.replace( buildPath, '' ) ) }:`
114
+ );
112
115
 
113
116
  for ( const url of invalidHrefs ) {
114
- console.log( chalk.gray( ` * '${ url.href }' - ${ url.text.replace( /\s+/g, ' ' ) }` ) );
117
+ console.log( styleText( 'gray', ` * '${ url.href }' - ${ url.text.replace( /\s+/g, ' ' ) }` ) );
115
118
  }
116
119
  }
117
120
  }
@@ -5,24 +5,27 @@
5
5
 
6
6
  'use strict';
7
7
 
8
+ const { styleText } = require( 'util' );
8
9
  const upath = require( 'upath' );
9
- const cpx = require( 'cpx' );
10
- const chalk = require( 'chalk' );
10
+ const chokidar = require( 'chokidar' );
11
+ const { copy } = require( 'fs-extra' );
11
12
 
12
- module.exports = hexoManager => new Promise( resolve => {
13
- console.log( chalk.yellow( 'Umberto is in watch mode press CTRL+C to exit.' ) );
14
- const originPaths = hexoManager.getOriginPaths();
13
+ module.exports = function watchMd( hexoManager ) {
14
+ console.log( styleText( 'yellow', 'Umberto is in watch mode press CTRL+C to exit.' ) );
15
15
 
16
- for ( const item of originPaths ) {
17
- const path1 = upath.join( item.originPath, '*.md' );
18
- const path2 = upath.join( item.originPath, '**', '*.md' );
19
-
20
- cpx.watch( path1, item.dstPath, { initialCopy: false } );
21
- cpx.watch( path2, item.dstPath, { initialCopy: false } );
16
+ for ( const { originPath, dstPath } of hexoManager.getOriginPaths() ) {
17
+ chokidar
18
+ .watch( originPath, {
19
+ ignoreInitial: true,
20
+ ignored: ( path, stats ) => stats?.isFile() && !path.endsWith( '.md' )
21
+ } )
22
+ .on( 'add', file => copyFile( originPath, dstPath, file ) )
23
+ .on( 'change', file => copyFile( originPath, dstPath, file ) );
22
24
  }
25
+ };
26
+
27
+ function copyFile( originPath, dstPath, file ) {
28
+ const dest = upath.join( dstPath, upath.relative( originPath, file ) );
23
29
 
24
- process.on( 'SIGINT', function() {
25
- resolve();
26
- process.exit();
27
- } );
28
- } );
30
+ return copy( file, dest );
31
+ }
@@ -5,8 +5,7 @@
5
5
 
6
6
  'use strict';
7
7
 
8
- const fs = require( 'fs' );
9
- const mkdirp = require( 'mkdirp' );
8
+ const fs = require( 'fs-extra' );
10
9
  const upath = require( 'upath' );
11
10
 
12
11
  /**
@@ -14,29 +13,15 @@ const upath = require( 'upath' );
14
13
  *
15
14
  * @param {Array.<HtmlFile>} files HtmlFile objects containing content to be written to .html files to file system.
16
15
  * @param {String} destinationDir Additional destination path. Additional because files already have its own path.
17
- * @returns {Promise}
16
+ * @returns {Promise<void>}
18
17
  */
19
- module.exports = ( files, destinationDir = '.' ) => {
20
- const promises = [];
21
-
22
- for ( const file of files ) {
23
- const fileDir = upath.join( destinationDir, file.dirname );
24
-
25
- const promise = mkdirp( upath.resolve( fileDir ) )
26
- .then( () => {
27
- return new Promise( ( resolve, reject ) => {
28
- fs.writeFile( upath.join( fileDir, file.basename ), file.content, err => {
29
- if ( err ) {
30
- return reject( err );
31
- }
32
-
33
- return resolve();
34
- } );
35
- } );
36
- } );
37
-
38
- promises.push( promise );
39
- }
40
-
41
- return Promise.all( promises );
18
+ module.exports = async ( files, destinationDir = '.' ) => {
19
+ const writePromises = files.map( file =>
20
+ fs.outputFile(
21
+ upath.join( destinationDir, file.dirname, file.basename ),
22
+ file.content
23
+ )
24
+ );
25
+
26
+ return Promise.all( writePromises );
42
27
  };
@@ -15,7 +15,7 @@ const splitLongname = require( '../helpers/split-longname' );
15
15
  const extractLongname = require( '../helpers/extract-longname' );
16
16
  const getApiInfoboxTooltip = require( '../helpers/get-api-infobox-tooltip' );
17
17
  const capitalize = require( '../helpers/capitalize' );
18
- const relative_url = require( 'hexo/lib/plugins/helper/relative_url' ); // eslint-disable-line camelcase
18
+ const relative_url = require( 'hexo/dist/plugins/helper/relative_url' ); // eslint-disable-line camelcase
19
19
 
20
20
  /**
21
21
  * Provides pug templates and adds various helpers to them.
@@ -3,11 +3,6 @@
3
3
  * For licensing, see LICENSE.md.
4
4
  */
5
5
 
6
- // Polyfill for `window.Symbol`.
7
- import '@babel/polyfill';
8
- // Polyfill for `Element.closest()`.
9
- import 'element-closest/browser';
10
-
11
6
  import $ from 'jquery';
12
7
  import { setupPrism } from './_prism';
13
8
  import { enableCollapsables, hideTogglers } from './_collapsables';
@@ -3,11 +3,6 @@
3
3
  * For licensing, see LICENSE.md.
4
4
  */
5
5
 
6
- // Polyfill for `window.Symbol`.
7
- import '@babel/polyfill';
8
- // Polyfill for `Element.closest()`.
9
- import 'element-closest/browser';
10
-
11
6
  import $ from 'jquery';
12
7
  import { setupPrism } from './_prism';
13
8
  import { enableCollapsables, hideTogglers } from './_collapsables';
@@ -1,34 +0,0 @@
1
- /**
2
- * @license Copyright (c) 2017-2025, CKSource Holding sp. z o.o. All rights reserved.
3
- * For licensing, see LICENSE.md.
4
- */
5
-
6
- 'use strict';
7
-
8
- const fs = require( 'fs' );
9
-
10
- /**
11
- * Copies a specified file from the `source` path to the `destination` path.
12
- *
13
- * @param {String} source
14
- * @param {String} destination
15
- * @return {Promise}
16
- */
17
- module.exports = function copyFile( source, destination ) {
18
- return new Promise( ( resolve, reject ) => {
19
- const readStream = fs.createReadStream( source );
20
-
21
- // In order to catch an error if `source` points to non-existing file, we need to wait for
22
- // the `#open` event emitted by the read readStream.
23
- readStream.on( 'open', () => {
24
- const writeStream = fs.createWriteStream( destination );
25
-
26
- readStream.pipe( writeStream );
27
-
28
- writeStream.on( 'error', reject );
29
- writeStream.on( 'finish', resolve );
30
- } );
31
-
32
- readStream.on( 'error', reject );
33
- } );
34
- };