umberto 9.3.0 → 9.4.0
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 +16 -7
- package/package.json +1 -1
- package/src/api-builder/api-builder.js +56 -3
- package/src/api-builder/classes/navigation-tree.js +1 -1
- package/src/hexo/filter/project-locals.js +76 -2
- package/src/tasks/build-documentation.js +17 -5
- package/src/tasks/get-project-config.js +5 -0
- package/themes/umberto/layout/gloria/_api-docs/_mixin/_api-tree-item.pug +18 -1
- package/themes/umberto/layout/gloria/_head/head.pug +5 -0
- package/themes/umberto/layout/umberto/_partial/head.pug +5 -0
- package/themes/umberto/src/gloria/css/components/_api-tree.scss +4 -0
- package/themes/umberto/src/gloria/js/components/api-nav-tree.js +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,22 @@
|
|
|
1
1
|
Changelog
|
|
2
2
|
=========
|
|
3
3
|
|
|
4
|
+
## [9.4.0](https://github.com/cksource/umberto/compare/v9.3.0...v9.4.0) (February 2, 2026)
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* Introduced configuration option to prevent selected project pages from being indexed by search engines. For these projects, the build injects `<meta name="robots" content="noindex, nofollow">` into the page `<head>`.
|
|
9
|
+
|
|
10
|
+
* When using `buildSingleProject()`, set the `shouldInjectNoIndexMeta` option in `umberto.json`:
|
|
11
|
+
`"shouldInjectNoIndexMeta": true`
|
|
12
|
+
* When using `buildMultiProjects()`, set the `nonIndexableProjects` option in `umberto-main.json` using the paths of projects that should not be indexed, e.g.:
|
|
13
|
+
`"nonIndexableProjects": [ "projects-external/ckeditor5-commercial/external/ckeditor5", "projects/trial" ]`
|
|
14
|
+
|
|
15
|
+
### Other changes
|
|
16
|
+
|
|
17
|
+
* Reduced the size of API docs sidebars by only rendering the full navigation tree for the current package. Other packages now link to their landing pages, significantly lowering total link count and improving build size and performance.
|
|
18
|
+
|
|
19
|
+
|
|
4
20
|
## [9.3.0](https://github.com/cksource/umberto/compare/v9.2.0...v9.3.0) (January 27, 2026)
|
|
5
21
|
|
|
6
22
|
### Features
|
|
@@ -47,13 +63,6 @@ Changelog
|
|
|
47
63
|
* Minification should preserve closing tags and output spec-compliant HTML.
|
|
48
64
|
* Fix encoding of SDK sources.
|
|
49
65
|
|
|
50
|
-
|
|
51
|
-
## [9.1.1](https://github.com/cksource/umberto/compare/v9.1.0...v9.1.1) (November 25, 2025)
|
|
52
|
-
|
|
53
|
-
### Other changes
|
|
54
|
-
|
|
55
|
-
* Added support for the `environment` field in Sentry configuration.
|
|
56
|
-
|
|
57
66
|
---
|
|
58
67
|
|
|
59
68
|
To see all releases, visit the [release page](https://github.com/cksource/umberto/releases).
|
package/package.json
CHANGED
|
@@ -151,6 +151,7 @@ module.exports = class ApiBuilder {
|
|
|
151
151
|
} );
|
|
152
152
|
|
|
153
153
|
this._navTreeHtml = '';
|
|
154
|
+
this._navTreeHtmlByPackage = {};
|
|
154
155
|
this._filterHtml = '';
|
|
155
156
|
|
|
156
157
|
/**
|
|
@@ -255,6 +256,15 @@ module.exports = class ApiBuilder {
|
|
|
255
256
|
return this._navTreeHtml;
|
|
256
257
|
}
|
|
257
258
|
|
|
259
|
+
/**
|
|
260
|
+
* Get HTML of API navigation tree by package name.
|
|
261
|
+
*
|
|
262
|
+
* @returns {Object}
|
|
263
|
+
*/
|
|
264
|
+
getNavTreeByPackage() {
|
|
265
|
+
return Object.assign( {}, this._navTreeHtmlByPackage );
|
|
266
|
+
}
|
|
267
|
+
|
|
258
268
|
/**
|
|
259
269
|
* Get HTML of API error codes.
|
|
260
270
|
* @returns {String}
|
|
@@ -385,13 +395,55 @@ module.exports = class ApiBuilder {
|
|
|
385
395
|
}
|
|
386
396
|
}
|
|
387
397
|
|
|
388
|
-
this._navTreeHtml = this.
|
|
398
|
+
this._navTreeHtml = this._renderNavTreeHtml();
|
|
399
|
+
this._navTreeHtmlByPackage = this._buildNavTreeHtmlByPackage();
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
/**
|
|
403
|
+
* Renders API navigation tree HTML.
|
|
404
|
+
*
|
|
405
|
+
* @param {String|null} activeApiPackage Package name used to expand its subtree.
|
|
406
|
+
* @returns {String}
|
|
407
|
+
*/
|
|
408
|
+
_renderNavTreeHtml( activeApiPackage = null ) {
|
|
409
|
+
return this._tmplCol.renderTemplate( '_partial/navtree', {
|
|
389
410
|
projectLocals: {
|
|
390
411
|
apiTree: this._navTree
|
|
391
|
-
}
|
|
412
|
+
},
|
|
413
|
+
activeApiPackage
|
|
392
414
|
} );
|
|
393
415
|
}
|
|
394
416
|
|
|
417
|
+
/**
|
|
418
|
+
* Builds an object of API navigation tree HTML keyed by package name.
|
|
419
|
+
*
|
|
420
|
+
* @returns {Object}
|
|
421
|
+
*/
|
|
422
|
+
_buildNavTreeHtmlByPackage() {
|
|
423
|
+
const htmlByPackage = {};
|
|
424
|
+
const rootChildren = this._navTree.getTree().getChildren();
|
|
425
|
+
|
|
426
|
+
if ( !Array.isArray( rootChildren ) || rootChildren.length === 0 ) {
|
|
427
|
+
return htmlByPackage;
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
for ( const child of rootChildren ) {
|
|
431
|
+
if ( child.getProp( 'type' ) !== this._navTree.NODE_TYPES.PACKAGE ) {
|
|
432
|
+
continue;
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
const packageName = child.getProp( 'name' );
|
|
436
|
+
|
|
437
|
+
if ( !packageName ) {
|
|
438
|
+
continue;
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
htmlByPackage[ packageName ] = this._renderNavTreeHtml( packageName );
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
return htmlByPackage;
|
|
445
|
+
}
|
|
446
|
+
|
|
395
447
|
/**
|
|
396
448
|
* Renders HTML of each API docs page and creates an HtmlFile instance for that page.
|
|
397
449
|
*/
|
|
@@ -412,6 +464,7 @@ module.exports = class ApiBuilder {
|
|
|
412
464
|
const shortModulePath = getShortModulePath( data.longname );
|
|
413
465
|
const split = splitLongname( data.longname );
|
|
414
466
|
const splitParts = [ split.packageName, ...split.directoryNames ];
|
|
467
|
+
const navTreeHtml = this._navTreeHtmlByPackage[ split.packageName ] || this._navTreeHtml;
|
|
415
468
|
const realImportPath = typeof this._getRealImportPath === 'function' ? this._getRealImportPath( shortModulePath ) : '';
|
|
416
469
|
|
|
417
470
|
let title;
|
|
@@ -498,7 +551,7 @@ module.exports = class ApiBuilder {
|
|
|
498
551
|
jobs.push(
|
|
499
552
|
pool.run( {
|
|
500
553
|
content: view.content,
|
|
501
|
-
navTreeHtml
|
|
554
|
+
navTreeHtml,
|
|
502
555
|
outputPath: upath.join( view.dirname, view.basename ),
|
|
503
556
|
themeDir: hexoManager.hexo.theme_dir
|
|
504
557
|
} )
|
|
@@ -10,6 +10,66 @@ const getPageGroupHelper = require( '../helper/get-page-group' );
|
|
|
10
10
|
const getDocSearchConfig = require( '../../helpers/get-docsearch-config' );
|
|
11
11
|
const umbertoVersion = require( '../../../package.json' ).version;
|
|
12
12
|
|
|
13
|
+
/**
|
|
14
|
+
* Resolves the API package name from a docs path.
|
|
15
|
+
*
|
|
16
|
+
* @param {Object} params
|
|
17
|
+
* @param {String} params.path
|
|
18
|
+
* @param {String} params.basePath
|
|
19
|
+
* @param {String|null} params.apiSlug
|
|
20
|
+
* @returns {String|null}
|
|
21
|
+
*/
|
|
22
|
+
function getApiPackageFromPath( { path, basePath, apiSlug } ) {
|
|
23
|
+
if ( !apiSlug ) {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const apiBasePath = upath.join( basePath, apiSlug );
|
|
28
|
+
const normalizedPath = upath.normalize( path );
|
|
29
|
+
|
|
30
|
+
if ( normalizedPath !== apiBasePath && !normalizedPath.startsWith( `${ apiBasePath }/` ) ) {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const firstSegment = normalizedPath
|
|
35
|
+
.slice( apiBasePath.length )
|
|
36
|
+
.replace( /^\/+/, '' )
|
|
37
|
+
.split( '/' )[ 0 ];
|
|
38
|
+
|
|
39
|
+
if ( !firstSegment || firstSegment === 'index.html' ) {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const packageName = firstSegment.replace( /\.html$/, '' );
|
|
44
|
+
|
|
45
|
+
return packageName === 'index' ? null : packageName;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Chooses the API tree HTML based on current page context.
|
|
50
|
+
*
|
|
51
|
+
* @param {Object} params
|
|
52
|
+
* @param {String} params.path
|
|
53
|
+
* @param {String} params.basePath
|
|
54
|
+
* @param {String|null} params.apiSlug
|
|
55
|
+
* @param {String} params.navTree
|
|
56
|
+
* @param {Object} params.navTreeByPackage
|
|
57
|
+
* @returns {String}
|
|
58
|
+
*/
|
|
59
|
+
function getApiTreeHtml( { path, basePath, apiSlug, navTree, navTreeByPackage } ) {
|
|
60
|
+
if ( !navTreeByPackage || Object.keys( navTreeByPackage ).length === 0 ) {
|
|
61
|
+
return navTree;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const apiPackage = getApiPackageFromPath( { path, basePath, apiSlug } );
|
|
65
|
+
|
|
66
|
+
if ( apiPackage && navTreeByPackage[ apiPackage ] ) {
|
|
67
|
+
return navTreeByPackage[ apiPackage ];
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return navTree;
|
|
71
|
+
}
|
|
72
|
+
|
|
13
73
|
/**
|
|
14
74
|
* Adds various project data as hexo locals available in templates.
|
|
15
75
|
*
|
|
@@ -27,6 +87,7 @@ const umbertoVersion = require( '../../../package.json' ).version;
|
|
|
27
87
|
* @param {Array} extraStylePaths Paths to extra external css.
|
|
28
88
|
* @param {Array} extraScriptsPaths Paths to extra external js.
|
|
29
89
|
* @param {Boolean} disableSearch Extra flag for disabling docsearch if needed.
|
|
90
|
+
* @param {Boolean} shouldInjectNoIndexMeta Whether the "do not index" header for bots should be included.
|
|
30
91
|
* @param {Array} quickNavigationProjects Projects to display in the quick navigation dropdown.
|
|
31
92
|
* @param {Boolean} navigationShowEmptyCategories If set on true, empty categories will be displayed.
|
|
32
93
|
* @param {Object} og Open Graph config.
|
|
@@ -46,6 +107,7 @@ module.exports = ( ctx, {
|
|
|
46
107
|
extraStylePaths,
|
|
47
108
|
extraScriptsPaths,
|
|
48
109
|
disableSearch,
|
|
110
|
+
shouldInjectNoIndexMeta,
|
|
49
111
|
og,
|
|
50
112
|
quickNavigationProjects,
|
|
51
113
|
navigationShowEmptyCategories
|
|
@@ -63,10 +125,18 @@ module.exports = ( ctx, {
|
|
|
63
125
|
return g;
|
|
64
126
|
} );
|
|
65
127
|
|
|
128
|
+
const apiTree = getApiTreeHtml( {
|
|
129
|
+
path: locals.path,
|
|
130
|
+
basePath,
|
|
131
|
+
apiSlug: groupsModified.find( g => g.id === 'api-reference' )?.slug ?? null,
|
|
132
|
+
navTree: ctx.projectGlobals[ projectSlug ].config.navTree,
|
|
133
|
+
navTreeByPackage: ctx.projectGlobals[ projectSlug ].config.navTreeByPackage
|
|
134
|
+
} );
|
|
135
|
+
|
|
66
136
|
locals.projectLocals = {
|
|
67
137
|
groups: groupsModified,
|
|
68
138
|
getPageGroup: getPageGroupHelper( groupsModified ),
|
|
69
|
-
apiTree
|
|
139
|
+
apiTree,
|
|
70
140
|
sdkNavTree: ctx.projectGlobals[ projectSlug ].config.sdkNavTree,
|
|
71
141
|
latestBasePath: upath.join( projectSlug, 'latest' ),
|
|
72
142
|
extraStylePaths,
|
|
@@ -85,7 +155,10 @@ module.exports = ( ctx, {
|
|
|
85
155
|
};
|
|
86
156
|
}
|
|
87
157
|
|
|
88
|
-
//
|
|
158
|
+
// ⚠️ WARNING ⚠️
|
|
159
|
+
// Following locals are the same for all projects. Each project overwrites previous ones.
|
|
160
|
+
// For unique values, use`projectLocals` or `projectsData`.
|
|
161
|
+
|
|
89
162
|
if ( !locals.projectsData ) {
|
|
90
163
|
locals.projectsData = [];
|
|
91
164
|
}
|
|
@@ -94,6 +167,7 @@ module.exports = ( ctx, {
|
|
|
94
167
|
locals.projectsData.push( {
|
|
95
168
|
name: projectName,
|
|
96
169
|
slug: projectSlug,
|
|
170
|
+
shouldInjectNoIndexMeta,
|
|
97
171
|
BASE_PATH: upath.join( projectSlug, config.version ),
|
|
98
172
|
latestBasePath: upath.join( projectSlug, 'latest' ),
|
|
99
173
|
startPage: config.startPage ? '/' + config.startPage : '/index.html'
|
|
@@ -131,7 +131,7 @@ module.exports = options => {
|
|
|
131
131
|
} );
|
|
132
132
|
} )
|
|
133
133
|
.then( async () => {
|
|
134
|
-
const configs = await getProjectConfigs( rootPath, projectPaths, { skipLiveSnippets } );
|
|
134
|
+
const configs = await getProjectConfigs( rootPath, projectPaths, { ...mainConfig, skipLiveSnippets } );
|
|
135
135
|
|
|
136
136
|
return executeHooks( configs, 'beforeHexo' );
|
|
137
137
|
} )
|
|
@@ -143,6 +143,8 @@ module.exports = options => {
|
|
|
143
143
|
dev,
|
|
144
144
|
docSearch: mainConfig.docsearch,
|
|
145
145
|
disableSearch: mainConfig.docsearch === false,
|
|
146
|
+
shouldInjectNoIndexMeta: mainConfig.shouldInjectNoIndexMeta,
|
|
147
|
+
nonIndexableProjects: mainConfig.nonIndexableProjects || [],
|
|
146
148
|
googleoptimize: mainConfig.googleoptimize,
|
|
147
149
|
googletagmanager: mainConfig.googletagmanager,
|
|
148
150
|
googleanalytics: mainConfig.googleanalytics,
|
|
@@ -189,6 +191,7 @@ module.exports = options => {
|
|
|
189
191
|
}
|
|
190
192
|
|
|
191
193
|
const projectConfigs = await getProjectConfigs( rootPath, projectPaths, {
|
|
194
|
+
...mainConfig,
|
|
192
195
|
skipLiveSnippets
|
|
193
196
|
} );
|
|
194
197
|
const buildDir = hexoManager.getPublicDir();
|
|
@@ -232,6 +235,7 @@ module.exports = options => {
|
|
|
232
235
|
// Links validation.
|
|
233
236
|
.then( async () => {
|
|
234
237
|
const projectConfigs = await getProjectConfigs( rootPath, projectPaths, {
|
|
238
|
+
...mainConfig,
|
|
235
239
|
skipLiveSnippets
|
|
236
240
|
} );
|
|
237
241
|
|
|
@@ -263,12 +267,12 @@ module.exports = options => {
|
|
|
263
267
|
return Promise.resolve();
|
|
264
268
|
} )
|
|
265
269
|
.then( async () => {
|
|
266
|
-
const projectConfigs = await getProjectConfigs( rootPath, projectPaths, { skipLiveSnippets } );
|
|
270
|
+
const projectConfigs = await getProjectConfigs( rootPath, projectPaths, { ...mainConfig, skipLiveSnippets } );
|
|
267
271
|
|
|
268
272
|
return createSitemapStep( { projectConfigs, verbose, mainConfig } );
|
|
269
273
|
} )
|
|
270
274
|
.then( async () => {
|
|
271
|
-
const configs = await getProjectConfigs( rootPath, projectPaths, { skipLiveSnippets } );
|
|
275
|
+
const configs = await getProjectConfigs( rootPath, projectPaths, { ...mainConfig, skipLiveSnippets } );
|
|
272
276
|
|
|
273
277
|
return executeHooks( configs, 'afterHexo' );
|
|
274
278
|
} )
|
|
@@ -382,6 +386,7 @@ async function buildProjects( rootPath, projectPaths, options = {} ) {
|
|
|
382
386
|
bindProjectLocals( hexoManager.hexo, {
|
|
383
387
|
basePath,
|
|
384
388
|
docSearch: options.docSearch,
|
|
389
|
+
shouldInjectNoIndexMeta: config.shouldInjectNoIndexMeta,
|
|
385
390
|
config,
|
|
386
391
|
googleoptimize: options.googleoptimize,
|
|
387
392
|
googletagmanager: options.googletagmanager,
|
|
@@ -428,8 +433,12 @@ async function getProjectConfigs( rootPath, projectPaths, options = {} ) {
|
|
|
428
433
|
const promises = projectPaths.map( async pPath => {
|
|
429
434
|
const projectRootPath = upath.join( rootPath, pPath );
|
|
430
435
|
|
|
436
|
+
const nonIndexableProjects = options.nonIndexableProjects || [];
|
|
437
|
+
const shouldInjectNoIndexMeta = options.shouldInjectNoIndexMeta || nonIndexableProjects.includes( pPath );
|
|
438
|
+
|
|
431
439
|
return getProjectConfig( projectRootPath, {
|
|
432
|
-
skipLiveSnippets: options.skipLiveSnippets
|
|
440
|
+
skipLiveSnippets: options.skipLiveSnippets,
|
|
441
|
+
shouldInjectNoIndexMeta
|
|
433
442
|
} );
|
|
434
443
|
} );
|
|
435
444
|
|
|
@@ -491,6 +500,7 @@ async function buildApis( projectConfigs, options = {} ) {
|
|
|
491
500
|
apiType: apiConfig.type
|
|
492
501
|
},
|
|
493
502
|
disableSearch: options.disableSearch,
|
|
503
|
+
shouldInjectNoIndexMeta: config.shouldInjectNoIndexMeta,
|
|
494
504
|
googleoptimize: options.googleoptimize,
|
|
495
505
|
googletagmanager: options.googletagmanager,
|
|
496
506
|
googleanalytics: options.googleanalytics,
|
|
@@ -507,8 +517,9 @@ async function buildApis( projectConfigs, options = {} ) {
|
|
|
507
517
|
projectConfig: config,
|
|
508
518
|
canonicalUrlBeginning: getCanonicalBeginning( { config, options, hexoManager } )
|
|
509
519
|
} ).then( apiDocs => {
|
|
510
|
-
// API docs navigation tree is rendered
|
|
520
|
+
// API docs navigation tree is rendered per package and reused as HTML.
|
|
511
521
|
config.navTree = apiDocs.getNavTree();
|
|
522
|
+
config.navTreeByPackage = apiDocs.getNavTreeByPackage();
|
|
512
523
|
// API errors documentation is stored here so that it's available in guides (and hexo filters).
|
|
513
524
|
config.errorsHtml = apiDocs.getErrors();
|
|
514
525
|
hexoManager.addProjectGlobalData( config.slug, 'doclets', apiDocs.getDataCollection() );
|
|
@@ -571,6 +582,7 @@ function buildSdks( projectConfigs, options = {} ) {
|
|
|
571
582
|
extraScriptsPaths: extraScripts
|
|
572
583
|
},
|
|
573
584
|
disableSearch: options.disableSearch,
|
|
585
|
+
shouldInjectNoIndexMeta: config.shouldInjectNoIndexMeta,
|
|
574
586
|
projectsData: basicProjectsData,
|
|
575
587
|
googleoptimize: options.googleoptimize,
|
|
576
588
|
googletagmanager: options.googletagmanager,
|
|
@@ -18,6 +18,7 @@ const cache = new Map();
|
|
|
18
18
|
* @param {String} rootPath
|
|
19
19
|
* @param {Object} [options={}]
|
|
20
20
|
* @param {Boolean} [options.skipLiveSnippets=false] If set to `true`, the `snippetAdapter` module will not be added to the configuration.
|
|
21
|
+
* @param {Boolean} [options.shouldInjectNoIndexMeta] Whether the "do not index" header for bots should be included.
|
|
21
22
|
* @returns {Promise}
|
|
22
23
|
*/
|
|
23
24
|
module.exports = async ( rootPath, options = {} ) => {
|
|
@@ -75,6 +76,10 @@ module.exports = async ( rootPath, options = {} ) => {
|
|
|
75
76
|
config.reportIssueWidget = {};
|
|
76
77
|
}
|
|
77
78
|
|
|
79
|
+
if ( options.shouldInjectNoIndexMeta ) {
|
|
80
|
+
config.shouldInjectNoIndexMeta = true;
|
|
81
|
+
}
|
|
82
|
+
|
|
78
83
|
// Prepare default values.
|
|
79
84
|
config.reportIssueWidget.enabled = config.reportIssueWidget.enabled || false;
|
|
80
85
|
config.reportIssueWidget.skipPages = config.reportIssueWidget.skipPages || [];
|
|
@@ -4,6 +4,9 @@ include ../../_components/svg/index
|
|
|
4
4
|
mixin treeItem( node, level )
|
|
5
5
|
- const children = node.getChildren();
|
|
6
6
|
- const hasChildren = children && children.length > 0;
|
|
7
|
+
- const isPackageNode = node.getProp( 'type' ) === 'package';
|
|
8
|
+
- const shouldRenderChildren = hasChildren && ( !isPackageNode || ( activeApiPackage && node.getProp( 'name' ) === activeApiPackage ) );
|
|
9
|
+
- const packageChevronClass = isPackageNode && hasChildren ? [ 'api-tree__button', 'api-tree__button--chevron', 'api-tree__button--package', shouldRenderChildren ? 'api-tree__button--open' : '' ] : [];
|
|
7
10
|
- let dataAttr = {};
|
|
8
11
|
|
|
9
12
|
- if ( node.getProp( 'access' ) ) dataAttr[ `data-${node.getProp('access')}` ] = 'true';
|
|
@@ -18,7 +21,21 @@ mixin treeItem( node, level )
|
|
|
18
21
|
- const longname = node.getProp( 'longname' );
|
|
19
22
|
- const iconClassName = "api-tree__link--with-icon api-tree__link--icon-" + node.getProp( 'type' );
|
|
20
23
|
|
|
21
|
-
if
|
|
24
|
+
if isPackageNode
|
|
25
|
+
div.api-tree__item-wrapper( data-ln = longname )
|
|
26
|
+
a(
|
|
27
|
+
class = [ classStr, 'api-tree__link', iconClassName ],
|
|
28
|
+
href=link,
|
|
29
|
+
data-skip-validation=''
|
|
30
|
+
)
|
|
31
|
+
if hasChildren
|
|
32
|
+
i( class = packageChevronClass )
|
|
33
|
+
| #{ node.getProp( 'name' ) }
|
|
34
|
+
if shouldRenderChildren
|
|
35
|
+
ul.api-tree__list( 'style'='--level:'+level )
|
|
36
|
+
each child in children
|
|
37
|
+
+treeItem( child, level + 1 )
|
|
38
|
+
else if !shouldRenderChildren
|
|
22
39
|
div.api-tree__item-wrapper
|
|
23
40
|
a.api-tree__link(
|
|
24
41
|
href=link,
|
|
@@ -17,7 +17,12 @@ if ( page[ 'twitter-card' ] || ogConfig.description )
|
|
|
17
17
|
meta( name='twitter:card' content= page[ 'twitter-card' ] || ogConfig.description )
|
|
18
18
|
meta( name='twitter:site' content= '@ckeditor' )
|
|
19
19
|
|
|
20
|
+
- const currentProject = projectLocals && projectsData.find( project => project.slug === projectLocals.projectSlug );
|
|
21
|
+
- const isNonIndexableProject = currentProject && currentProject.shouldInjectNoIndexMeta
|
|
22
|
+
|
|
20
23
|
meta( name= 'x-generated-at' content= Date() )
|
|
24
|
+
if shouldInjectNoIndexMeta || isNonIndexableProject
|
|
25
|
+
meta( name= 'robots' content='noindex, nofollow' )
|
|
21
26
|
|
|
22
27
|
if ( mainOg || ( projectLocals && projectLocals.og ) || page[ 'og-description' ] )
|
|
23
28
|
meta( property='og:title' content= page[ 'og-title' ] || title )
|
|
@@ -15,7 +15,12 @@ if ( page[ 'twitter-card' ] || ogConfig.description )
|
|
|
15
15
|
meta( name='twitter:card' content= page[ 'twitter-card' ] || ogConfig.description )
|
|
16
16
|
meta( name='twitter:site' content= '@ckeditor' )
|
|
17
17
|
|
|
18
|
+
- const currentProject = projectLocals && projectsData.find( project => project.slug === projectLocals.projectSlug );
|
|
19
|
+
- const isNonIndexableProject = currentProject && currentProject.shouldInjectNoIndexMeta
|
|
20
|
+
|
|
18
21
|
meta( name= 'x-generated-at' content= Date() )
|
|
22
|
+
if shouldInjectNoIndexMeta || isNonIndexableProject
|
|
23
|
+
meta( name= 'robots' content='noindex, nofollow' )
|
|
19
24
|
|
|
20
25
|
if ( mainOg || ( projectLocals && projectLocals.og ) || page[ 'og-description' ] )
|
|
21
26
|
meta( property='og:title' content= page[ 'og-title' ] || title )
|
|
@@ -184,6 +184,10 @@
|
|
|
184
184
|
transform: translate(-125%, -50%) rotate(90deg);
|
|
185
185
|
}
|
|
186
186
|
|
|
187
|
+
&--package {
|
|
188
|
+
left: 0;
|
|
189
|
+
}
|
|
190
|
+
|
|
187
191
|
&--chevron {
|
|
188
192
|
&:before {
|
|
189
193
|
content: url('data:image/svg+xml,<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M7.29274 3.96428C6.90222 3.57376 6.26905 3.57376 5.87853 3.96428C5.488 4.3548 5.488 4.98797 5.87853 5.37849L7.99982 7.49979L5.8785 9.62111C5.48798 10.0116 5.48798 10.6448 5.8785 11.0353C6.26903 11.4258 6.90219 11.4258 7.29272 11.0353L10.115 8.21301C10.1171 8.21099 10.1191 8.20896 10.1212 8.20692C10.5117 7.8164 10.5117 7.18323 10.1212 6.79271L10.1211 6.79268L7.29274 3.96428Z" fill="%233B4958"/></svg>') / 'Api-chevron icon';
|
|
@@ -155,7 +155,7 @@ export class ApiNavTree extends BaseComponent {
|
|
|
155
155
|
sidebarNav.scrollTop = Number( storedScrollPosition );
|
|
156
156
|
}
|
|
157
157
|
|
|
158
|
-
const activeElement = navTree.querySelector( '.api-tree__item-wrapper.active' );
|
|
158
|
+
const activeElement = navTree.querySelector( '.api-tree__item-wrapper.active' )?.parentElement;
|
|
159
159
|
|
|
160
160
|
setTimeout( () => {
|
|
161
161
|
// Ensure the sidebar is scrolled to the active element after a short delay.
|