umberto 3.2.0 → 3.2.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,24 @@
1
1
  Changelog
2
2
  =========
3
3
 
4
+ ## [3.2.2](https://github.com/cksource/umberto/compare/v3.2.1...v3.2.2) (2023-08-28)
5
+
6
+ ### Bug fixes
7
+
8
+ * Fixed jumping layout in the secondary (table of content) navigation in a case when a text is just barely fitting a single line. When it gets highlighted and the font geometry changes, and it gets to two lines. Closes [cksource/umberto#1152](https://github.com/cksource/umberto/issues/1152). ([commit](https://github.com/cksource/umberto/commit/102674435ea8f70c321d7c029bf984ddc16f7855))
9
+ * HTML tags will no longer render in ToC. Closes [#1157](https://github.com/cksource/umberto/issues/1157). ([commit](https://github.com/cksource/umberto/commit/cc44e61f496bef25f34d8e2d41eca8e849a54924))
10
+ * Skip search results from API on the root page in documentation. Closes [#1029](https://github.com/cksource/umberto/issues/1029). ([commit](https://github.com/cksource/umberto/commit/b4f9250a43ff887da6da7f042434aa1542582ea7))
11
+
12
+ ### Other changes
13
+
14
+ * The Google Analytics `<script>` tag produces output compatible with the latest version (v4). Closes [#1166](https://github.com/cksource/umberto/issues/1166). ([commit](https://github.com/cksource/umberto/commit/0cefecde3ccc12f171580dded361895bfb0b12cd))
15
+
16
+
17
+ ## [3.2.1](https://github.com/cksource/umberto/compare/v3.2.0...v3.2.1) (2023-06-21)
18
+
19
+ Internal changes only (updated dependencies, documentation, etc.).
20
+
21
+
4
22
  ## [3.2.0](https://github.com/cksource/umberto/compare/v3.1.0...v3.2.0) (2023-06-02)
5
23
 
6
24
  ### Features
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "umberto",
3
- "version": "3.2.0",
3
+ "version": "3.2.2",
4
4
  "description": "CKSource Documentation builder",
5
5
  "main": "src/index.js",
6
6
  "files": [
@@ -27,6 +27,7 @@
27
27
  "escape-string-regexp": "^4.0.0",
28
28
  "fs-extra": "^10.1.0",
29
29
  "fuse.js": "^6.6.2",
30
+ "glob": "^7.2.3",
30
31
  "hexo": "^6.2.0",
31
32
  "hexo-generator-archive": "^1.0.0",
32
33
  "hexo-generator-category": "^1.0.0",
@@ -33,8 +33,12 @@ hexo.extend.helper.register( 'uToc', ( data, options = {} ) => {
33
33
 
34
34
  headings.each( function() {
35
35
  const hLevel = Number( this.name[ 1 ] );
36
- const text = $r( this ).find( '.headerlink' ).remove().end().text().trim();
37
36
  const id = $r( this ).attr( 'id' );
37
+ const text = $r( this ).find( '.headerlink' ).remove().end().text().trim()
38
+ // Replace the chevrons with their HTML escape characters to avoid rendering HTML in ToC.
39
+ .replace( /</g, '&lt;' )
40
+ .replace( />/g, '&gt;' );
41
+
38
42
  const newItem = `<li><a href="#${ id }">${ text }</a></li>`;
39
43
 
40
44
  if ( tocLastLevels[ hLevel ] ) {
@@ -5,8 +5,14 @@
5
5
 
6
6
  'use strict';
7
7
 
8
- const { stringify } = require( 'javascript-stringify' );
9
8
  const { cloneDeep } = require( 'lodash' );
9
+ const { stringify } = require( 'javascript-stringify' );
10
+ const fs = require( 'fs' );
11
+ const upath = require( 'upath' );
12
+
13
+ const defaultScriptTemplate = fs.readFileSync( upath.join( __dirname, 'templates', 'scripts', 'default.js' ), 'utf-8' );
14
+ const groupScriptTemplate = fs.readFileSync( upath.join( __dirname, 'templates', 'scripts', 'group.js' ), 'utf-8' );
15
+ const rootScriptTemplate = fs.readFileSync( upath.join( __dirname, 'templates', 'scripts', 'root.js' ), 'utf-8' );
10
16
 
11
17
  module.exports = ( searchConfig, {
12
18
  groups = [],
@@ -25,7 +31,7 @@ module.exports = ( searchConfig, {
25
31
  const options = {
26
32
  inputSelector: '#docsearch_input',
27
33
  algoliaOptions: {
28
- hitsPerPage: 10,
34
+ hitsPerPage: 250,
29
35
  attributesToRetrieve: '*'
30
36
  }
31
37
  };
@@ -35,7 +41,7 @@ module.exports = ( searchConfig, {
35
41
  dConfig,
36
42
  options,
37
43
  {
38
- isEnabled: dConfig.apiKey && dConfig.indexName,
44
+ isEnabled: Boolean( dConfig.apiKey && dConfig.indexName ),
39
45
  css: 'https://cdn.jsdelivr.net/docsearch.js/1/docsearch.min.css',
40
46
  js: 'https://cdn.jsdelivr.net/docsearch.js/2/docsearch.min.js'
41
47
  }
@@ -58,7 +64,6 @@ module.exports = ( searchConfig, {
58
64
 
59
65
  if ( transformDataFunctions ) {
60
66
  for ( const tag of Object.keys( transformDataFunctions ) ) {
61
- innerConfig.algoliaOptions.hitsPerPage = 250;
62
67
  const innerConfigStr = stringify( innerConfig ).replace( /^{|}$/g, '' );
63
68
 
64
69
  docSearchConfig.scripts[ tag ] = [
@@ -88,144 +93,35 @@ module.exports = ( searchConfig, {
88
93
  };
89
94
 
90
95
  function getTransformDataFns( groups, slug ) {
91
- if ( !Array.isArray( groups ) || groups.length === 0 ) {
92
- return null;
93
- }
96
+ const functions = {
97
+ rootScript: fillTemplate( rootScriptTemplate.toString() )
98
+ };
94
99
 
95
- const functions = {};
96
- const tags = `[ ${ groups.map( g => `'${ g.slug }'` ).join( ', ' ) } ]`;
97
-
98
- for ( const g of groups ) {
99
- functions[ g.slug ] = [
100
- 'function( hits ) {',
101
-
102
- 'var sortingFn = function( a, b ) {',
103
- 'a.custom_ranking = a.custom_ranking || 0;',
104
- 'b.custom_ranking = b.custom_ranking || 0;',
105
-
106
- 'if ( a.custom_ranking === b.custom_ranking ) return a.index - b.index;',
107
- 'if ( a.custom_ranking > b.custom_ranking ) return -1;',
108
- 'if ( a.custom_ranking < b.custom_ranking ) return 1;',
109
- '};',
110
-
111
- 'var result = [];',
112
- `var tags = ${ tags };`,
113
-
114
- 'var hitsGrouped = { api: [] };',
115
-
116
- `hitsGrouped[ '${ g.slug }' ] = hits`,
117
- '.filter( function( h ) {',
118
- `return h.tags.includes( '${ slug }' ) && h.tags.includes( '${ g.slug }' );`,
119
- '} )',
120
- '.slice( 0, 7 )',
121
- '.map( function( item, idx ) {',
122
- 'item.index = idx;',
123
- 'return item;',
124
- '} )',
125
- '.sort( sortingFn );',
126
-
127
- 'tags.forEach( function( tag ) {',
128
- `if ( tag !== '${ g.slug }' ) {`,
129
- 'hitsGrouped[ tag ] = hits',
130
- '.filter( function( h ) {',
131
- `return h.tags.includes( '${ slug }' ) && h.tags.includes( tag );`,
132
- '} )',
133
- '.slice( 0, 10 )',
134
- '.map( function( item, idx ) {',
135
- 'item.index = idx;',
136
- 'return item;',
137
- '} )',
138
- '.sort( sortingFn )',
139
- '.slice( 0, 3 );',
140
- '}',
141
- '} );',
142
-
143
- 'var apiSearchHits = [];',
144
-
145
- 'if ( window.apiSearch ) apiSearchHits = window.apiSearch();',
146
-
147
- 'hitsGrouped.api = hitsGrouped.api.filter( function( h ) {',
148
- 'var isDuplicated = false;',
149
-
150
- 'for ( var i = 0; i < apiSearchHits.length; i++ ) {',
151
- 'if ( h.url.includes( apiSearchHits[ i ].urlShort ) ) {',
152
- 'isDuplicated = true;',
153
- 'break;',
154
- '}',
155
- '}',
156
-
157
- 'return !isDuplicated;',
158
- '} );',
159
-
160
- 'hitsGrouped.api = ( apiSearchHits || [] ).concat( hitsGrouped.api );',
161
-
162
- `result = result.concat( hitsGrouped[ '${ g.slug }' ] );`,
163
-
164
- 'tags.forEach( function( tag ) {',
165
- `if ( tag !== '${ g.slug }' ) result = result.concat( hitsGrouped[ tag ].slice( 0, 4 ) );`,
166
- '} );',
167
-
168
- 'return result;',
169
- '}'
170
- ].join( '' );
100
+ if ( !Array.isArray( groups ) || groups.length === 0 ) {
101
+ return functions;
171
102
  }
172
103
 
173
- functions.defaultScript = [
174
- 'function( hits ) {',
175
- 'var sortingFn = function( a, b ) {',
176
- 'a.custom_ranking = a.custom_ranking || 0;',
177
- 'b.custom_ranking = b.custom_ranking || 0;',
178
-
179
- 'if ( a.custom_ranking === b.custom_ranking ) return a.index - b.index;',
180
- 'if ( a.custom_ranking > b.custom_ranking ) return -1;',
181
- 'if ( a.custom_ranking < b.custom_ranking ) return 1;',
182
- '};',
104
+ const tags = `${ groups.map( group => `${ group.slug }` ).join( '\', \'' ) }`;
183
105
 
184
- 'var result = [];',
185
- `var tags = ${ tags };`,
106
+ for ( const group of groups ) {
107
+ const groupSlug = group.slug;
186
108
 
187
- 'var hitsGrouped = { api: [] };',
188
-
189
- 'tags.forEach( function( tag ) {',
190
- 'hitsGrouped[ tag ] = hits',
191
- '.filter( function( h ) {',
192
- `return h.tags.includes( '${ slug }' ) && h.tags.includes( tag );`,
193
- '} )',
194
- '.slice( 0, 10 )',
195
- '.map( function( item, idx ) {',
196
- 'item.index = idx;',
197
- 'return item;',
198
- '} )',
199
- '.sort( sortingFn )',
200
- '.slice( 0, 3 );',
201
- '} );',
202
-
203
- 'var apiSearchHits = [];',
204
-
205
- 'if ( window.apiSearch ) apiSearchHits = window.apiSearch();',
206
-
207
- 'hitsGrouped.api = hitsGrouped.api.filter( function( h ) {',
208
- 'var isDuplicated = false;',
109
+ functions[ groupSlug ] = fillTemplate( groupScriptTemplate.toString(), { tags, slug, groupSlug } );
110
+ }
209
111
 
210
- 'for ( var i = 0; i < apiSearchHits.length; i++ ) {',
211
- 'if ( h.url.includes( apiSearchHits[ i ].urlShort ) ) {',
212
- 'isDuplicated = true;',
213
- 'break;',
214
- '}',
215
- '}',
112
+ functions.defaultScript = fillTemplate( defaultScriptTemplate.toString(), { tags, slug } );
216
113
 
217
- 'return !isDuplicated;',
218
- '} );',
114
+ return functions;
115
+ }
219
116
 
220
- 'hitsGrouped.api = ( apiSearchHits || [] ).concat( hitsGrouped.api );',
117
+ function fillTemplate( template, data ) {
118
+ let updatedTemplate = template.replace( /^function [\S]+\( hits \)/, 'function( hits )' );
221
119
 
222
- 'tags.forEach( function( tag ) {',
223
- 'result = result.concat( hitsGrouped[ tag ].slice( 0, 4 ) );',
224
- '} );',
120
+ for ( const key in data ) {
121
+ const pattern = new RegExp( `{{{ ${ key } }}}`, 'g' );
225
122
 
226
- 'return result;',
227
- '}'
228
- ].join( '' );
123
+ updatedTemplate = updatedTemplate.replace( pattern, data[ key ] );
124
+ }
229
125
 
230
- return functions;
126
+ return updatedTemplate.replace( /\n\s*/g, '' );
231
127
  }
@@ -0,0 +1,54 @@
1
+ function defaultScript( hits ) {
2
+ var sortingFn = function( a, b ) {
3
+ a.custom_ranking = a.custom_ranking || 0;
4
+ b.custom_ranking = b.custom_ranking || 0;
5
+
6
+ if ( a.custom_ranking === b.custom_ranking ) return a.index - b.index;
7
+ if ( a.custom_ranking > b.custom_ranking ) return -1;
8
+ if ( a.custom_ranking < b.custom_ranking ) return 1;
9
+ };
10
+
11
+ var result = [];
12
+ var tags = [ '{{{ tags }}}' ];
13
+
14
+ var hitsGrouped = { api: [] };
15
+
16
+ tags.forEach( function( tag ) {
17
+ hitsGrouped[ tag ] = hits
18
+ .filter( function( h ) {
19
+ return h.tags.includes( '{{{ slug }}}' ) && h.tags.includes( tag );
20
+ } )
21
+ .slice( 0, 10 )
22
+ .map( function( item, idx ) {
23
+ item.index = idx;
24
+ return item;
25
+ } )
26
+ .sort( sortingFn )
27
+ .slice( 0, 3 );
28
+ } );
29
+
30
+ var apiSearchHits = [];
31
+
32
+ if ( window.apiSearch ) apiSearchHits = window.apiSearch();
33
+
34
+ hitsGrouped.api = hitsGrouped.api.filter( function( h ) {
35
+ var isDuplicated = false;
36
+
37
+ for ( var i = 0; i < apiSearchHits.length; i++ ) {
38
+ if ( h.url.includes( apiSearchHits[ i ].urlShort ) ) {
39
+ isDuplicated = true;
40
+ break;
41
+ }
42
+ }
43
+
44
+ return !isDuplicated;
45
+ } );
46
+
47
+ hitsGrouped.api = ( apiSearchHits || [] ).concat( hitsGrouped.api );
48
+
49
+ tags.forEach( function( tag ) {
50
+ result = result.concat( hitsGrouped[ tag ].slice( 0, 4 ) );
51
+ } );
52
+
53
+ return result;
54
+ }
@@ -0,0 +1,69 @@
1
+ function groupScript( hits ) {
2
+ var sortingFn = function( a, b ) {
3
+ a.custom_ranking = a.custom_ranking || 0;
4
+ b.custom_ranking = b.custom_ranking || 0;
5
+
6
+ if ( a.custom_ranking === b.custom_ranking ) return a.index - b.index;
7
+ if ( a.custom_ranking > b.custom_ranking ) return -1;
8
+ if ( a.custom_ranking < b.custom_ranking ) return 1;
9
+ };
10
+
11
+ var result = [];
12
+ var tags = [ '{{{ tags }}}' ];
13
+
14
+ var hitsGrouped = { api: [] };
15
+
16
+ hitsGrouped[ '{{{ groupSlug }}}' ] = hits
17
+ .filter( function( h ) {
18
+ return h.tags.includes( '{{{ slug }}}' ) && h.tags.includes( '{{{ groupSlug }}}' );
19
+ } )
20
+ .slice( 0, 7 )
21
+ .map( function( item, idx ) {
22
+ item.index = idx;
23
+ return item;
24
+ } )
25
+ .sort( sortingFn );
26
+
27
+ tags.forEach( function( tag ) {
28
+ if ( tag !== '{{{ groupSlug }}}' ) {
29
+ hitsGrouped[ tag ] = hits
30
+ .filter( function( h ) {
31
+ return h.tags.includes( '{{{ slug }}}' ) && h.tags.includes( tag );
32
+ } )
33
+ .slice( 0, 10 )
34
+ .map( function( item, idx ) {
35
+ item.index = idx;
36
+ return item;
37
+ } )
38
+ .sort( sortingFn )
39
+ .slice( 0, 3 );
40
+ }
41
+ } );
42
+
43
+ var apiSearchHits = [];
44
+
45
+ if ( window.apiSearch ) apiSearchHits = window.apiSearch();
46
+
47
+ hitsGrouped.api = hitsGrouped.api.filter( function( h ) {
48
+ var isDuplicated = false;
49
+
50
+ for ( var i = 0; i < apiSearchHits.length; i++ ) {
51
+ if ( h.url.includes( apiSearchHits[ i ].urlShort ) ) {
52
+ isDuplicated = true;
53
+ break;
54
+ }
55
+ }
56
+
57
+ return !isDuplicated;
58
+ } );
59
+
60
+ hitsGrouped.api = ( apiSearchHits || [] ).concat( hitsGrouped.api );
61
+
62
+ result = result.concat( hitsGrouped[ '{{{ groupSlug }}}' ] );
63
+
64
+ tags.forEach( function( tag ) {
65
+ if ( tag !== '{{{ groupSlug }}}' ) result = result.concat( hitsGrouped[ tag ].slice( 0, 4 ) );
66
+ } );
67
+
68
+ return result;
69
+ }
@@ -0,0 +1,21 @@
1
+ function rootScript( hits ) {
2
+ var sortingFn = function( a, b ) {
3
+ a.custom_ranking = a.custom_ranking || 0;
4
+ b.custom_ranking = b.custom_ranking || 0;
5
+
6
+ if ( a.custom_ranking === b.custom_ranking ) return a.index - b.index;
7
+ if ( a.custom_ranking > b.custom_ranking ) return -1;
8
+ if ( a.custom_ranking < b.custom_ranking ) return 1;
9
+ };
10
+
11
+ return hits
12
+ .filter( function( h ) {
13
+ return !h.tags.includes( 'api' );
14
+ } )
15
+ .slice( 0, 10 )
16
+ .map( function( item, idx ) {
17
+ item.index = idx;
18
+ return item;
19
+ } )
20
+ .sort( sortingFn );
21
+ }
@@ -13,7 +13,9 @@ if ( docSearchConfig && docSearchConfig.isEnabled && !disableSearch && (!project
13
13
 
14
14
  script( src=config.js )
15
15
 
16
- if ( !page.groupSlug || !config.scripts[ page.groupSlug ] )
16
+ if ( page.path === 'index.html' )
17
+ != config.scripts.rootScript
18
+ else if ( !page.groupSlug || !config.scripts[ page.groupSlug ] )
17
19
  != config.scripts.defaultScript
18
20
  else
19
21
  != config.scripts[ page.groupSlug ]
@@ -1,25 +1,19 @@
1
1
  if googleanalytics && !googletagmanager
2
2
  script.
3
3
  if ( !{ JSON.stringify( googleanalytics.domains ) }.indexOf( location.hostname ) !== -1 ) {
4
- function pageView() {
5
- ga( 'send', 'pageview', location.pathname + location.search + location.hash );
6
- }
7
-
8
- (function( i, s, o, g, r, a, m ) {
9
- i[ 'GoogleAnalyticsObject' ] = r;
10
- i[ r ] = i[ r ] || function() {
11
- (i[ r ].q = i[ r ].q || []).push( arguments )
12
- }, i[ r ].l = 1 * new Date();
13
- a = s.createElement( o ),
14
- m = s.getElementsByTagName( o )[ 0 ];
4
+ ( function ( w, d, e, u, a, b ) {
5
+ a = d.createElement( e );
6
+ b = d.getElementsByTagName( e )[ 0 ];
15
7
  a.async = 1;
16
- a.src = g;
17
- m.parentNode.insertBefore( a, m )
18
- })( window, document, 'script', 'https://www.google-analytics.com/analytics.js', 'ga' );
8
+ a.src = u;
9
+ b.parentNode.insertBefore( a, b )
10
+ } )( window, document, 'script', 'https://www.googletagmanager.com/gtag/js?id=!{ googleanalytics.config.trackingId }' );
11
+ window.dataLayer = window.dataLayer || [];
19
12
 
20
- ga( 'create', !{ JSON.stringify( googleanalytics.config ) } );
21
-
22
- pageView();
13
+ function gtag() {
14
+ dataLayer.push( arguments );
15
+ }
23
16
 
24
- window.addEventListener( 'hashchange', pageView );
17
+ gtag( 'js', new Date() );
18
+ gtag( 'config', '!{ googleanalytics.config.trackingId }' );
25
19
  }
@@ -68,7 +68,7 @@ nav.secondary-navigation {
68
68
 
69
69
  &.secondary-navigation__current-position {
70
70
  color: u-color( 'link' );
71
- font-weight: bold;
71
+ -webkit-text-stroke-width: thin;
72
72
 
73
73
  &::before {
74
74
  opacity: 1;