Markdown Overview Buttons Tabs Footnotes Collapse ToC Navigation Formula Page-Specific Meta Custom Components
For this recipe, we're going to assume that we've got a nice search API that gives you a JSON array of URLs of matching documentation pages, based on a given query, and now we want to use it instead of the GitHub search for our docs.
We are assuming that the API, when requested with:
1link$curl https://my-search.cloud?q=whatever
would respond with something like:
1link${
2link$  "results": [
3link$    "https://johndoe.github.io/my-project/",
4link$    "https://johndoe.github.io/my-project/docs/stuff",
5link$    "https://johndoe.github.io/my-project/docs/whatever/overview"
6link$  ]
7link$}
Lets create a search component in .codedoc/content/my-search.tsx:
1linkimport { ajax } from 'rxjs/ajax';
2linkimport { Subject, of } from 'rxjs';
3linkimport { switchMap, map, catchError, share } from 'rxjs/operators';
4linkimport { RendererLike, ComponentThis } from '@connectv/html';
5linkimport { transport } from '@connectv/sdh/transport';
6linkimport { ToCSearchBtn } from '@codedoc/core/components';
7link
8link
9linkexport function MySearch(this: ComponentThis, options: SearchOptions, renderer: RendererLike<any, any>) {
10link  const query = new Subject();
11link  const prefix = 'https://johndoe.github.io/my-project';
12link
13link  const results = query.pipe(
14link    switchMap(q =>
15link      ajax.getJSON(
16link        `https://my-search.cloud?q=${encodeURIComponent(q)}`
17link      ).pipe(catchError(() => of(undefined)))       // --> no sweat in case of error
18link    ),
19link    map(res => 
20link      (res.results || [])
21link      .map(url => url.substr(prefix.length))        // --> returned URLs must be relative to domain root
22link    ),
23link    share(),
24link  );
25link
26link  return <ToCSearchBtn label="Search via my-search ..." query={query} results={results}/>;
27link}
28link
29link
30linkexport const MySearch$ = /*#__PURE__*/transport(MySearch);
touch_app NOTE
Note that although we have defined the component
MySearch, we also export a transported version of it namedMySearch$. The reason isMySearchis a client-side component, i.e. it should be rendered and bound on the browser. However, we want to feed it to the rest of our layout components on the server-side, i.e. when we are building the HTML files.MySearch$basically acts as a placeholder forMySearchin server-side code, allowing you to include it where you need it. When included, it will cause the code for the client-side component, i.e.MySearch, to be included in codedoc bundle, alongside an initialization script that would renderMySearchin place of the placeholder on the browser.
Now lets configure our ToC to use MySearch$ instead of the default GithubSearch$ component.
For that purpose, we just need to modify .codedoc/content/index.tsx:
1linkimport { RendererLike } from '@connectv/html';
2linkimport { File } from 'rxline/fs';
3linkimport { Page, Meta, ContentNav, Fonts, ToC } from '@codedoc/core/components';
4link
5linkimport { config } from '../config';
6linkimport { Header } from './header';
7linkimport { Footer } from './footer';
8linkimport { MySearch$ } from './my-search';            // --> import the component
9link
10link
11linkexport function content(_content: HTMLElement, toc: HTMLElement, renderer: RendererLike<any, any>, file: File<string>) {
12link  return (
13link    <Page title={config.page.title.extractor(_content, config, file)}
14link          favicon={config.page.favicon}
15link          meta={<Meta {...config.page.meta}/>}
16link          fonts={<Fonts {...config.page.fonts}/>}
17link
18link          scripts={config.page.scripts}
19link          stylesheets={config.page.stylesheets}
20link
21link          header={<Header {...config}/>}
22link          footer={<Footer {...config}/>}
23link          toc={
24link            <ToC search={<MySearch$/>}>{toc}</ToC>       // --> give it to ToC for search
25link          }>
26link      {_content}
27link      <ContentNav content={_content}/>
28link    </Page>
29link  )
30link}