mirror of
https://github.com/squidfunk/mkdocs-material.git
synced 2024-06-14 11:52:32 +03:00
Restructured project
This commit is contained in:
parent
d1928cc31f
commit
e04387902c
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1
material/assets/javascripts/worker/packer.js.map
Normal file
1
material/assets/javascripts/worker/packer.js.map
Normal file
File diff suppressed because one or more lines are too long
@ -55,5 +55,5 @@
|
||||
* Copyright(c) 2015 Andreas Lubbe
|
||||
* Copyright(c) 2015 Tiancheng "Timothy" Gu
|
||||
* MIT Licensed
|
||||
*/var n=/["'&<>]/;e.exports=function(e){var t,r=""+e,i=n.exec(r);if(!i)return r;var s="",o=0,a=0;for(o=i.index;o<r.length;o++){switch(r.charCodeAt(o)){case 34:t=""";break;case 38:t="&";break;case 39:t="'";break;case 60:t="<";break;case 62:t=">";break;default:continue}a!==o&&(s+=r.substring(a,o)),a=o+1,s+=t}return a!==o?s+r.substring(a,o):s}},function(e,t,r){"use strict";const n=/[|\\{}()[\]^$+*?.-]/g;e.exports=e=>{if("string"!=typeof e)throw new TypeError("Expected a string");return e.replace(n,"\\$&")}},function(e,t,r){"use strict";r.r(t);var n=r(0),i=r(1),s=function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,i,s=r.call(e),o=[];try{for(;(void 0===t||t-- >0)&&!(n=s.next()).done;)o.push(n.value)}catch(e){i={error:e}}finally{try{n&&!n.done&&(r=s.return)&&r.call(s)}finally{if(i)throw i.error}}return o};var a=r(2),u=function(){return(u=Object.assign||function(e){for(var t,r=1,n=arguments.length;r<n;r++)for(var i in t=arguments[r])Object.prototype.hasOwnProperty.call(t,i)&&(e[i]=t[i]);return e}).apply(this,arguments)};var l,c,h=function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},d=function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,i,s=r.call(e),o=[];try{for(;(void 0===t||t-- >0)&&!(n=s.next()).done;)o.push(n.value)}catch(e){i={error:e}}finally{try{n&&!n.done&&(r=s.return)&&r.call(s)}finally{if(i)throw i.error}}return o},f=function(){for(var e=[],t=0;t<arguments.length;t++)e=e.concat(d(arguments[t]));return e},p=function(){function e(e){var t=e.config,r=e.docs,l=e.pipeline,c=e.index;this.documents=function(e){var t,r,n=new Map;try{for(var a=s(e),u=a.next();!u.done;u=a.next()){var l=u.value,c=o(l.location.split("#"),2),h=c[0],d=c[1],f=l.location,p=l.title,y=i(l.text).replace(/\s+(?=[,.:;!?])/g,"").replace(/\s+/g," ");if(d){var m=n.get(h);m.section?n.set(f,{location:f,title:p,text:y,article:m}):(m.title=l.title,m.text=y,m.section=!0)}else n.set(f,{location:f,title:p,text:y,section:!1})}}catch(e){t={error:e}}finally{try{u&&!u.done&&(r=a.return)&&r.call(a)}finally{if(t)throw t.error}}return n}(r),this.highlight=function(e){var t=new RegExp(e.separator,"img"),r=function(e,t,r){return t+"<em>"+r+"</em>"};return function(n){n=n.replace(/[\s*+-:~^]+/g," ").trim();var i=new RegExp("(^|"+e.separator+")("+a(n).replace(t,"|")+")","img");return function(e){return u(u({},e),{title:e.title.replace(i,r),text:e.text.replace(i,r)})}}}(t),this.index=void 0===c?n((function(){var e,t;l=l||{trimmer:!0,stopwords:!0},this.pipeline.reset(),l.trimmer&&this.pipeline.add(n.trimmer),l.stopwords&&this.pipeline.add(n.stopWordFilter),this.field("title",{boost:10}),this.field("text"),this.ref("location");try{for(var i=h(r),s=i.next();!s.done;s=i.next()){var o=s.value;this.add(o)}}catch(t){e={error:t}}finally{try{s&&!s.done&&(t=i.return)&&t.call(i)}finally{if(e)throw e.error}}})):n.Index.load("string"==typeof c?JSON.parse(c):c)}return e.prototype.search=function(e){var t=this;if(e)try{var r=this.index.search(e).reduce((function(e,r){var n=t.documents.get(r.ref);if(void 0!==n)if("article"in n){var i=n.article.location;e.set(i,f(e.get(i)||[],[r]))}else{i=n.location;e.set(i,e.get(i)||[])}return e}),new Map),n=this.highlight(e);return f(r).map((function(e){var r=d(e,2),i=r[0],s=r[1];return{article:n(t.documents.get(i)),sections:s.map((function(e){return n(t.documents.get(e.ref))}))}}))}catch(t){console.warn("Invalid query: "+e+" – see https://bit.ly/2s3ChXG")}return[]},e.prototype.toString=function(){return JSON.stringify(this.index)},e}();function y(e){switch(e.type){case l.SETUP:return c=new p(e.data),{type:l.DUMP,data:c.toString()};case l.QUERY:return{type:l.RESULT,data:c?c.search(e.data):[]};default:throw new TypeError("Invalid message type")}}!function(e){e[e.SETUP=0]="SETUP",e[e.DUMP=1]="DUMP",e[e.QUERY=2]="QUERY",e[e.RESULT=3]="RESULT"}(l||(l={})),r.d(t,"handler",(function(){return y})),addEventListener("message",(function(e){postMessage(y(e.data))}))}]);
|
||||
*/var n=/["'&<>]/;e.exports=function(e){var t,r=""+e,i=n.exec(r);if(!i)return r;var s="",o=0,a=0;for(o=i.index;o<r.length;o++){switch(r.charCodeAt(o)){case 34:t=""";break;case 38:t="&";break;case 39:t="'";break;case 60:t="<";break;case 62:t=">";break;default:continue}a!==o&&(s+=r.substring(a,o)),a=o+1,s+=t}return a!==o?s+r.substring(a,o):s}},function(e,t,r){"use strict";const n=/[|\\{}()[\]^$+*?.-]/g;e.exports=e=>{if("string"!=typeof e)throw new TypeError("Expected a string");return e.replace(n,"\\$&")}},function(e,t,r){"use strict";r.r(t);var n=r(0),i=r(1),s=function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,i,s=r.call(e),o=[];try{for(;(void 0===t||t-- >0)&&!(n=s.next()).done;)o.push(n.value)}catch(e){i={error:e}}finally{try{n&&!n.done&&(r=s.return)&&r.call(s)}finally{if(i)throw i.error}}return o};var a=r(2),u=function(){return(u=Object.assign||function(e){for(var t,r=1,n=arguments.length;r<n;r++)for(var i in t=arguments[r])Object.prototype.hasOwnProperty.call(t,i)&&(e[i]=t[i]);return e}).apply(this,arguments)};var l,c,h=function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},d=function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,i,s=r.call(e),o=[];try{for(;(void 0===t||t-- >0)&&!(n=s.next()).done;)o.push(n.value)}catch(e){i={error:e}}finally{try{n&&!n.done&&(r=s.return)&&r.call(s)}finally{if(i)throw i.error}}return o},f=function(){for(var e=[],t=0;t<arguments.length;t++)e=e.concat(d(arguments[t]));return e},p=function(){function e(e){var t=e.config,r=e.docs,l=e.pipeline,c=e.index;this.documents=function(e){var t,r,n=new Map;try{for(var a=s(e),u=a.next();!u.done;u=a.next()){var l=u.value,c=o(l.location.split("#"),2),h=c[0],d=c[1],f=l.location,p=l.title,y=i(l.text).replace(/\s+(?=[,.:;!?])/g,"").replace(/\s+/g," ");if(d){var m=n.get(h);m.linked?n.set(f,{location:f,title:p,text:y,parent:m}):(m.title=l.title,m.text=y,m.linked=!0)}else n.set(f,{location:f,title:p,text:y,linked:!1})}}catch(e){t={error:e}}finally{try{u&&!u.done&&(r=a.return)&&r.call(a)}finally{if(t)throw t.error}}return n}(r),this.highlight=function(e){var t=new RegExp(e.separator,"img"),r=function(e,t,r){return t+"<em>"+r+"</em>"};return function(n){n=n.replace(/[\s*+-:~^]+/g," ").trim();var i=new RegExp("(^|"+e.separator+")("+a(n).replace(t,"|")+")","img");return function(e){return u(u({},e),{title:e.title.replace(i,r),text:e.text.replace(i,r)})}}}(t),this.index=void 0===c?n((function(){var e,t;l=l||{trimmer:!0,stopwords:!0},this.pipeline.reset(),l.trimmer&&this.pipeline.add(n.trimmer),l.stopwords&&this.pipeline.add(n.stopWordFilter),this.field("title",{boost:10}),this.field("text"),this.ref("location");try{for(var i=h(r),s=i.next();!s.done;s=i.next()){var o=s.value;this.add(o)}}catch(t){e={error:t}}finally{try{s&&!s.done&&(t=i.return)&&t.call(i)}finally{if(e)throw e.error}}})):n.Index.load("string"==typeof c?JSON.parse(c):c)}return e.prototype.search=function(e){var t=this;if(e)try{var r=this.index.search(e).reduce((function(e,r){var n=t.documents.get(r.ref);if(void 0!==n)if("parent"in n){var i=n.parent.location;e.set(i,f(e.get(i)||[],[r]))}else{i=n.location;e.set(i,e.get(i)||[])}return e}),new Map),n=this.highlight(e);return f(r).map((function(e){var r=d(e,2),i=r[0],s=r[1];return{article:n(t.documents.get(i)),sections:s.map((function(e){return n(t.documents.get(e.ref))}))}}))}catch(t){console.warn("Invalid query: "+e+" – see https://bit.ly/2s3ChXG")}return[]},e.prototype.toString=function(){return JSON.stringify(this.index)},e}();function y(e){switch(e.type){case l.SETUP:return c=new p(e.data),{type:l.DUMP,data:c.toString()};case l.QUERY:return{type:l.RESULT,data:c?c.search(e.data):[]};default:throw new TypeError("Invalid message type")}}!function(e){e[e.SETUP=0]="SETUP",e[e.DUMP=1]="DUMP",e[e.QUERY=2]="QUERY",e[e.RESULT=3]="RESULT"}(l||(l={})),r.d(t,"handler",(function(){return y})),addEventListener("message",(function(e){postMessage(y(e.data))}))}]);
|
||||
//# sourceMappingURL=search.js.map
|
1
material/assets/javascripts/worker/search.js.map
Normal file
1
material/assets/javascripts/worker/search.js.map
Normal file
File diff suppressed because one or more lines are too long
@ -1002,8 +1002,7 @@ hr {
|
||||
margin: 0 0.2rem;
|
||||
overflow-y: auto;
|
||||
-webkit-backface-visibility: hidden;
|
||||
backface-visibility: hidden;
|
||||
-webkit-overflow-scrolling: touch; }
|
||||
backface-visibility: hidden; }
|
||||
.md-sidebar__scrollwrap::-webkit-scrollbar {
|
||||
width: 0.2rem;
|
||||
height: 0.2rem; }
|
||||
@ -2542,7 +2541,9 @@ hr {
|
||||
margin-right: 100%;
|
||||
margin-left: initial;
|
||||
-webkit-transform: translate(100%, 0);
|
||||
transform: translate(100%, 0); } }
|
||||
transform: translate(100%, 0); }
|
||||
.md-sidebar--secondary .md-sidebar__scrollwrap {
|
||||
-webkit-overflow-scrolling: touch; } }
|
||||
|
||||
@media only screen and (min-width: 76.25em) {
|
||||
.md-content {
|
||||
|
File diff suppressed because one or more lines are too long
2
material/assets/stylesheets/app.min.css
vendored
2
material/assets/stylesheets/app.min.css
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -31,7 +31,7 @@
|
||||
<meta name="author" content="{{ config.site_author }}">
|
||||
{% endif %}
|
||||
<link rel="shortcut icon" href="{{ config.theme.favicon | url }}">
|
||||
<meta name="generator" content="mkdocs-{{ mkdocs_version }}, mkdocs-material-4.6.0">
|
||||
<meta name="generator" content="mkdocs-{{ mkdocs_version }}, mkdocs-material-5.0.0-preview">
|
||||
{% endblock %}
|
||||
{% block htmltitle %}
|
||||
{% if page and page.meta and page.meta.title %}
|
||||
@ -236,7 +236,7 @@
|
||||
{%- endfor -%}
|
||||
{{ translations | tojson }}
|
||||
</script>
|
||||
<script>app=initialize({base:"{{ base_url }}",worker:{search:"{{ 'assets/javascripts/search.js' | url }}",packer:"{{ 'assets/javascripts/packer.js' | url }}"}})</script>
|
||||
<script>app=initialize({base:"{{ base_url }}",worker:{search:"{{ 'assets/javascripts/worker/search.js' | url }}",packer:"{{ 'assets/javascripts/worker/packer.js' | url }}"}})</script>
|
||||
{% for path in config["extra_javascript"] %}
|
||||
<script src="{{ path | url }}"></script>
|
||||
{% endfor %}
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "mkdocs-material",
|
||||
"version": "4.6.0",
|
||||
"version": "5.0.0-preview",
|
||||
"description": "A Material Design theme for MkDocs",
|
||||
"keywords": [
|
||||
"mkdocs",
|
||||
|
@ -27,9 +27,9 @@ import { Observable, defer, of } from "rxjs"
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Header
|
||||
* Header state
|
||||
*/
|
||||
export interface Header {
|
||||
export interface HeaderState {
|
||||
sticky: boolean /* Header stickyness */
|
||||
height: number /* Header visible height */
|
||||
}
|
||||
@ -46,11 +46,11 @@ export interface Header {
|
||||
*
|
||||
* @param el - Header element
|
||||
*
|
||||
* @return Header observable
|
||||
* @return Header state observable
|
||||
*/
|
||||
export function watchHeader(
|
||||
el: HTMLElement
|
||||
): Observable<Header> {
|
||||
): Observable<HeaderState> {
|
||||
return defer(() => {
|
||||
const sticky = getComputedStyle(el)
|
||||
.getPropertyValue("position") === "fixed"
|
||||
|
@ -30,7 +30,7 @@ import {
|
||||
|
||||
import { Agent, ViewportOffset } from "utilities"
|
||||
|
||||
import { Header } from "../_"
|
||||
import { HeaderState } from "../_"
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Helper types
|
||||
@ -40,7 +40,7 @@ import { Header } from "../_"
|
||||
* Options
|
||||
*/
|
||||
interface Options {
|
||||
header$: Observable<Header> /* Header observable */
|
||||
header$: Observable<HeaderState> /* Header state observable */
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
@ -59,7 +59,7 @@ interface Options {
|
||||
*
|
||||
* @return Viewport offset observable
|
||||
*/
|
||||
export function watchHeaderOffsetToTopOf(
|
||||
export function watchViewportOffsetFromTopOf(
|
||||
el: HTMLElement, { viewport }: Agent, { header$ }: Options
|
||||
): Observable<ViewportOffset> {
|
||||
|
||||
@ -91,7 +91,7 @@ export function watchHeaderOffsetToTopOf(
|
||||
*
|
||||
* @return Viewport offset observable
|
||||
*/
|
||||
export function watchHeaderOffsetToBottomOf(
|
||||
export function watchViewportOffsetFromBottomOf(
|
||||
el: HTMLElement, { viewport }: Agent, { header$ }: Options
|
||||
): Observable<ViewportOffset> {
|
||||
|
||||
|
@ -34,7 +34,7 @@ import {
|
||||
|
||||
import { resetHeaderShadow, setHeaderShadow } from "actions"
|
||||
|
||||
import { Main } from "../../main"
|
||||
import { MainState } from "../../main"
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Functions
|
||||
@ -49,7 +49,7 @@ import { Main } from "../../main"
|
||||
*/
|
||||
export function paintHeaderShadow(
|
||||
el: HTMLElement
|
||||
): MonoTypeOperatorFunction<Main> {
|
||||
): MonoTypeOperatorFunction<MainState> {
|
||||
return pipe(
|
||||
distinctUntilKeyChanged("active"),
|
||||
|
||||
|
@ -26,16 +26,16 @@ import { map, shareReplay } from "rxjs/operators"
|
||||
import { switchMapIf } from "extensions"
|
||||
import { Agent, paintHidden } from "utilities"
|
||||
|
||||
import { Header, watchHeaderOffsetToTopOf } from "../header"
|
||||
import { HeaderState, watchViewportOffsetFromTopOf } from "../header"
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Types
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Hero
|
||||
* Hero state
|
||||
*/
|
||||
export interface Hero {
|
||||
export interface HeroState {
|
||||
hidden: boolean /* Whether the hero is hidden */
|
||||
}
|
||||
|
||||
@ -47,7 +47,7 @@ export interface Hero {
|
||||
* Options
|
||||
*/
|
||||
interface Options {
|
||||
header$: Observable<Header> /* Header observable */
|
||||
header$: Observable<HeaderState> /* Header state observable */
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
@ -55,22 +55,20 @@ interface Options {
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Setup hero from source observable
|
||||
* Watch hero
|
||||
*
|
||||
* @param el - Hero element
|
||||
* @param agent - Agent
|
||||
* @param options - Options
|
||||
*
|
||||
* @return Operator function
|
||||
* @return Hero state
|
||||
*/
|
||||
export function setupHero(
|
||||
agent: Agent, { header$ }: Options
|
||||
): OperatorFunction<HTMLElement, Hero> {
|
||||
const { media } = agent
|
||||
return pipe(
|
||||
switchMapIf(media.screen$, el => {
|
||||
export function watchHero(
|
||||
el: HTMLElement, agent: Agent, { header$ }: Options
|
||||
): Observable<HeroState> {
|
||||
|
||||
/* Watch and paint visibility */
|
||||
const hidden$ = watchHeaderOffsetToTopOf(el, agent, { header$ })
|
||||
const hidden$ = watchViewportOffsetFromTopOf(el, agent, { header$ })
|
||||
.pipe(
|
||||
paintHidden(el, 20)
|
||||
)
|
||||
@ -80,7 +78,24 @@ export function setupHero(
|
||||
.pipe(
|
||||
map(hidden => ({ hidden }))
|
||||
)
|
||||
}),
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Mount hero from source observable
|
||||
*
|
||||
* @param agent - Agent
|
||||
* @param options - Options
|
||||
*
|
||||
* @return Operator function
|
||||
*/
|
||||
export function mountHero(
|
||||
agent: Agent, options: Options
|
||||
): OperatorFunction<HTMLElement, HeroState> {
|
||||
const { media } = agent
|
||||
return pipe(
|
||||
switchMapIf(media.screen$, el => watchHero(el, agent, options)),
|
||||
shareReplay(1)
|
||||
)
|
||||
}
|
||||
|
@ -31,16 +31,16 @@ import {
|
||||
|
||||
import { Agent } from "utilities"
|
||||
|
||||
import { Header } from "../../header"
|
||||
import { HeaderState } from "../../header"
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Types
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Main area
|
||||
* Main area state
|
||||
*/
|
||||
export interface Main {
|
||||
export interface MainState {
|
||||
offset: number /* Main area top offset */
|
||||
height: number /* Main area visible height */
|
||||
active: boolean /* Scrolled past top offset */
|
||||
@ -54,7 +54,7 @@ export interface Main {
|
||||
* Options
|
||||
*/
|
||||
interface Options {
|
||||
header$: Observable<Header> /* Header observable */
|
||||
header$: Observable<HeaderState> /* Header state observable */
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
@ -62,23 +62,21 @@ interface Options {
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Setup main area from source observable
|
||||
* Watch main area
|
||||
*
|
||||
* This function returns an observable that computes the visual parameters of
|
||||
* the main area from the viewport height and vertical offset, as well as the
|
||||
* height of the header element. The height of the main area is corrected by
|
||||
* the height of the header (if fixed) and footer element.
|
||||
* the main area which depends on the viewport height and vertical offset, as
|
||||
* well as the height of the header element, if the header is fixed.
|
||||
*
|
||||
* @param el - Main area element
|
||||
* @param agent - Agent
|
||||
* @param options - Options
|
||||
*
|
||||
* @return Operator function
|
||||
* @return Main area state observable
|
||||
*/
|
||||
export function setupMain(
|
||||
{ viewport }: Agent, { header$ }: Options
|
||||
): OperatorFunction<HTMLElement, Main> {
|
||||
return pipe(
|
||||
switchMap(el => {
|
||||
export function watchMain(
|
||||
el: HTMLElement, { viewport }: Agent, { header$ }: Options
|
||||
): Observable<MainState> {
|
||||
|
||||
/* Compute necessary adjustment for header */
|
||||
const adjust$ = header$
|
||||
@ -119,7 +117,23 @@ export function setupMain(
|
||||
active
|
||||
}))
|
||||
)
|
||||
}),
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Mount main area from source observable
|
||||
*
|
||||
* @param agent - Agent
|
||||
* @param options - Options
|
||||
*
|
||||
* @return Operator function
|
||||
*/
|
||||
export function mountMain(
|
||||
agent: Agent, options: Options
|
||||
): OperatorFunction<HTMLElement, MainState> {
|
||||
return pipe(
|
||||
switchMap(el => watchMain(el, agent, options)),
|
||||
shareReplay(1)
|
||||
)
|
||||
}
|
||||
|
@ -45,16 +45,16 @@ import {
|
||||
} from "actions"
|
||||
import { Agent } from "utilities"
|
||||
|
||||
import { Main } from "../main"
|
||||
import { MainState } from "../_"
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Types
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Sidebar
|
||||
* Sidebar state
|
||||
*/
|
||||
export interface Sidebar {
|
||||
export interface SidebarState {
|
||||
height: number /* Sidebar height */
|
||||
lock: boolean /* Sidebar lock */
|
||||
}
|
||||
@ -67,7 +67,7 @@ export interface Sidebar {
|
||||
* Options
|
||||
*/
|
||||
interface Options {
|
||||
main$: Observable<Main> /* Main area observable */
|
||||
main$: Observable<MainState> /* Main area state observable */
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
@ -78,19 +78,19 @@ interface Options {
|
||||
* Watch sidebar
|
||||
*
|
||||
* This function returns an observable that computes the visual parameters of
|
||||
* the given element (a sidebar) from the vertical viewport offset, as well as
|
||||
* the height of the main area. When the page is scrolled beyond the header,
|
||||
* the sidebar is locked and fills the remaining space.
|
||||
* the sidebar which depends on the vertical viewport offset, as well as the
|
||||
* height of the main area. When the page is scrolled beyond the header, the
|
||||
* sidebar is locked and fills the remaining space.
|
||||
*
|
||||
* @param el - Sidebar element
|
||||
* @param agent - Agent
|
||||
* @param options - Options
|
||||
*
|
||||
* @return Sidebar observable
|
||||
* @return Sidebar state observable
|
||||
*/
|
||||
export function watchSidebar(
|
||||
el: HTMLElement, { viewport }: Agent, { main$ }: Options
|
||||
): Observable<Sidebar> {
|
||||
): Observable<SidebarState> {
|
||||
|
||||
/* Adjust for internal main area offset */
|
||||
const adjust = parseFloat(
|
||||
@ -116,7 +116,7 @@ export function watchSidebar(
|
||||
return combineLatest([height$, lock$])
|
||||
.pipe(
|
||||
map(([height, lock]) => ({ height, lock })),
|
||||
distinctUntilChanged<Sidebar>(equals),
|
||||
distinctUntilChanged<SidebarState>(equals),
|
||||
shareReplay(1)
|
||||
)
|
||||
}
|
||||
@ -132,7 +132,7 @@ export function watchSidebar(
|
||||
*/
|
||||
export function paintSidebar(
|
||||
el: HTMLElement
|
||||
): MonoTypeOperatorFunction<Sidebar> {
|
||||
): MonoTypeOperatorFunction<SidebarState> {
|
||||
return pipe(
|
||||
|
||||
/* Defer repaint to next animation frame */
|
||||
|
@ -27,8 +27,8 @@ import { switchMapIf } from "extensions"
|
||||
import { Agent } from "utilities"
|
||||
|
||||
import {
|
||||
Main,
|
||||
Sidebar,
|
||||
MainState,
|
||||
SidebarState,
|
||||
paintSidebar,
|
||||
watchSidebar
|
||||
} from "../../main"
|
||||
@ -38,10 +38,10 @@ import {
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Navigation
|
||||
* Navigation state
|
||||
*/
|
||||
export interface Navigation {
|
||||
sidebar: Sidebar /* Sidebar */
|
||||
export interface NavigationState {
|
||||
sidebar: SidebarState /* Sidebar state */
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
@ -52,7 +52,7 @@ export interface Navigation {
|
||||
* Options
|
||||
*/
|
||||
interface Options {
|
||||
main$: Observable<Main> /* Main observable */
|
||||
main$: Observable<MainState> /* Main area state observable */
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
@ -60,19 +60,17 @@ interface Options {
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Setup navigation from source observable
|
||||
* Watch navigation
|
||||
*
|
||||
* @param el - Navigation element
|
||||
* @param agent - Agent
|
||||
* @param options - Options
|
||||
*
|
||||
* @return Operator function
|
||||
* @return Navigation state observable
|
||||
*/
|
||||
export function setupNavigation(
|
||||
agent: Agent, { main$ }: Options
|
||||
): OperatorFunction<HTMLElement, Navigation> {
|
||||
const { media } = agent
|
||||
return pipe(
|
||||
switchMapIf(media.screen$, el => {
|
||||
export function watchNavigation(
|
||||
el: HTMLElement, agent: Agent, { main$ }: Options
|
||||
): Observable<NavigationState> {
|
||||
|
||||
/* Watch and paint sidebar */
|
||||
const sidebar$ = watchSidebar(el, agent, { main$ })
|
||||
@ -85,7 +83,24 @@ export function setupNavigation(
|
||||
.pipe(
|
||||
map(sidebar => ({ sidebar }))
|
||||
)
|
||||
}),
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Mount navigation from source observable
|
||||
*
|
||||
* @param agent - Agent
|
||||
* @param options - Options
|
||||
*
|
||||
* @return Operator function
|
||||
*/
|
||||
export function mountNavigation(
|
||||
agent: Agent, options: Options
|
||||
): OperatorFunction<HTMLElement, NavigationState> {
|
||||
const { media } = agent
|
||||
return pipe(
|
||||
switchMapIf(media.screen$, el => watchNavigation(el, agent, options)),
|
||||
shareReplay(1)
|
||||
)
|
||||
}
|
||||
|
@ -20,7 +20,6 @@
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
// tslint:disable-next-line
|
||||
// export * from "./query"
|
||||
export * from "./query"
|
||||
export * from "./reset"
|
||||
export * from "./result"
|
||||
|
@ -19,3 +19,71 @@
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
import { Observable, combineLatest, fromEvent } from "rxjs"
|
||||
import {
|
||||
distinctUntilChanged,
|
||||
map,
|
||||
shareReplay,
|
||||
startWith
|
||||
} from "rxjs/operators"
|
||||
|
||||
import { watchElementFocus } from "utilities"
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Types
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Search query state
|
||||
*/
|
||||
export interface SearchQueryState {
|
||||
value: string /* Query value */
|
||||
focus: boolean /* Query focus state */
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Helper types
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Options
|
||||
*/
|
||||
interface Options {
|
||||
prepare(value: string): string /* Preparation function */
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Functions
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Watch search query
|
||||
*
|
||||
* @param el - Search query element
|
||||
* @param options - Options
|
||||
*
|
||||
* @return Search query state observable
|
||||
*/
|
||||
export function watchSearchQuery(
|
||||
el: HTMLInputElement, { prepare }: Options
|
||||
): Observable<SearchQueryState> {
|
||||
|
||||
/* Intercept keyboard events */
|
||||
const value$ = fromEvent(el, "keyup")
|
||||
.pipe(
|
||||
map(() => prepare(el.value)),
|
||||
startWith(""),
|
||||
distinctUntilChanged()
|
||||
)
|
||||
|
||||
/* Intercept focus events */
|
||||
const focus$ = watchElementFocus(el)
|
||||
|
||||
/* Combine into a single hot observable */
|
||||
return combineLatest([value$, focus$])
|
||||
.pipe(
|
||||
map(([value, focus]) => ({ value, focus })),
|
||||
shareReplay(1)
|
||||
)
|
||||
}
|
||||
|
@ -36,9 +36,9 @@ import { mapTo } from "rxjs/operators"
|
||||
*/
|
||||
export function watchSearchReset(
|
||||
el: HTMLElement
|
||||
): Observable<boolean> {
|
||||
): Observable<void> {
|
||||
return fromEvent(el, "click")
|
||||
.pipe(
|
||||
mapTo(true)
|
||||
mapTo(undefined)
|
||||
)
|
||||
}
|
||||
|
@ -52,34 +52,53 @@ interface Options {
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Setup search result from source observable
|
||||
* Watch search result
|
||||
*
|
||||
* @param el - Search result element
|
||||
* @param agent - Agent
|
||||
* @param options - Options
|
||||
*
|
||||
* @return Operator function
|
||||
* @return Search result state observable
|
||||
*/
|
||||
export function setupSearchResult(
|
||||
agent: Agent, { result$, query$ }: Options
|
||||
): OperatorFunction<HTMLElement, SearchResult[]> {
|
||||
return pipe(
|
||||
switchMap(el => {
|
||||
const parent = el.parentElement!
|
||||
export function watchSearchResult(
|
||||
el: HTMLElement, agent: Agent, { result$, query$ }: Options
|
||||
): Observable<SearchResult[]> {
|
||||
const container = el.parentElement!
|
||||
|
||||
/* Compute whether more elements need to be rendered */
|
||||
const render$ = watchElementOffset(parent, agent)
|
||||
/* Compute whether there are more search results elements */
|
||||
const render$ = watchElementOffset(container, agent)
|
||||
.pipe(
|
||||
map(({ y }) => y >= parent.scrollHeight - parent.offsetHeight - 16),
|
||||
map(({ y }) => y >= container.scrollHeight - container.offsetHeight - 16),
|
||||
distinctUntilChanged(),
|
||||
filter(identity)
|
||||
)
|
||||
|
||||
// combine into search result observable...
|
||||
|
||||
/* Paint search results */
|
||||
return result$
|
||||
.pipe(
|
||||
tap(x => { console.log("watchSearchResult", x) }),
|
||||
paintSearchResultMeta(el, { query$ }),
|
||||
paintSearchResultList(el, { render$ })
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Mount search result from source observable
|
||||
*
|
||||
* @param agent - Agent
|
||||
* @param options - Options
|
||||
*
|
||||
* @return Operator function
|
||||
*/
|
||||
export function mountSearchResult(
|
||||
agent: Agent, options: Options
|
||||
): OperatorFunction<HTMLElement, SearchResult[]> {
|
||||
return pipe(
|
||||
switchMap(el => watchSearchResult(el, agent, options)),
|
||||
shareReplay(1)
|
||||
)
|
||||
}
|
||||
|
@ -68,7 +68,7 @@ interface Options {
|
||||
export function paintSearchResultList(
|
||||
el: HTMLElement, { render$ }: Options
|
||||
): MonoTypeOperatorFunction<SearchResult[]> {
|
||||
const parent = el.parentElement!
|
||||
const container = el.parentElement!
|
||||
const list = getElement(".md-search-result__list", el)!
|
||||
return pipe(
|
||||
switchMap(result => render$
|
||||
@ -79,7 +79,7 @@ export function paintSearchResultList(
|
||||
scan(index => {
|
||||
while (index < result.length) {
|
||||
addToSearchResultList(list, renderSearchResult(result[index++]))
|
||||
if (parent.scrollHeight - parent.offsetHeight > 16)
|
||||
if (container.scrollHeight - container.offsetHeight > 16)
|
||||
break
|
||||
}
|
||||
return index
|
||||
|
@ -26,16 +26,16 @@ import { map, shareReplay } from "rxjs/operators"
|
||||
import { switchMapIf } from "extensions"
|
||||
import { Agent, paintHidden } from "utilities"
|
||||
|
||||
import { Header, watchHeaderOffsetToTopOf } from "../header"
|
||||
import { HeaderState, watchViewportOffsetFromTopOf } from "../header"
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Types
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Tabs
|
||||
* Tabs state
|
||||
*/
|
||||
export interface Tabs {
|
||||
export interface TabsState {
|
||||
hidden: boolean /* Whether the tabs are hidden */
|
||||
}
|
||||
|
||||
@ -47,7 +47,7 @@ export interface Tabs {
|
||||
* Options
|
||||
*/
|
||||
interface Options {
|
||||
header$: Observable<Header> /* Header observable */
|
||||
header$: Observable<HeaderState> /* Header state observable */
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
@ -55,22 +55,23 @@ interface Options {
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Setup tabs from source observable
|
||||
* Watch tabs
|
||||
*
|
||||
* This function returns an observable that computes the visual parameters of
|
||||
* the tabs, currently only denoting whether the tabs are hidden or not.
|
||||
*
|
||||
* @param el - Tabs element
|
||||
* @param agent - Agent
|
||||
* @param options - Options
|
||||
*
|
||||
* @return Operator function
|
||||
* @return Tabs state
|
||||
*/
|
||||
export function setupTabs(
|
||||
agent: Agent, { header$ }: Options
|
||||
): OperatorFunction<HTMLElement, Tabs> {
|
||||
const { media } = agent
|
||||
return pipe(
|
||||
switchMapIf(media.screen$, el => {
|
||||
export function watchTabs(
|
||||
el: HTMLElement, agent: Agent, { header$ }: Options
|
||||
): Observable<TabsState> {
|
||||
|
||||
/* Watch and paint visibility */
|
||||
const hidden$ = watchHeaderOffsetToTopOf(el, agent, { header$ })
|
||||
const hidden$ = watchViewportOffsetFromTopOf(el, agent, { header$ })
|
||||
.pipe(
|
||||
paintHidden(el, 8)
|
||||
)
|
||||
@ -80,7 +81,24 @@ export function setupTabs(
|
||||
.pipe(
|
||||
map(hidden => ({ hidden }))
|
||||
)
|
||||
}),
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Mount tabs from source observable
|
||||
*
|
||||
* @param agent - Agent
|
||||
* @param options - Options
|
||||
*
|
||||
* @return Operator function
|
||||
*/
|
||||
export function mountTabs(
|
||||
agent: Agent, options: Options
|
||||
): OperatorFunction<HTMLElement, TabsState> {
|
||||
const { media } = agent
|
||||
return pipe(
|
||||
switchMapIf(media.screen$, el => watchTabs(el, agent, options)),
|
||||
shareReplay(1)
|
||||
)
|
||||
}
|
||||
|
@ -26,10 +26,10 @@ import { map, shareReplay } from "rxjs/operators"
|
||||
import { switchMapIf } from "extensions"
|
||||
import { Agent, getElements } from "utilities"
|
||||
|
||||
import { Header } from "../../header"
|
||||
import { HeaderState } from "../../header"
|
||||
import {
|
||||
Main,
|
||||
Sidebar,
|
||||
MainState,
|
||||
SidebarState,
|
||||
paintSidebar,
|
||||
watchSidebar
|
||||
} from "../../main"
|
||||
@ -44,10 +44,10 @@ import {
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Table of contents
|
||||
* Table of contents state
|
||||
*/
|
||||
export interface TableOfContents {
|
||||
sidebar: Sidebar /* Sidebar */
|
||||
export interface TableOfContentsState {
|
||||
sidebar: SidebarState /* Sidebar state */
|
||||
anchors: AnchorList /* Anchor list */
|
||||
}
|
||||
|
||||
@ -59,8 +59,8 @@ export interface TableOfContents {
|
||||
* Options
|
||||
*/
|
||||
interface Options {
|
||||
header$: Observable<Header> /* Header observable */
|
||||
main$: Observable<Main> /* Main observable */
|
||||
header$: Observable<HeaderState> /* Header state observable */
|
||||
main$: Observable<MainState> /* Main area state observable */
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
@ -68,19 +68,17 @@ interface Options {
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Setup table of contents from source observable
|
||||
* Watch table of contents
|
||||
*
|
||||
* @param el - Table of contents element
|
||||
* @param agent - Agent
|
||||
* @param options - Options
|
||||
*
|
||||
* @return Operator function
|
||||
* @return Table of contents state observable
|
||||
*/
|
||||
export function setupTableOfContents(
|
||||
agent: Agent, { header$, main$ }: Options
|
||||
): OperatorFunction<HTMLElement, TableOfContents> {
|
||||
const { media } = agent
|
||||
return pipe(
|
||||
switchMapIf(media.tablet$, el => {
|
||||
export function watchTableOfContents(
|
||||
el: HTMLElement, agent: Agent, { header$, main$ }: Options
|
||||
): Observable<TableOfContentsState> {
|
||||
|
||||
/* Watch and paint sidebar */
|
||||
const sidebar$ = watchSidebar(el, agent, { main$ })
|
||||
@ -100,7 +98,24 @@ export function setupTableOfContents(
|
||||
.pipe(
|
||||
map(([sidebar, anchors]) => ({ sidebar, anchors }))
|
||||
)
|
||||
}),
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Mount table of contents from source observable
|
||||
*
|
||||
* @param agent - Agent
|
||||
* @param options - Options
|
||||
*
|
||||
* @return Operator function
|
||||
*/
|
||||
export function mountTableOfContents(
|
||||
agent: Agent, options: Options
|
||||
): OperatorFunction<HTMLElement, TableOfContentsState> {
|
||||
const { media } = agent
|
||||
return pipe(
|
||||
switchMapIf(media.tablet$, el => watchTableOfContents(el, agent, options)),
|
||||
shareReplay(1)
|
||||
)
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ import {
|
||||
} from "actions"
|
||||
import { Agent, getElement } from "utilities"
|
||||
|
||||
import { Header } from "../../header"
|
||||
import { HeaderState } from "../../header"
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Types
|
||||
@ -69,7 +69,7 @@ export interface AnchorList {
|
||||
* Options
|
||||
*/
|
||||
interface Options {
|
||||
header$: Observable<Header> /* Header observable */
|
||||
header$: Observable<HeaderState> /* Header state observable */
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
|
@ -21,4 +21,3 @@
|
||||
*/
|
||||
|
||||
export * from "./_"
|
||||
export * from "./anchor"
|
||||
|
@ -55,25 +55,25 @@ export interface SearchIndexDocument {
|
||||
}
|
||||
|
||||
/**
|
||||
* Search index options
|
||||
* Search index pipeline
|
||||
*/
|
||||
export interface SearchIndexOptions {
|
||||
pipeline: {
|
||||
export interface SearchIndexPipeline {
|
||||
trimmer: boolean /* Add trimmer to pipeline */
|
||||
stopwords: boolean /* Add stopword filter to pipeline */
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Search index
|
||||
* Search index options
|
||||
*
|
||||
* This interfaces describes the format of the `search_index.json` file which
|
||||
* is automatically built by the MkDocs search plugin.
|
||||
*/
|
||||
export interface SearchIndex {
|
||||
export interface SearchIndexOptions {
|
||||
config: SearchIndexConfig /* Search index configuration */
|
||||
docs: SearchIndexDocument[] /* Search index documents */
|
||||
options?: SearchIndexOptions /* Search index options */
|
||||
pipeline?: SearchIndexPipeline /* Search index pipeline */
|
||||
index?: object | string /* Prebuilt or serialized index */
|
||||
}
|
||||
|
||||
@ -87,25 +87,11 @@ export interface SearchResult {
|
||||
sections: SectionDocument[] /* Section documents */
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Data
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Default options
|
||||
*/
|
||||
const defaultOptions: SearchIndexOptions = {
|
||||
pipeline: {
|
||||
trimmer: true,
|
||||
stopwords: true
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Class
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
export class Search {
|
||||
export class SearchIndex {
|
||||
|
||||
/**
|
||||
* Search document mapping
|
||||
@ -130,17 +116,19 @@ export class Search {
|
||||
/**
|
||||
* Create a search index
|
||||
*
|
||||
* @param index - Search index
|
||||
* @param options - Options
|
||||
*/
|
||||
public constructor({ config, docs, options, index }: SearchIndex) {
|
||||
public constructor({ config, docs, pipeline, index }: SearchIndexOptions) {
|
||||
this.documents = setupSearchDocumentMap(docs)
|
||||
this.highlight = setupSearchHighlighter(config)
|
||||
|
||||
/* If no index was given, create it */
|
||||
if (typeof index === "undefined") {
|
||||
this.index = lunr(function() {
|
||||
const { pipeline } = options || defaultOptions
|
||||
pipeline = pipeline || {
|
||||
trimmer: true,
|
||||
stopwords: true
|
||||
}
|
||||
|
||||
/* Remove stemmer, as it cripples search experience */
|
||||
this.pipeline.reset()
|
||||
@ -194,8 +182,8 @@ export class Search {
|
||||
.reduce((results, result) => {
|
||||
const document = this.documents.get(result.ref)
|
||||
if (typeof document !== "undefined") {
|
||||
if ("article" in document) {
|
||||
const ref = document.article.location
|
||||
if ("parent" in document) {
|
||||
const ref = document.parent.location
|
||||
results.set(ref, [...results.get(ref) || [], result])
|
||||
} else {
|
||||
const ref = document.location
|
||||
@ -228,7 +216,7 @@ export class Search {
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialize index
|
||||
* Serialize search index
|
||||
*
|
||||
* @return String representation
|
||||
*/
|
||||
|
@ -32,14 +32,14 @@ import { SearchIndexDocument } from "../_"
|
||||
* A top-level article
|
||||
*/
|
||||
export interface ArticleDocument extends SearchIndexDocument {
|
||||
section: boolean /* Whether the section was linked */
|
||||
linked: boolean /* Whether the section was linked */
|
||||
}
|
||||
|
||||
/**
|
||||
* A section of an article
|
||||
*/
|
||||
export interface SectionDocument extends SearchIndexDocument {
|
||||
article: ArticleDocument /* Parent article */
|
||||
parent: ArticleDocument /* Parent article */
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
@ -85,22 +85,22 @@ export function setupSearchDocumentMap(
|
||||
|
||||
/* Handle section */
|
||||
if (hash) {
|
||||
const article = documents.get(path) as ArticleDocument
|
||||
const parent = documents.get(path) as ArticleDocument
|
||||
|
||||
/* Ignore first section, override article */
|
||||
if (!article.section) {
|
||||
article.title = doc.title
|
||||
article.text = text
|
||||
article.section = true
|
||||
if (!parent.linked) {
|
||||
parent.title = doc.title
|
||||
parent.text = text
|
||||
parent.linked = true
|
||||
|
||||
/* Add subsequent section */
|
||||
} else {
|
||||
documents.set(location, { location, title, text, article })
|
||||
documents.set(location, { location, title, text, parent })
|
||||
}
|
||||
|
||||
/* Add article */
|
||||
} else {
|
||||
documents.set(location, { location, title, text, section: false })
|
||||
documents.set(location, { location, title, text, linked: false })
|
||||
}
|
||||
}
|
||||
return documents
|
||||
|
@ -21,4 +21,8 @@
|
||||
*/
|
||||
|
||||
export * from "./_"
|
||||
export * from "./document"
|
||||
export {
|
||||
ArticleDocument,
|
||||
SearchDocument,
|
||||
SectionDocument
|
||||
} from "./document"
|
||||
|
@ -20,4 +20,4 @@
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
export * from "./_"
|
||||
export * from "./result"
|
||||
|
@ -44,7 +44,7 @@ const css = {
|
||||
/**
|
||||
* Render a search result
|
||||
*
|
||||
* @param article - Search result
|
||||
* @param result - Search result
|
||||
*
|
||||
* @return HTML element
|
||||
*/
|
23
src/assets/javascripts/templates/search/result/index.ts
Normal file
23
src/assets/javascripts/templates/search/result/index.ts
Normal file
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2019 Martin Donath <martin.donath@squidfunk.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
export * from "./_"
|
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2019 Martin Donath <martin.donath@squidfunk.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
import { Observable, fromEvent, merge } from "rxjs"
|
||||
import { mapTo, shareReplay, startWith } from "rxjs/operators"
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Functions
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Watch element focus
|
||||
*
|
||||
* @param el - Element
|
||||
*
|
||||
* @return Element focus observable
|
||||
*/
|
||||
export function watchElementFocus(
|
||||
el: HTMLElement
|
||||
): Observable<boolean> {
|
||||
const focus$ = fromEvent(el, "focus")
|
||||
const blur$ = fromEvent(el, "blur")
|
||||
|
||||
/* Map events to boolean state */
|
||||
return merge(
|
||||
focus$.pipe(mapTo(true)),
|
||||
blur$.pipe(mapTo(false))
|
||||
)
|
||||
.pipe(
|
||||
startWith(el === document.activeElement),
|
||||
shareReplay(1)
|
||||
)
|
||||
}
|
@ -21,4 +21,5 @@
|
||||
*/
|
||||
|
||||
export * from "./_"
|
||||
export * from "./focus"
|
||||
export * from "./offset"
|
||||
|
@ -68,7 +68,7 @@ export function watchWorker<T extends WorkerMessage>(
|
||||
worker: Worker, { send$ }: Options<T>
|
||||
): Observable<T> {
|
||||
|
||||
/* Observable for messages from web worker */
|
||||
/* Intercept messages from web worker */
|
||||
const recv$ = fromEvent(worker, "message")
|
||||
.pipe(
|
||||
pluck<Event, T>("data"),
|
||||
|
@ -27,6 +27,26 @@ import { pluck } from "rxjs/operators"
|
||||
* Functions
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Set toggle
|
||||
*
|
||||
* Simulating a click event seems to be the most cross-browser compatible way
|
||||
* of changing the value while also emitting a `change` event. Before, Material
|
||||
* used `CustomEvent` to programatically change the value of a toggle, but this
|
||||
* is a much simpler and cleaner solution.
|
||||
*
|
||||
* @param el - Toggle element
|
||||
* @param value - Toggle value
|
||||
*/
|
||||
export function setToggle(
|
||||
el: HTMLInputElement, value: boolean
|
||||
): void {
|
||||
if (el.checked !== value)
|
||||
el.click()
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Watch toggle
|
||||
*
|
||||
|
@ -20,7 +20,7 @@
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
import { SearchIndex, SearchResult } from "modules"
|
||||
import { SearchIndexOptions, SearchResult } from "modules"
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Types
|
||||
@ -43,7 +43,7 @@ export const enum SearchMessageType {
|
||||
*/
|
||||
export interface SearchSetupMessage {
|
||||
type: SearchMessageType.SETUP /* Message type */
|
||||
data: SearchIndex /* Message data */
|
||||
data: SearchIndexOptions /* Message data */
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -20,7 +20,7 @@
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
import { Search } from "modules"
|
||||
import { SearchIndex } from "modules"
|
||||
|
||||
import { SearchMessage, SearchMessageType } from "../_"
|
||||
|
||||
@ -31,7 +31,7 @@ import { SearchMessage, SearchMessageType } from "../_"
|
||||
/**
|
||||
* Search index
|
||||
*/
|
||||
let index: Search
|
||||
let index: SearchIndex
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Functions
|
||||
@ -49,7 +49,7 @@ export function handler(message: SearchMessage): SearchMessage {
|
||||
|
||||
/* Setup search index */
|
||||
case SearchMessageType.SETUP:
|
||||
index = new Search(message.data)
|
||||
index = new SearchIndex(message.data)
|
||||
return {
|
||||
type: SearchMessageType.DUMP,
|
||||
data: index.toString()
|
||||
|
@ -118,6 +118,11 @@ $md-toggle__drawer--checked:
|
||||
margin-left: initial;
|
||||
transform: translate(100%, 0);
|
||||
}
|
||||
|
||||
// Ensure smooth scrolling on iOS
|
||||
.md-sidebar__scrollwrap {
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
}
|
||||
|
||||
// [screen +]: Limit to grid
|
||||
|
@ -82,7 +82,14 @@ function config(args: Configuration): Configuration {
|
||||
},
|
||||
|
||||
/* Source maps */
|
||||
devtool: "source-map"
|
||||
devtool: "source-map",
|
||||
|
||||
/* Filter false positives */
|
||||
stats: {
|
||||
warningsFilter: [
|
||||
/export '.*' was not found in/
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -96,7 +103,7 @@ function config(args: Configuration): Configuration {
|
||||
* @param env - Webpack environment arguments
|
||||
* @param args - Command-line arguments
|
||||
*
|
||||
* @return Webpack configuration
|
||||
* @return Webpack configurations
|
||||
*/
|
||||
export default (_env: never, args: Configuration): Configuration[] => ([
|
||||
|
||||
@ -117,7 +124,7 @@ export default (_env: never, args: Configuration): Configuration[] => ([
|
||||
entry: "src/assets/javascripts/workers/search/main",
|
||||
output: {
|
||||
path: path.resolve(__dirname, "material/assets/javascripts"),
|
||||
filename: "search.js",
|
||||
filename: "worker/search.js",
|
||||
libraryTarget: "var"
|
||||
}
|
||||
},
|
||||
@ -128,7 +135,7 @@ export default (_env: never, args: Configuration): Configuration[] => ([
|
||||
entry: "src/assets/javascripts/workers/packer/main",
|
||||
output: {
|
||||
path: path.resolve(__dirname, "material/assets/javascripts"),
|
||||
filename: "packer.js",
|
||||
filename: "worker/packer.js",
|
||||
libraryTarget: "var"
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user