umberto 8.0.3 → 8.2.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 +20 -28
- package/package.json +1 -1
- package/scripts/filter/after-post-render/gloria/apply-design-doc-classes.js +6 -55
- package/scripts/filter/after-post-render/gloria/wrap-table-into-wrappers.js +11 -5
- package/scripts/utils/apply-design-doc-classes.js +82 -0
- package/scripts/utils/{pipe.js → compose.js} +1 -1
- package/scripts/utils/concat-url-parts.js +2 -2
- package/src/helpers/resolve-path.js +13 -0
- package/src/hexo/filter/project-locals.js +3 -0
- package/src/hexo/get-repo-urls.js +1 -1
- package/src/tasks/build-documentation.js +4 -0
- package/src/tasks/copy-project-docs.js +4 -4
- package/src/tasks/copy-project-icons.js +4 -1
- package/themes/umberto/layout/gloria/_components/button/index.pug +2 -1
- package/themes/umberto/layout/gloria/_head/head.pug +2 -0
- package/themes/umberto/layout/gloria/_modules/header/index.pug +2 -0
- package/themes/umberto/layout/gloria/_modules/index.pug +1 -0
- package/themes/umberto/layout/gloria/_modules/kapa/index.pug +102 -0
- package/themes/umberto/source/gloria/assets/_img/icons/chat.svg +3 -0
- package/themes/umberto/src/gloria/js/components/iframe.js +1 -10
- package/themes/umberto/src/gloria/js/helpers/{pipe.js → compose.js} +1 -1
- package/themes/umberto/src/gloria/js/modules/algolia-search.js +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,26 @@
|
|
|
1
1
|
Changelog
|
|
2
2
|
=========
|
|
3
3
|
|
|
4
|
+
## [8.2.0](https://github.com/cksource/umberto/compare/v8.1.0...v8.2.0) (August 29, 2025)
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* Added integration with the [Kapa.ai](https://www.kapa.ai/) service.
|
|
9
|
+
|
|
10
|
+
Umberto configuration can now specify the `kapa` key that allows loading the Kapa button and widget.
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
## [8.1.0](https://github.com/cksource/umberto/compare/v8.0.3...v8.1.0) (August 12, 2025)
|
|
14
|
+
|
|
15
|
+
### Features
|
|
16
|
+
|
|
17
|
+
* Added support for relative paths in `packagesDir` option.
|
|
18
|
+
|
|
19
|
+
### Bug fixes
|
|
20
|
+
|
|
21
|
+
* Updated how `<iframe>` elements are created to fix issues with automated tests using Chrome v139.
|
|
22
|
+
|
|
23
|
+
|
|
4
24
|
## [8.0.3](https://github.com/cksource/umberto/compare/v8.0.2...v8.0.3) (August 5, 2025)
|
|
5
25
|
|
|
6
26
|
### Bug fixes
|
|
@@ -33,34 +53,6 @@ Changelog
|
|
|
33
53
|
* Fixed the project selection dropdown: after rebuilding, it now correctly displays all available projects instead of only one.
|
|
34
54
|
* Optimized the performance of the navigation tree building process, resulting in faster page loads and smoother navigation.
|
|
35
55
|
|
|
36
|
-
|
|
37
|
-
## [8.0.0](https://github.com/cksource/umberto/compare/v7.0.2...v8.0.0) (July 18, 2025)
|
|
38
|
-
|
|
39
|
-
### BREAKING CHANGES
|
|
40
|
-
|
|
41
|
-
* Updated the required version of Node.js to 22.
|
|
42
|
-
|
|
43
|
-
### Features
|
|
44
|
-
|
|
45
|
-
* We have introduced a brand-new theme to elevate your UI experience. Enjoy a fresh look with improved aesthetics and feel.
|
|
46
|
-
|
|
47
|
-
### Bug fixes
|
|
48
|
-
|
|
49
|
-
* Removed link to unnecessary stylesheet that results in a 404.
|
|
50
|
-
* Fixed output path calculation on Windows environment for generated HTML files. Previously, non-normalized CWD was used which caused the generated output path to contain invalid characters and be incorrect.
|
|
51
|
-
|
|
52
|
-
### Other changes
|
|
53
|
-
|
|
54
|
-
* The repository now uses ESLint v9. Therefore, the required Node.js version has been upgraded to 22 to match the ESLint requirements.
|
|
55
|
-
* Update `LICENSE.md` file to include licenses of direct dependencies
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
## [7.0.2](https://github.com/cksource/umberto/compare/v7.0.1...v7.0.2) (2025-05-20)
|
|
59
|
-
|
|
60
|
-
### Bug fixes
|
|
61
|
-
|
|
62
|
-
* 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))
|
|
63
|
-
|
|
64
56
|
---
|
|
65
57
|
|
|
66
58
|
To see all releases, visit the [release page](https://github.com/cksource/umberto/releases).
|
package/package.json
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
'use strict';
|
|
7
7
|
|
|
8
|
-
const
|
|
8
|
+
const applyDesignDocClasses = require( '../../../utils/apply-design-doc-classes' );
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* Global mapping of HTML elements to their corresponding design system classes.
|
|
@@ -86,60 +86,11 @@ hexo.extend.filter.register( 'after_post_render', page => {
|
|
|
86
86
|
return page;
|
|
87
87
|
}
|
|
88
88
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
$elements.each( ( _, element ) => {
|
|
96
|
-
const $element = $( element );
|
|
97
|
-
|
|
98
|
-
if ( hasClassOrParentWithClass( $element, 'no-transform' ) ) {
|
|
99
|
-
return;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
// Add the 'doc' class to each element that gets styled
|
|
103
|
-
$element.addClass( 'doc' );
|
|
104
|
-
|
|
105
|
-
const classList = ( $element.attr( 'class' )?.split( /\s+/ ) || [] ).filter(
|
|
106
|
-
className => !ELEMENTS_WITH_WHITELIST_CLASSES.includes( className )
|
|
107
|
-
);
|
|
108
|
-
|
|
109
|
-
// Avoid applying classes to elements that already have one.
|
|
110
|
-
if ( classList.length > 1 ) {
|
|
111
|
-
return;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
// Add the specified classes
|
|
115
|
-
if ( typeof classesOrCallback === 'function' ) {
|
|
116
|
-
const elementClasses = classesOrCallback( $element );
|
|
117
|
-
|
|
118
|
-
if ( Array.isArray( elementClasses ) ) {
|
|
119
|
-
$element.addClass( elementClasses.join( ' ' ) );
|
|
120
|
-
} else if ( typeof elementClasses === 'string' ) {
|
|
121
|
-
$element.addClass( elementClasses );
|
|
122
|
-
}
|
|
123
|
-
} else if ( Array.isArray( classesOrCallback ) ) {
|
|
124
|
-
$element.addClass( classesOrCallback.join( ' ' ) );
|
|
125
|
-
} else {
|
|
126
|
-
$element.addClass( classesOrCallback );
|
|
127
|
-
}
|
|
128
|
-
} );
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
page.content = $.html();
|
|
89
|
+
page.content = applyDesignDocClasses( {
|
|
90
|
+
elementsClassesMappings: ELEMENTS_CLASSES_MAPPINGS,
|
|
91
|
+
elementsWithWhitelistClasses: ELEMENTS_WITH_WHITELIST_CLASSES,
|
|
92
|
+
content: page.content
|
|
93
|
+
} );
|
|
132
94
|
|
|
133
95
|
return page;
|
|
134
96
|
}, 40 );
|
|
135
|
-
|
|
136
|
-
/**
|
|
137
|
-
* Checks if the element itself or any of its parents has the specified class.
|
|
138
|
-
*
|
|
139
|
-
* @param $element - The jQuery element to check.
|
|
140
|
-
* @param className - The class name to look for.
|
|
141
|
-
* @returns True if the element or any parent has the class, false otherwise.
|
|
142
|
-
*/
|
|
143
|
-
function hasClassOrParentWithClass( $element, className ) {
|
|
144
|
-
return $element.hasClass( className ) || $element.parents( `.${ className }` ).length > 0;
|
|
145
|
-
}
|
|
@@ -7,10 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
const cheerio = require( 'cheerio' );
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
* Enforce priority 30 to run it after apply design doc classes filter.
|
|
12
|
-
*/
|
|
13
|
-
hexo.extend.filter.register( 'after_post_render', page => {
|
|
10
|
+
function wrapTableIntoWrappers( page ) {
|
|
14
11
|
if ( page.projectTheme !== 'gloria' ) {
|
|
15
12
|
return page;
|
|
16
13
|
}
|
|
@@ -27,4 +24,13 @@ hexo.extend.filter.register( 'after_post_render', page => {
|
|
|
27
24
|
page.content = $.html();
|
|
28
25
|
|
|
29
26
|
return page;
|
|
30
|
-
}
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Enforce priority 30 to run it after apply design doc classes filter.
|
|
31
|
+
*/
|
|
32
|
+
if ( typeof hexo !== 'undefined' ) {
|
|
33
|
+
hexo.extend.filter.register( 'after_post_render', wrapTableIntoWrappers, 30 );
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
module.exports = wrapTableIntoWrappers;
|
|
@@ -0,0 +1,82 @@
|
|
|
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 cheerio = require( 'cheerio' );
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Add design system classes to the parsed document elements. If element has 0 CSS classes
|
|
12
|
+
* it'll be considered as not styled and the design system classes will be applied.
|
|
13
|
+
|
|
14
|
+
* @param options - Options for applying design classes.
|
|
15
|
+
* @param options.elementsClassesMappings - Mappings of elements to their classes or
|
|
16
|
+
* functions that return classes.
|
|
17
|
+
* @param options.elementsWithWhitelistClasses - List of classes that are
|
|
18
|
+
* considered as transparent in checks for amount of the classes.
|
|
19
|
+
* @param options.content - The HTML content to process.
|
|
20
|
+
*/
|
|
21
|
+
module.exports = function applyDesignDocClasses(
|
|
22
|
+
{
|
|
23
|
+
elementsClassesMappings,
|
|
24
|
+
elementsWithWhitelistClasses,
|
|
25
|
+
content
|
|
26
|
+
}
|
|
27
|
+
) {
|
|
28
|
+
const $ = cheerio.load( content, null, false );
|
|
29
|
+
|
|
30
|
+
// Apply classes based on the global mapping
|
|
31
|
+
for ( const [ element, classesOrCallback ] of Object.entries( elementsClassesMappings ) ) {
|
|
32
|
+
const $elements = $( element );
|
|
33
|
+
|
|
34
|
+
$elements.each( ( _, element ) => {
|
|
35
|
+
const $element = $( element );
|
|
36
|
+
|
|
37
|
+
if ( hasClassOrParentWithClass( $element, 'no-transform' ) ) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Add the 'doc' class to each element that gets styled
|
|
42
|
+
$element.addClass( 'doc' );
|
|
43
|
+
|
|
44
|
+
const classList = ( $element.attr( 'class' )?.split( /\s+/ ) || [] ).filter(
|
|
45
|
+
className => !elementsWithWhitelistClasses.includes( className )
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
// Avoid applying classes to elements that already have one.
|
|
49
|
+
if ( classList.length > 1 ) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Add the specified classes
|
|
54
|
+
if ( typeof classesOrCallback === 'function' ) {
|
|
55
|
+
const elementClasses = classesOrCallback( $element );
|
|
56
|
+
|
|
57
|
+
if ( Array.isArray( elementClasses ) ) {
|
|
58
|
+
$element.addClass( elementClasses.join( ' ' ) );
|
|
59
|
+
} else if ( typeof elementClasses === 'string' ) {
|
|
60
|
+
$element.addClass( elementClasses );
|
|
61
|
+
}
|
|
62
|
+
} else if ( Array.isArray( classesOrCallback ) ) {
|
|
63
|
+
$element.addClass( classesOrCallback.join( ' ' ) );
|
|
64
|
+
} else {
|
|
65
|
+
$element.addClass( classesOrCallback );
|
|
66
|
+
}
|
|
67
|
+
} );
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return $.html();
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Checks if the element itself or any of its parents has the specified class.
|
|
75
|
+
*
|
|
76
|
+
* @param $element - The jQuery element to check.
|
|
77
|
+
* @param className - The class name to look for.
|
|
78
|
+
* @returns True if the element or any parent has the class, false otherwise.
|
|
79
|
+
*/
|
|
80
|
+
function hasClassOrParentWithClass( $element, className ) {
|
|
81
|
+
return $element.hasClass( className ) || $element.parents( `.${ className }` ).length > 0;
|
|
82
|
+
}
|
|
@@ -12,6 +12,6 @@
|
|
|
12
12
|
* @param {*} value - The initial value to be processed by the functions.
|
|
13
13
|
* @returns {*} The final result after all functions have been applied.
|
|
14
14
|
*/
|
|
15
|
-
module.exports = function
|
|
15
|
+
module.exports = function compose( ...fns ) {
|
|
16
16
|
return value => fns.reduce( ( acc, fn ) => fn( acc ), value );
|
|
17
17
|
};
|
|
@@ -7,13 +7,13 @@
|
|
|
7
7
|
|
|
8
8
|
const dropInitSlash = require( './drop-init-slash' );
|
|
9
9
|
const dropTrailingSlash = require( './drop-trailing-slash' );
|
|
10
|
-
const
|
|
10
|
+
const compose = require( './compose' );
|
|
11
11
|
|
|
12
12
|
module.exports = function concatUrlParts( ...urls ) {
|
|
13
13
|
return (
|
|
14
14
|
urls
|
|
15
15
|
.filter( Boolean )
|
|
16
|
-
.map(
|
|
16
|
+
.map( compose( dropTrailingSlash, dropInitSlash ) )
|
|
17
17
|
.join( '/' )
|
|
18
18
|
);
|
|
19
19
|
};
|
|
@@ -0,0 +1,13 @@
|
|
|
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
|
+
/**
|
|
9
|
+
* Wrapper around `require.resolve()` to allow mocking it in tests.
|
|
10
|
+
*/
|
|
11
|
+
module.exports = function resolvePath( path, options ) {
|
|
12
|
+
return require.resolve( path, options );
|
|
13
|
+
};
|
|
@@ -20,6 +20,7 @@ const umbertoVersion = require( '../../../package.json' ).version;
|
|
|
20
20
|
* @param {Object} googleoptimize Google Optimize config.
|
|
21
21
|
* @param {Object} googletagmanager Google Tag Manager config.
|
|
22
22
|
* @param {Object} googleanalytics Google Analytics config.
|
|
23
|
+
* @param {Object} kapa Kapa.ai config.
|
|
23
24
|
* @param {Object} vwo Visual Website Optimizer config.
|
|
24
25
|
* @param {Object} feedbackWidget Feedback widget config
|
|
25
26
|
* @param {Array} extraStylePaths Paths to extra external css.
|
|
@@ -36,6 +37,7 @@ module.exports = ( ctx, {
|
|
|
36
37
|
googleoptimize,
|
|
37
38
|
googletagmanager,
|
|
38
39
|
googleanalytics,
|
|
40
|
+
kapa,
|
|
39
41
|
promobar,
|
|
40
42
|
vwo,
|
|
41
43
|
feedbackWidget,
|
|
@@ -105,6 +107,7 @@ module.exports = ( ctx, {
|
|
|
105
107
|
locals.googleoptimize = googleoptimize;
|
|
106
108
|
locals.googletagmanager = googletagmanager;
|
|
107
109
|
locals.googleanalytics = googleanalytics;
|
|
110
|
+
locals.kapa = kapa;
|
|
108
111
|
locals.promobar = promobar;
|
|
109
112
|
locals.vwo = vwo;
|
|
110
113
|
locals.feedbackWidget = feedbackWidget;
|
|
@@ -17,7 +17,7 @@ module.exports = ( {
|
|
|
17
17
|
guidesToRepos.default = defaultRepoUrl;
|
|
18
18
|
|
|
19
19
|
for ( const item of packages ) {
|
|
20
|
-
const packageRepoUrl = getRepoUrl( upath.
|
|
20
|
+
const packageRepoUrl = getRepoUrl( upath.resolve( rootPath, item.path ) );
|
|
21
21
|
globSync( upath.join( rootPath, item.path, 'docs', '**', '*.md' ) )
|
|
22
22
|
.map( p => upath.normalize( p ) )
|
|
23
23
|
.map( p => p.replace( upath.join( rootPath, item.path, 'docs' ), '' ) )
|
|
@@ -141,6 +141,7 @@ module.exports = options => {
|
|
|
141
141
|
googleoptimize: mainConfig.googleoptimize,
|
|
142
142
|
googletagmanager: mainConfig.googletagmanager,
|
|
143
143
|
googleanalytics: mainConfig.googleanalytics,
|
|
144
|
+
kapa: mainConfig.kapa,
|
|
144
145
|
promobar: mainConfig.promobar,
|
|
145
146
|
sitemap: mainConfig.sitemap,
|
|
146
147
|
vwo: mainConfig.vwo,
|
|
@@ -275,6 +276,7 @@ async function buildProjects( rootPath, projectPaths, options = {} ) {
|
|
|
275
276
|
googleoptimize: options.googleoptimize,
|
|
276
277
|
googletagmanager: options.googletagmanager,
|
|
277
278
|
googleanalytics: options.googleanalytics,
|
|
279
|
+
kapa: options.kapa,
|
|
278
280
|
promobar: options.promobar,
|
|
279
281
|
sitemap: options.sitemap,
|
|
280
282
|
vwo: options.vwo,
|
|
@@ -353,6 +355,7 @@ async function buildProjects( rootPath, projectPaths, options = {} ) {
|
|
|
353
355
|
googleoptimize: options.googleoptimize,
|
|
354
356
|
googletagmanager: options.googletagmanager,
|
|
355
357
|
googleanalytics: options.googleanalytics,
|
|
358
|
+
kapa: options.kapa,
|
|
356
359
|
promobar: options.promobar,
|
|
357
360
|
quickNavigationProjects: options.quickNavigationProjects,
|
|
358
361
|
vwo: options.vwo,
|
|
@@ -465,6 +468,7 @@ async function buildApis( projectConfigs, options = {} ) {
|
|
|
465
468
|
googleoptimize: options.googleoptimize,
|
|
466
469
|
googletagmanager: options.googletagmanager,
|
|
467
470
|
googleanalytics: options.googleanalytics,
|
|
471
|
+
kapa: options.kapa,
|
|
468
472
|
promobar: options.promobar,
|
|
469
473
|
vwo: options.vwo,
|
|
470
474
|
feedbackWidget: options.feedbackWidget,
|
|
@@ -58,13 +58,13 @@ module.exports = ( rootPath, config, options ) => {
|
|
|
58
58
|
if ( config.items && Array.isArray( config.items ) ) {
|
|
59
59
|
for ( const item of config.items ) {
|
|
60
60
|
hexoManager.addOriginPath(
|
|
61
|
-
upath.
|
|
62
|
-
upath.
|
|
61
|
+
upath.resolve( rootPath, item.path, config.path ),
|
|
62
|
+
upath.resolve( hexoManager.getSourceDir(), BASE_PATH )
|
|
63
63
|
);
|
|
64
64
|
|
|
65
65
|
promises.push( copyDocFiles(
|
|
66
|
-
upath.
|
|
67
|
-
upath.
|
|
66
|
+
upath.resolve( rootPath, item.path, config.path ),
|
|
67
|
+
upath.resolve( hexoManager.getSourceDir(), BASE_PATH ),
|
|
68
68
|
{
|
|
69
69
|
match,
|
|
70
70
|
allOutputPaths,
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
const upath = require( 'upath' );
|
|
9
9
|
const fs = require( 'fs-extra' );
|
|
10
|
+
const resolvePath = require( '../helpers/resolve-path' );
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
13
|
* @returns {Promise<void>}
|
|
@@ -19,7 +20,9 @@ module.exports = async function copyProjectIcons( projectGlobals, buildDirectory
|
|
|
19
20
|
const destinationIconsPath = upath.join( buildDirectory, projectDetails.BASE_PATH, 'assets', 'icons' );
|
|
20
21
|
|
|
21
22
|
for ( const [ sourceFile, destinationName ] of projectDetails._icons ) {
|
|
22
|
-
const fullSourcePath =
|
|
23
|
+
const fullSourcePath = resolvePath( sourceFile, {
|
|
24
|
+
paths: [ projectDetails.config.projectRootPath ]
|
|
25
|
+
} );
|
|
23
26
|
const fullDestinationPath = upath.join( destinationIconsPath, destinationName );
|
|
24
27
|
|
|
25
28
|
try {
|
|
@@ -16,12 +16,13 @@
|
|
|
16
16
|
//- +button({ variant: 'secondary' })
|
|
17
17
|
//- +button({ variant: 'transparent', fillColor: '--color-orange-600' })
|
|
18
18
|
//- span Custom content
|
|
19
|
-
mixin button({ variant = 'primary', tooltip, blockDisplay, active, disabled, id, className, square, rounded, type = 'button', size = 'base', label, ariaLabel, ariaControls, icon, labelClassName, iconClassName, fillColor, iconPosition = 'left' })
|
|
19
|
+
mixin button({ variant = 'primary', tooltip, blockDisplay, active, disabled, id, className, square, rounded, type = 'button', size = 'base', label, ariaLabel, ariaControls, icon, labelClassName, iconClassName, fillColor, iconPosition = 'left', onClick })
|
|
20
20
|
- const showTooltip = !!id && !!tooltip && !ariaLabel;
|
|
21
21
|
|
|
22
22
|
button.c-button(
|
|
23
23
|
id=id,
|
|
24
24
|
disabled=disabled,
|
|
25
|
+
onClick=onClick || false,
|
|
25
26
|
class={
|
|
26
27
|
'is-block': blockDisplay,
|
|
27
28
|
'is-active': active,
|
|
@@ -45,6 +45,8 @@ if page.BASE_PATH && page.BASE_PATH !== '.' && !page.BASE_PATH.includes( 'latest
|
|
|
45
45
|
link( rel = 'canonical' href = page.canonicalUrlBeginning + page.path.replace( page.BASE_PATH, projectLocals.latestBasePath ) )
|
|
46
46
|
|
|
47
47
|
+head-preloads()
|
|
48
|
+
if kapa
|
|
49
|
+
+load-kapa-script(kapa)
|
|
48
50
|
|
|
49
51
|
script(src=relative_url(page.path, pathJoin( 'assets', umbertoVersion, 'gloria/scripts/app.js')))
|
|
50
52
|
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
mixin load-kapa-script(kapa)
|
|
2
|
+
-
|
|
3
|
+
const mainColor = '#743CCD';
|
|
4
|
+
const textPrimaryColor = '#00091B';
|
|
5
|
+
const textSecondaryColor = '#585B5F';
|
|
6
|
+
const infoPanelBackgroundColor = '#F8F9FA';
|
|
7
|
+
const standardBorder = '1px solid var(--mantine-color-gray-3)';
|
|
8
|
+
const buttonHoverBgColor = 'var(--mantine-color-default-hover)';
|
|
9
|
+
const exampleQuestionsTitleColor = 'var(--mantine-color-gray-text)';
|
|
10
|
+
|
|
11
|
+
var attributes = {
|
|
12
|
+
'async': true,
|
|
13
|
+
'fetchpriority': 'low',
|
|
14
|
+
'src': 'https://widget.kapa.ai/kapa-widget.bundle.js',
|
|
15
|
+
'data-website-id': kapa.widgetOptions.websiteId,
|
|
16
|
+
'data-project-name': kapa.widgetOptions.projectName,
|
|
17
|
+
|
|
18
|
+
// Global settings.
|
|
19
|
+
'data-project-color': mainColor,
|
|
20
|
+
'data-project-logo': 'https://ckeditor.com/docs/ckeditor5/latest/assets/img/ckeditor5-logo.svg',
|
|
21
|
+
'data-font-family': '"Title Mullish", text public sans',
|
|
22
|
+
|
|
23
|
+
// Floating button.
|
|
24
|
+
'data-button-text': 'Need help?',
|
|
25
|
+
'data-button-image': 'https://ckeditor.com/docs/ckeditor5/latest/assets/img/ckeditor5-logo-white.svg',
|
|
26
|
+
'data-button-width': 'fit-content',
|
|
27
|
+
'data-button-height': '90px',
|
|
28
|
+
'data-button-padding': '12px',
|
|
29
|
+
|
|
30
|
+
// Modal style.
|
|
31
|
+
'data-modal-size': '900px',
|
|
32
|
+
'data-modal-z-index': '2000',
|
|
33
|
+
'data-modal-border-radius': '6px',
|
|
34
|
+
|
|
35
|
+
// Modal title.
|
|
36
|
+
'data-modal-title': 'AI Helper',
|
|
37
|
+
'data-modal-title-color': textPrimaryColor,
|
|
38
|
+
|
|
39
|
+
// Modal disclaimer.
|
|
40
|
+
'data-modal-disclaimer': 'Disclaimer: Responses are generated by AI and may contain inaccuracies. Please verify the information with the official documentation.',
|
|
41
|
+
'data-modal-disclaimer-text-color': exampleQuestionsTitleColor,
|
|
42
|
+
'data-modal-disclaimer-bg-color': infoPanelBackgroundColor,
|
|
43
|
+
|
|
44
|
+
// Modal example questions.
|
|
45
|
+
'data-example-question-button-border': standardBorder,
|
|
46
|
+
'data-example-question-button-text-color': textSecondaryColor,
|
|
47
|
+
|
|
48
|
+
// Modal question input.
|
|
49
|
+
'data-query-input-text-color': textPrimaryColor,
|
|
50
|
+
'data-query-input-placeholder-text-color': textSecondaryColor,
|
|
51
|
+
'data-modal-ask-ai-input-placeholder': 'Ask me a question about the project...',
|
|
52
|
+
|
|
53
|
+
// Modal deep thinking button.
|
|
54
|
+
'data-deep-thinking-button-text-color': textSecondaryColor,
|
|
55
|
+
|
|
56
|
+
// Modal answer.
|
|
57
|
+
'data-question-text-color': textPrimaryColor,
|
|
58
|
+
'data-answer-text-color': textPrimaryColor,
|
|
59
|
+
|
|
60
|
+
// Modal copy, clear & feedback buttons.
|
|
61
|
+
'data-answer-copy-button-bg-color': 'white',
|
|
62
|
+
'data-answer-copy-button-border': standardBorder,
|
|
63
|
+
'data-answer-copy-button-hover-bg-color': buttonHoverBgColor,
|
|
64
|
+
'data-thread-clear-button-bg-color': 'white',
|
|
65
|
+
'data-thread-clear-button-border': standardBorder,
|
|
66
|
+
'data-thread-clear-button-hover-bg-color': buttonHoverBgColor,
|
|
67
|
+
'data-answer-feedback-button-bg-color': 'white',
|
|
68
|
+
'data-answer-feedback-button-border': standardBorder,
|
|
69
|
+
'data-answer-feedback-button-active-bg-color': buttonHoverBgColor,
|
|
70
|
+
|
|
71
|
+
// Modal answer source buttons.
|
|
72
|
+
'data-source-link-primary-heading-text-color': textPrimaryColor,
|
|
73
|
+
'data-source-link-secondary-heading-text-color': textSecondaryColor,
|
|
74
|
+
'data-source-link-hover-bg-color': buttonHoverBgColor,
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const projectConfig = projectLocals && kapa[ projectLocals.projectSlug ];
|
|
78
|
+
const modalTitle = projectConfig && projectConfig.modalTitle;
|
|
79
|
+
const questionPlaceholder = projectConfig && projectConfig.questionPlaceholder;
|
|
80
|
+
const exampleQuestions = projectConfig && projectConfig.exampleQuestions;
|
|
81
|
+
|
|
82
|
+
if ( modalTitle ) {
|
|
83
|
+
attributes[ 'data-modal-title' ] = modalTitle;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if ( questionPlaceholder ) {
|
|
87
|
+
attributes[ 'data-modal-ask-ai-input-placeholder' ] = questionPlaceholder;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if ( exampleQuestions && exampleQuestions.length ) {
|
|
91
|
+
attributes[ 'data-modal-example-questions' ] = exampleQuestions.join( ',' );
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
script&attributes(attributes)
|
|
95
|
+
|
|
96
|
+
mixin kapa-button
|
|
97
|
+
+button({
|
|
98
|
+
label: 'Ask AI',
|
|
99
|
+
icon: 'chat',
|
|
100
|
+
variant: 'toolbar',
|
|
101
|
+
onClick: 'window.Kapa(\'open\')'
|
|
102
|
+
})
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<path d="M1.76782 15.2671C1.82839 15.2671 1.88757 15.2565 1.94458 15.2388L4.21411 14.4995C6.12656 15.1316 8.2129 14.7834 9.80396 13.6245L9.79517 13.6167C10.4093 13.5828 11.0272 13.4619 11.6252 13.2495L13.886 13.9614C13.9575 13.984 14.033 13.9924 14.1077 13.9858C14.1823 13.9793 14.2551 13.958 14.3215 13.9233C14.388 13.8887 14.4472 13.8411 14.4954 13.7837C14.5434 13.7263 14.5794 13.6598 14.6018 13.5884C14.6197 13.5348 14.6292 13.4776 14.6292 13.4204L14.6428 11.0522C16.3963 8.78261 16.4699 5.58834 14.7502 3.21338C12.6163 0.290177 8.51232 -0.357907 5.58911 1.76709C5.20354 2.0456 4.85922 2.35857 4.55396 2.69775L4.55396 2.6958C3.19644 3.06057 2.00514 3.87984 1.17896 5.01709C-0.417359 7.21518 -0.376417 10.1666 1.19653 12.3022L1.19653 14.6958C1.19668 15.0116 1.45198 15.2669 1.76782 15.2671ZM11.5891 11.8921L11.3752 11.981C9.15207 12.847 6.59175 12.1221 5.16138 10.1597C3.45604 7.81327 3.97848 4.51834 6.33911 2.80225C8.69255 1.09877 11.9926 1.62058 13.7141 3.98096C15.1284 5.92914 15.0285 8.58439 13.5178 10.4272L13.3752 10.5884L13.3577 12.4458L11.5891 11.8921ZM2.50024 11.856L2.35767 11.6772C0.991728 9.98443 0.917806 7.56318 2.21411 5.78467C2.53375 5.34003 2.91082 4.97189 3.32153 4.67725L3.33228 4.67041C2.53946 6.68459 2.76114 9.04694 4.12524 10.9272C4.96108 12.0747 6.14695 12.9202 7.50415 13.3364L7.50024 13.3384C6.51275 13.6152 5.44653 13.5848 4.44653 13.2134L4.23267 13.1245L2.48267 13.7134L2.50024 11.856ZM6.9104 7.8042C7.3229 7.8042 7.64282 7.484 7.64282 7.08936C7.6426 6.69491 7.32276 6.37549 6.9104 6.37549C6.53378 6.37553 6.21434 6.69493 6.21411 7.08936C6.21411 7.48397 6.53365 7.80415 6.9104 7.8042ZM9.4104 7.8042C9.8229 7.8042 10.1428 7.484 10.1428 7.08936C10.1426 6.69491 9.82276 6.37549 9.4104 6.37549C9.03378 6.37553 8.71434 6.69493 8.71411 7.08936C8.71411 7.48397 9.03365 7.80415 9.4104 7.8042ZM11.9104 7.8042C12.3229 7.8042 12.6428 7.484 12.6428 7.08936C12.6426 6.69491 12.3228 6.37549 11.9104 6.37549C11.5338 6.37554 11.2143 6.69493 11.2141 7.08936C11.2141 7.48397 11.5337 7.80415 11.9104 7.8042Z" fill="#585B5F"/>
|
|
3
|
+
</svg>
|
|
@@ -71,10 +71,7 @@ export class IFrame extends BaseComponent {
|
|
|
71
71
|
* @param content - HTML content to load
|
|
72
72
|
*/
|
|
73
73
|
setContent( content ) {
|
|
74
|
-
|
|
75
|
-
const iframeDocument = iframe.contentDocument || iframe.contentWindow?.document;
|
|
76
|
-
|
|
77
|
-
const wrappedHTML = `
|
|
74
|
+
this.elements.iframe.srcdoc = `
|
|
78
75
|
<!DOCTYPE html>
|
|
79
76
|
${ content }
|
|
80
77
|
${ this.config.autoResize ? `
|
|
@@ -91,12 +88,6 @@ export class IFrame extends BaseComponent {
|
|
|
91
88
|
</script>
|
|
92
89
|
` : '' }
|
|
93
90
|
`;
|
|
94
|
-
|
|
95
|
-
if ( iframeDocument ) {
|
|
96
|
-
iframeDocument.open();
|
|
97
|
-
iframeDocument.write( wrappedHTML );
|
|
98
|
-
iframeDocument.close();
|
|
99
|
-
}
|
|
100
91
|
}
|
|
101
92
|
|
|
102
93
|
/**
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
import { BaseComponent } from '../components/base-component';
|
|
7
7
|
import { identity } from '../helpers/identity';
|
|
8
8
|
import { injectScript } from '../helpers/inject-script';
|
|
9
|
-
import {
|
|
9
|
+
import { compose } from '../helpers/compose';
|
|
10
10
|
|
|
11
11
|
const DOCSEARCH_JS_URL = 'https://cdn.jsdelivr.net/npm/@docsearch/js@3.9.0/dist/umd/index.min.js';
|
|
12
12
|
|
|
@@ -67,7 +67,7 @@ export class AlgoliaSearch extends BaseComponent {
|
|
|
67
67
|
|
|
68
68
|
client.search = async ( options, ...rest ) => {
|
|
69
69
|
const { results: [ firstResult ] } = await originalSearch( options, ...rest );
|
|
70
|
-
const mappedResults =
|
|
70
|
+
const mappedResults = compose(
|
|
71
71
|
filterByTags( { slug, tags } ),
|
|
72
72
|
boostByTags( boost.tags )
|
|
73
73
|
)( firstResult.hits );
|
|
@@ -110,7 +110,7 @@ function boostByTags( tags ) {
|
|
|
110
110
|
return identity;
|
|
111
111
|
}
|
|
112
112
|
|
|
113
|
-
return
|
|
113
|
+
return compose(
|
|
114
114
|
groupByTag,
|
|
115
115
|
sortObjectKeysByIndices( tags ),
|
|
116
116
|
Object.values,
|