just-the-docs 0.2.4 → 0.2.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +2 -2
  3. data/_includes/css/custom.scss.liquid +1 -0
  4. data/_includes/css/just-the-docs.scss.liquid +7 -0
  5. data/_includes/head.html +25 -13
  6. data/_includes/head_custom.html +0 -0
  7. data/_includes/js/custom.js +0 -0
  8. data/_includes/nav.html +41 -34
  9. data/_includes/title.html +5 -0
  10. data/_includes/vendor/anchor_headings.html +100 -0
  11. data/_layouts/default.html +100 -39
  12. data/_layouts/table_wrappers.html +7 -0
  13. data/_layouts/vendor/compress.html +10 -0
  14. data/_sass/base.scss +16 -18
  15. data/_sass/buttons.scss +1 -1
  16. data/_sass/code.scss +209 -69
  17. data/_sass/color_schemes/dark.scss +3 -1
  18. data/_sass/color_schemes/light.scss +0 -0
  19. data/_sass/content.scss +79 -0
  20. data/_sass/custom/custom.scss +0 -120
  21. data/_sass/labels.scss +5 -4
  22. data/_sass/layout.scss +90 -29
  23. data/_sass/modules.scss +19 -0
  24. data/_sass/navigation.scss +4 -32
  25. data/_sass/search.scss +98 -45
  26. data/_sass/support/_functions.scss +2 -3
  27. data/_sass/support/_variables.scss +20 -20
  28. data/_sass/support/mixins/_layout.scss +1 -3
  29. data/_sass/support/mixins/_typography.scss +6 -1
  30. data/_sass/tables.scss +13 -33
  31. data/_sass/typography.scss +10 -8
  32. data/_sass/utilities/_layout.scss +75 -18
  33. data/_sass/utilities/_lists.scss +7 -1
  34. data/_sass/utilities/_spacing.scss +70 -26
  35. data/_sass/utilities/_typography.scss +1 -1
  36. data/assets/css/just-the-docs-dark.scss +3 -0
  37. data/assets/css/just-the-docs-default.scss +8 -0
  38. data/assets/css/just-the-docs-light.scss +3 -0
  39. data/assets/js/just-the-docs.js +240 -103
  40. data/assets/js/search-data.json +4 -4
  41. data/assets/js/vendor/lunr.min.js +3 -3
  42. data/lib/tasks/search.rake +4 -4
  43. metadata +47 -25
  44. data/assets/css/dark-mode-preview.scss +0 -41
  45. data/assets/css/just-the-docs.scss +0 -44
@@ -2,7 +2,7 @@
2
2
  // Utility classes for typography
3
3
  //
4
4
 
5
- // stylelint-disable primer/selector-no-utility
5
+ // stylelint-disable primer/selector-no-utility, primer/no-override
6
6
 
7
7
  .fs-1 {
8
8
  @include fs-1;
@@ -0,0 +1,3 @@
1
+ ---
2
+ ---
3
+ {% include css/just-the-docs.scss.liquid color_scheme="dark" %}
@@ -0,0 +1,8 @@
1
+ ---
2
+ ---
3
+ {% if site.color_scheme and site.color_scheme != "nil" %}
4
+ {% assign color_scheme = site.color_scheme %}
5
+ {% else %}
6
+ {% assign color_scheme = "light" %}
7
+ {% endif %}
8
+ {% include css/just-the-docs.scss.liquid color_scheme=color_scheme %}
@@ -0,0 +1,3 @@
1
+ ---
2
+ ---
3
+ {% include css/just-the-docs.scss.liquid color_scheme="light" %}
@@ -1,28 +1,41 @@
1
+ ---
2
+ ---
3
+ (function (jtd, undefined) {
4
+
1
5
  // Event handling
2
6
 
3
- function addEvent(el, type, handler) {
4
- if (el.attachEvent) el.attachEvent('on'+type, handler); else el.addEventListener(type, handler);
7
+ jtd.addEvent = function(el, type, handler) {
8
+ if (el.attachEvent) el.attachEvent('on'+type, handler); else el.addEventListener(type, handler);
9
+ }
10
+ jtd.removeEvent = function(el, type, handler) {
11
+ if (el.detachEvent) el.detachEvent('on'+type, handler); else el.removeEventListener(type, handler);
5
12
  }
6
- function removeEvent(el, type, handler) {
7
- if (el.detachEvent) el.detachEvent('on'+type, handler); else el.removeEventListener(type, handler);
13
+ jtd.onReady = function(ready) {
14
+ // in case the document is already rendered
15
+ if (document.readyState!='loading') ready();
16
+ // modern browsers
17
+ else if (document.addEventListener) document.addEventListener('DOMContentLoaded', ready);
18
+ // IE <= 8
19
+ else document.attachEvent('onreadystatechange', function(){
20
+ if (document.readyState=='complete') ready();
21
+ });
8
22
  }
9
23
 
10
24
  // Show/hide mobile menu
11
25
 
12
- function toggleNav(){
13
- const nav = document.querySelector('.js-main-nav');
14
- const auxNav = document.querySelector('.js-aux-nav');
26
+ function initNav() {
27
+ const mainNav = document.querySelector('.js-main-nav');
28
+ const pageHeader = document.querySelector('.js-page-header');
15
29
  const navTrigger = document.querySelector('.js-main-nav-trigger');
16
- const search = document.querySelector('.js-search');
17
30
 
18
- addEvent(navTrigger, 'click', function(){
31
+ jtd.addEvent(navTrigger, 'click', function(e){
32
+ e.preventDefault();
19
33
  var text = navTrigger.innerText;
20
34
  var textToggle = navTrigger.getAttribute('data-text-toggle');
21
35
 
22
- nav.classList.toggle('nav-open');
23
- auxNav.classList.toggle('nav-open');
36
+ mainNav.classList.toggle('nav-open');
37
+ pageHeader.classList.toggle('nav-open');
24
38
  navTrigger.classList.toggle('nav-open');
25
- search.classList.toggle('nav-open');
26
39
  navTrigger.innerText = textToggle;
27
40
  navTrigger.setAttribute('data-text-toggle', text);
28
41
  textToggle = text;
@@ -32,145 +45,269 @@ function toggleNav(){
32
45
  // Site search
33
46
 
34
47
  function initSearch() {
35
- var index = lunr(function () {
36
- this.ref('id');
37
- this.field('title', { boost: 20 });
38
- this.field('content', { boost: 10 });
39
- this.field('url');
40
- });
41
-
42
- // Get the generated search_data.json file so lunr.js can search it locally.
43
-
44
- sc = document.getElementsByTagName("script");
45
- source = '';
46
-
47
- for(idx = 0; idx < sc.length; idx++)
48
- {
49
- s = sc.item(idx);
50
-
51
- if(s.src && s.src.match(/just-the-docs\.js$/))
52
- { source = s.src; }
53
- }
54
-
55
- jsPath = source.replace('just-the-docs.js', '');
56
-
57
- jsonPath = jsPath + 'search-data.json';
58
-
59
48
  var request = new XMLHttpRequest();
60
- request.open('GET', jsonPath, true);
49
+ request.open('GET', '{{ "assets/js/search-data.json" | absolute_url }}', true);
61
50
 
62
- request.onload = function() {
51
+ request.onload = function(){
63
52
  if (request.status >= 200 && request.status < 400) {
64
53
  // Success!
65
54
  var data = JSON.parse(request.responseText);
66
- var keys = Object.keys(data);
67
-
68
- for(var i in data) {
69
- index.add({
70
- id: data[i].id,
71
- title: data[i].title,
72
- content: data[i].content,
73
- url: data[i].url
74
- });
75
- }
76
- searchResults(data);
55
+
56
+ {% if site.search_tokenizer_separator != nil %}
57
+ lunr.tokenizer.separator = {{ site.search_tokenizer_separator }}
58
+ {% else %}
59
+ lunr.tokenizer.separator = /[\s\-/]+/
60
+ {% endif %}
61
+
62
+ var index = lunr(function () {
63
+ this.ref('id');
64
+ this.field('title', { boost: 200 });
65
+ this.field('content', { boost: 2 });
66
+ this.field('url');
67
+ this.metadataWhitelist = ['position']
68
+
69
+ for (var i in data) {
70
+ this.add({
71
+ id: i,
72
+ title: data[i].title,
73
+ content: data[i].content,
74
+ url: data[i].url
75
+ });
76
+ }
77
+ });
78
+
79
+ searchResults(index, data);
77
80
  } else {
78
81
  // We reached our target server, but it returned an error
79
82
  console.log('Error loading ajax request. Request status:' + request.status);
80
83
  }
81
84
  };
82
85
 
83
- request.onerror = function() {
86
+ request.onerror = function(){
84
87
  // There was a connection error of some sort
85
88
  console.log('There was a connection error');
86
89
  };
87
90
 
88
91
  request.send();
89
92
 
90
- function searchResults(dataStore) {
93
+ function searchResults(index, data) {
94
+ var index = index;
95
+ var docs = data;
91
96
  var searchInput = document.querySelector('.js-search-input');
92
97
  var searchResults = document.querySelector('.js-search-results');
93
- var store = dataStore;
94
98
 
95
99
  function hideResults() {
96
100
  searchResults.innerHTML = '';
97
101
  searchResults.classList.remove('active');
98
102
  }
99
103
 
100
- addEvent(searchInput, 'keyup', function(e){
101
- var query = this.value;
102
-
103
- searchResults.innerHTML = '';
104
- searchResults.classList.remove('active');
105
-
106
- if (query === '') {
107
- hideResults();
108
- } else {
109
- var results = index.search(query);
110
-
111
- if (results.length > 0) {
112
- searchResults.classList.add('active');
113
- var resultsList = document.createElement('ul');
114
- searchResults.appendChild(resultsList);
115
-
116
- for (var i in results) {
117
- var resultsListItem = document.createElement('li');
118
- var resultsLink = document.createElement('a');
119
- var resultsUrlDesc = document.createElement('span');
120
- var resultsUrl = store[results[i].ref].url;
121
- var resultsRelUrl = store[results[i].ref].relUrl;
122
- var resultsTitle = store[results[i].ref].title;
123
-
124
- resultsLink.setAttribute('href', resultsUrl);
125
- resultsLink.innerText = resultsTitle;
126
- resultsUrlDesc.innerText = resultsRelUrl;
127
-
128
- resultsList.classList.add('search-results-list');
129
- resultsListItem.classList.add('search-results-list-item');
130
- resultsLink.classList.add('search-results-link');
131
- resultsUrlDesc.classList.add('fs-2','text-grey-dk-000','d-block');
132
-
133
- resultsList.appendChild(resultsListItem);
134
- resultsListItem.appendChild(resultsLink);
135
- resultsLink.appendChild(resultsUrlDesc);
104
+ jtd.addEvent(searchInput, 'keydown', function(e){
105
+ switch (e.keyCode) {
106
+ case 38: // arrow up
107
+ e.preventDefault();
108
+ var active = document.querySelector('.search-result.active');
109
+ if (active) {
110
+ active.classList.remove('active');
111
+ if (active.parentElement.previousSibling) {
112
+ var previous = active.parentElement.previousSibling.querySelector('.search-result');
113
+ previous.classList.add('active');
114
+ }
136
115
  }
137
- }
116
+ return;
117
+ case 40: // arrow down
118
+ e.preventDefault();
119
+ var active = document.querySelector('.search-result.active');
120
+ if (active) {
121
+ if (active.parentElement.nextSibling) {
122
+ var next = active.parentElement.nextSibling.querySelector('.search-result');
123
+ active.classList.remove('active');
124
+ next.classList.add('active');
125
+ }
126
+ } else {
127
+ var next = document.querySelector('.search-result');
128
+ if (next) {
129
+ next.classList.add('active');
130
+ }
131
+ }
132
+ return;
133
+ case 13: // enter
134
+ e.preventDefault();
135
+ var active = document.querySelector('.search-result.active');
136
+ if (active) {
137
+ active.click();
138
+ } else {
139
+ var first = document.querySelector('.search-result');
140
+ if (first) {
141
+ first.click();
142
+ }
143
+ }
144
+ return;
145
+ }
146
+ });
138
147
 
139
- // When esc key is pressed, hide the results and clear the field
140
- if (e.keyCode == 27) {
148
+ jtd.addEvent(searchInput, 'keyup', function(e){
149
+ switch (e.keyCode) {
150
+ case 27: // When esc key is pressed, hide the results and clear the field
141
151
  hideResults();
142
152
  searchInput.value = '';
153
+ return;
154
+ case 38: // arrow up
155
+ case 40: // arrow down
156
+ case 13: // enter
157
+ e.preventDefault();
158
+ return;
159
+ }
160
+
161
+ hideResults();
162
+
163
+ var input = this.value;
164
+ if (input === '') {
165
+ return;
166
+ }
167
+
168
+ var results = index.query(function (query) {
169
+ var tokens = lunr.tokenizer(input)
170
+ query.term(tokens, {
171
+ boost: 10
172
+ });
173
+ query.term(tokens, {
174
+ wildcard: lunr.Query.wildcard.TRAILING
175
+ });
176
+ });
177
+
178
+ if (results.length > 0) {
179
+ searchResults.classList.add('active');
180
+ var resultsList = document.createElement('ul');
181
+ resultsList.classList.add('search-results-list');
182
+ searchResults.appendChild(resultsList);
183
+
184
+ for (var i in results) {
185
+ var result = results[i];
186
+ var doc = docs[result.ref];
187
+
188
+ var resultsListItem = document.createElement('li');
189
+ resultsListItem.classList.add('search-results-list-item');
190
+ resultsList.appendChild(resultsListItem);
191
+
192
+ var resultLink = document.createElement('a');
193
+ resultLink.classList.add('search-result');
194
+ resultLink.setAttribute('href', doc.url);
195
+ resultsListItem.appendChild(resultLink);
196
+
197
+ var resultTitle = document.createElement('div');
198
+ resultTitle.classList.add('search-result-title');
199
+ resultTitle.innerText = doc.title;
200
+ resultLink.appendChild(resultTitle);
201
+
202
+ var resultRelUrl = document.createElement('span');
203
+ resultRelUrl.classList.add('search-result-rel-url');
204
+ resultRelUrl.innerText = doc.relUrl;
205
+ resultTitle.appendChild(resultRelUrl);
206
+
207
+ var metadata = result.matchData.metadata;
208
+ var contentFound = false;
209
+ for (var j in metadata) {
210
+ if (metadata[j].title) {
211
+ var position = metadata[j].title.position[0];
212
+ var start = position[0];
213
+ var end = position[0] + position[1];
214
+ resultTitle.innerHTML = doc.title.substring(0, start) + '<span class="search-result-highlight">' + doc.title.substring(start, end) + '</span>' + doc.title.substring(end, doc.title.length)+'<span class="search-result-rel-url">'+doc.relUrl+'</span>';
215
+
216
+ } else if (metadata[j].content && !contentFound) {
217
+ contentFound = true;
218
+
219
+ var position = metadata[j].content.position[0];
220
+ var start = position[0];
221
+ var end = position[0] + position[1];
222
+ var previewStart = start;
223
+ var previewEnd = end;
224
+ var ellipsesBefore = true;
225
+ var ellipsesAfter = true;
226
+ for (var k = 0; k < 3; k++) {
227
+ var nextSpace = doc.content.lastIndexOf(' ', previewStart - 2);
228
+ var nextDot = doc.content.lastIndexOf('.', previewStart - 2);
229
+ if ((nextDot > 0) && (nextDot > nextSpace)) {
230
+ previewStart = nextDot + 1;
231
+ ellipsesBefore = false;
232
+ break;
233
+ }
234
+ if (nextSpace < 0) {
235
+ previewStart = 0;
236
+ ellipsesBefore = false;
237
+ break;
238
+ }
239
+ previewStart = nextSpace + 1;
240
+ }
241
+ for (var k = 0; k < 10; k++) {
242
+ var nextSpace = doc.content.indexOf(' ', previewEnd + 1);
243
+ var nextDot = doc.content.indexOf('.', previewEnd + 1);
244
+ if ((nextDot > 0) && (nextDot < nextSpace)) {
245
+ previewEnd = nextDot;
246
+ ellipsesAfter = false;
247
+ break;
248
+ }
249
+ if (nextSpace < 0) {
250
+ previewEnd = doc.content.length;
251
+ ellipsesAfter = false;
252
+ break;
253
+ }
254
+ previewEnd = nextSpace;
255
+ }
256
+ var preview = doc.content.substring(previewStart, start);
257
+ if (ellipsesBefore) {
258
+ preview = '... ' + preview;
259
+ }
260
+ preview += '<span class="search-result-highlight">' + doc.content.substring(start, end) + '</span>';
261
+ preview += doc.content.substring(end, previewEnd);
262
+ if (ellipsesAfter) {
263
+ preview += ' ...';
264
+ }
265
+
266
+ var resultPreview = document.createElement('div');
267
+ resultPreview.classList.add('search-result-preview');
268
+ resultPreview.innerHTML = preview;
269
+ resultLink.appendChild(resultPreview);
270
+ }
271
+ }
143
272
  }
144
273
  }
145
274
  });
146
275
 
147
- addEvent(searchInput, 'blur', function(){
276
+ jtd.addEvent(searchInput, 'blur', function(){
148
277
  setTimeout(function(){ hideResults() }, 300);
149
278
  });
150
279
  }
151
280
  }
152
281
 
282
+ // Focus
283
+
153
284
  function pageFocus() {
154
285
  var mainContent = document.querySelector('.js-main-content');
155
286
  mainContent.focus();
156
287
  }
157
288
 
289
+ // Switch theme
290
+
291
+ jtd.getTheme = function() {
292
+ var cssFileHref = document.querySelector('[rel="stylesheet"]').getAttribute('href');
293
+ return cssFileHref.substring(cssFileHref.lastIndexOf('-') + 1, cssFileHref.length - 4);
294
+ }
295
+
296
+ jtd.setTheme = function(theme) {
297
+ var cssFile = document.querySelector('[rel="stylesheet"]');
298
+ cssFile.setAttribute('href', '{{ "assets/css/just-the-docs-" | absolute_url }}' + theme + '.css');
299
+ }
158
300
 
159
301
  // Document ready
160
302
 
161
- function ready(){
162
- toggleNav();
303
+ jtd.onReady(function(){
304
+ initNav();
163
305
  pageFocus();
164
306
  if (typeof lunr !== 'undefined') {
165
307
  initSearch();
166
308
  }
167
- }
168
-
169
- // in case the document is already rendered
170
- if (document.readyState!='loading') ready();
171
- // modern browsers
172
- else if (document.addEventListener) document.addEventListener('DOMContentLoaded', ready);
173
- // IE <= 8
174
- else document.attachEvent('onreadystatechange', function(){
175
- if (document.readyState=='complete') ready();
176
309
  });
310
+
311
+ })(window.jtd = window.jtd || {});
312
+
313
+ {% include js/custom.js %}
@@ -1,12 +1,12 @@
1
1
  ---
2
2
  ---
3
3
  {
4
- {% for page in site.html_pages %}{% if page.search_exclude != true %}"{{ forloop.index0 }}": {
5
- "id": "{{ forloop.index0 }}",
4
+ {% assign comma = false %}
5
+ {% for page in site.html_pages %}{% if page.search_exclude != true %}{% if comma == true%},{% endif %}"{{ forloop.index0 }}": {
6
6
  "title": "{{ page.title | replace: '&amp;', '&' }}",
7
- "content": "{{ page.content | markdownify | strip_html | escape_once | remove: 'Table of contents' | remove: '```' | remove: '---' | replace: '\', ' ' | normalize_whitespace }}",
7
+ "content": "{{ page.content | markdownify | replace: '</h', ' . </h' | replace: '<hr', ' . <hr' | replace: '</p', ' . </p' | replace: '</ul', ' . </ul' | replace: '</tr', ' . </tr' | replace: '</li', ' | </li' | replace: '</td', ' | </td' | strip_html | escape_once | remove: 'Table of contents' | remove: '```' | remove: '---' | replace: '\', ' ' | replace: ' . . . ', ' . ' | replace: ' . . ', ' . ' | normalize_whitespace }}",
8
8
  "url": "{{ page.url | absolute_url }}",
9
9
  "relUrl": "{{ page.url }}"
10
- }{% unless forloop.last %},{% endunless %}
10
+ }{% assign comma = true %}
11
11
  {% endif %}{% endfor %}
12
12
  }