refactor: use js for find
parent
5e93038023
commit
59707cda58
|
@ -65,6 +65,7 @@ def htmlOutput (result : AnalyzerResult) (root : String) : IO Unit := do
|
||||||
let config := { root := root, result := result, currentName := none, sourceLinker := ←sourceLinker}
|
let config := { root := root, result := result, currentName := none, sourceLinker := ←sourceLinker}
|
||||||
let basePath := FilePath.mk "." / "build" / "doc"
|
let basePath := FilePath.mk "." / "build" / "doc"
|
||||||
let indexHtml := ReaderT.run index config
|
let indexHtml := ReaderT.run index config
|
||||||
|
let findHtml := ReaderT.run find config
|
||||||
let notFoundHtml := ReaderT.run notFound config
|
let notFoundHtml := ReaderT.run notFound config
|
||||||
FS.createDirAll basePath
|
FS.createDirAll basePath
|
||||||
FS.createDirAll (basePath / "find")
|
FS.createDirAll (basePath / "find")
|
||||||
|
@ -72,12 +73,12 @@ def htmlOutput (result : AnalyzerResult) (root : String) : IO Unit := do
|
||||||
let mut declList := #[]
|
let mut declList := #[]
|
||||||
for (_, mod) in result.moduleInfo.toArray do
|
for (_, mod) in result.moduleInfo.toArray do
|
||||||
for decl in filterMapDocInfo mod.members do
|
for decl in filterMapDocInfo mod.members do
|
||||||
let findHtml := ReaderT.run (findRedirectHtml decl.getName) config
|
let name := decl.getName.toString
|
||||||
let findDir := basePath / "find" / decl.getName.toString
|
let description := decl.getDocString.getD ""
|
||||||
FS.createDirAll findDir
|
let link := Id.run <| ReaderT.run (declNameToLink decl.getName) config
|
||||||
FS.writeFile (findDir / "index.html") findHtml.toString
|
let obj := Json.mkObj [("name", name), ("description", description), ("link", link)]
|
||||||
let obj := Json.mkObj [("name", decl.getName.toString), ("description", decl.getDocString.getD "")]
|
|
||||||
declList := declList.push obj
|
declList := declList.push obj
|
||||||
|
|
||||||
let json := Json.arr declList
|
let json := Json.arr declList
|
||||||
|
|
||||||
FS.writeFile (basePath / "searchable_data.bmp") json.compress
|
FS.writeFile (basePath / "searchable_data.bmp") json.compress
|
||||||
|
@ -88,6 +89,11 @@ def htmlOutput (result : AnalyzerResult) (root : String) : IO Unit := do
|
||||||
FS.writeFile (basePath / "search.js") searchJs
|
FS.writeFile (basePath / "search.js") searchJs
|
||||||
FS.writeFile (basePath / "mathjax-config.js") mathjaxConfigJs
|
FS.writeFile (basePath / "mathjax-config.js") mathjaxConfigJs
|
||||||
FS.writeFile (basePath / "site-root.js") s!"export const SITE_ROOT = \"{config.root}\";";
|
FS.writeFile (basePath / "site-root.js") s!"export const SITE_ROOT = \"{config.root}\";";
|
||||||
|
|
||||||
|
FS.writeFile (basePath / "find" / "index.html") findHtml.toString
|
||||||
|
FS.writeFile (basePath / "find" / "find.js") findJs
|
||||||
|
|
||||||
|
|
||||||
for (module, content) in result.moduleInfo.toArray do
|
for (module, content) in result.moduleInfo.toArray do
|
||||||
let moduleHtml := ReaderT.run (moduleToHtml content) config
|
let moduleHtml := ReaderT.run (moduleToHtml content) config
|
||||||
let path := moduleNameToFile basePath module
|
let path := moduleNameToFile basePath module
|
||||||
|
|
|
@ -49,6 +49,7 @@ section Static
|
||||||
def styleCss : String := include_str "./static/style.css"
|
def styleCss : String := include_str "./static/style.css"
|
||||||
def navJs : String := include_str "./static/nav.js"
|
def navJs : String := include_str "./static/nav.js"
|
||||||
def searchJs : String := include_str "./static/search.js"
|
def searchJs : String := include_str "./static/search.js"
|
||||||
|
def findJs : String := include_str "./static/find/find.js"
|
||||||
def mathjaxConfigJs : String := include_str "./static/mathjax-config.js"
|
def mathjaxConfigJs : String := include_str "./static/mathjax-config.js"
|
||||||
end Static
|
end Static
|
||||||
|
|
||||||
|
|
|
@ -6,10 +6,16 @@ namespace Output
|
||||||
open scoped DocGen4.Jsx
|
open scoped DocGen4.Jsx
|
||||||
open Lean
|
open Lean
|
||||||
|
|
||||||
def findRedirectHtml (decl : Name) : HtmlM Html := do
|
def find : HtmlM Html := do
|
||||||
let res ← getResult
|
pure
|
||||||
let url ← declNameToLink decl
|
<html lang="en">
|
||||||
let contentString := s!"0;url={url}"
|
<head>
|
||||||
pure $ Html.element "meta" false #[("http-equiv", "refresh"), ("content", contentString)] #[]
|
<link rel="preload" href={s!"{←getRoot}searchable_data.bmp"}/>
|
||||||
|
<script type="module" async="true" src={s!"./find.js"}></script>
|
||||||
|
</head>
|
||||||
|
<body></body>
|
||||||
|
</html>
|
||||||
|
|
||||||
end Output
|
end Output
|
||||||
end DocGen4
|
end DocGen4
|
||||||
|
|
||||||
|
|
|
@ -26,13 +26,11 @@ def baseHtmlArray (title : String) (site : Array Html) : HtmlM Html := do
|
||||||
<link rel="shortcut icon" href={s!"{←getRoot}favicon.ico"}/>
|
<link rel="shortcut icon" href={s!"{←getRoot}favicon.ico"}/>
|
||||||
<link rel="prefetch" href={s!"{←getRoot}searchable_data.bmp"}/>
|
<link rel="prefetch" href={s!"{←getRoot}searchable_data.bmp"}/>
|
||||||
|
|
||||||
<script type="module" src={s!"{←getRoot}site-root.js"}></script>
|
|
||||||
<script type="module" src={s!"{←getRoot}nav.js"}></script>
|
|
||||||
<script type="module" src={s!"{←getRoot}search.js"}></script>
|
|
||||||
|
|
||||||
<script defer="true" src={s!"{←getRoot}mathjax-config.js"}></script>
|
<script defer="true" src={s!"{←getRoot}mathjax-config.js"}></script>
|
||||||
<script defer="true" src="https://polyfill.io/v3/polyfill.min.js?features=es6"></script>
|
<script defer="true" src="https://polyfill.io/v3/polyfill.min.js?features=es6"></script>
|
||||||
<script defer="true" src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
|
<script defer="true" src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
|
||||||
|
|
||||||
|
<script type="module" src={s!"{←getRoot}nav.js"}></script>
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
import { SITE_ROOT } from "../site-root.js";
|
||||||
|
import { declSearch } from "../search.js";
|
||||||
|
|
||||||
|
let splits = window.location.href.split("#");
|
||||||
|
|
||||||
|
if (splits.length < 2) {
|
||||||
|
window.location.replace(`${SITE_ROOT}/404.html`);
|
||||||
|
}
|
||||||
|
|
||||||
|
declSearch(splits[1]).then((results) => {
|
||||||
|
window.location.replace(results[0].link);
|
||||||
|
}).catch(() => {
|
||||||
|
window.location.replace(`${SITE_ROOT}404.html`);
|
||||||
|
});
|
|
@ -1,5 +1,4 @@
|
||||||
import { SITE_ROOT } from "./site-root.js";
|
import { declSearch } from "./search.js";
|
||||||
import { loadDecls, getMatches } from "./search.js";
|
|
||||||
|
|
||||||
// Persistent expansion cookie for the file tree
|
// Persistent expansion cookie for the file tree
|
||||||
// ---------------------------------------------
|
// ---------------------------------------------
|
||||||
|
@ -109,24 +108,6 @@ if (tse != null) {
|
||||||
// Simple declaration search
|
// Simple declaration search
|
||||||
// -------------------------
|
// -------------------------
|
||||||
|
|
||||||
const declURL = new URL(`${SITE_ROOT}searchable_data.bmp`, window.location);
|
|
||||||
const getDecls = (() => {
|
|
||||||
let decls;
|
|
||||||
return () => {
|
|
||||||
if (!decls) decls = new Promise((resolve, reject) => {
|
|
||||||
const req = new XMLHttpRequest();
|
|
||||||
req.responseType = 'json';
|
|
||||||
req.addEventListener('load', () => resolve(loadDecls(req.response)));
|
|
||||||
req.addEventListener('error', () => reject());
|
|
||||||
req.open('GET', declURL);
|
|
||||||
req.send();
|
|
||||||
})
|
|
||||||
return decls;
|
|
||||||
}
|
|
||||||
})()
|
|
||||||
|
|
||||||
const declSearch = async (q) => getMatches(await getDecls(), q);
|
|
||||||
|
|
||||||
const srId = 'search_results';
|
const srId = 'search_results';
|
||||||
document.getElementById('search_form')
|
document.getElementById('search_form')
|
||||||
.appendChild(document.createElement('div'))
|
.appendChild(document.createElement('div'))
|
||||||
|
@ -191,11 +172,11 @@ searchInput.addEventListener('input', async (ev) => {
|
||||||
|
|
||||||
const oldSR = document.getElementById('search_results');
|
const oldSR = document.getElementById('search_results');
|
||||||
const sr = oldSR.cloneNode(false);
|
const sr = oldSR.cloneNode(false);
|
||||||
for (const {decl} of result) {
|
for (const {decl, link} of result) {
|
||||||
const d = sr.appendChild(document.createElement('a'));
|
const d = sr.appendChild(document.createElement('a'));
|
||||||
d.innerText = decl;
|
d.innerText = decl;
|
||||||
d.title = decl;
|
d.title = decl;
|
||||||
d.href = `${SITE_ROOT}find/${decl}`;
|
d.href = link;
|
||||||
}
|
}
|
||||||
sr.setAttribute('state', 'done');
|
sr.setAttribute('state', 'done');
|
||||||
oldSR.replaceWith(sr);
|
oldSR.replaceWith(sr);
|
||||||
|
@ -222,10 +203,10 @@ if (howabout) {
|
||||||
declSearch(query).then((results) => {
|
declSearch(query).then((results) => {
|
||||||
howabout.innerText = 'How about one of these instead:';
|
howabout.innerText = 'How about one of these instead:';
|
||||||
const ul = howabout.appendChild(document.createElement('ul'));
|
const ul = howabout.appendChild(document.createElement('ul'));
|
||||||
for (const {decl} of results) {
|
for (const {decl, link} of results) {
|
||||||
const li = ul.appendChild(document.createElement('li'));
|
const li = ul.appendChild(document.createElement('li'));
|
||||||
const a = li.appendChild(document.createElement('a'));
|
const a = li.appendChild(document.createElement('a'));
|
||||||
a.href = `${SITE_ROOT}find/${decl}`;
|
a.href = link;
|
||||||
a.appendChild(document.createElement('code')).innerText = decl;
|
a.appendChild(document.createElement('code')).innerText = decl;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
import { SITE_ROOT } from "./site-root.js";
|
||||||
|
|
||||||
function isSep(c) {
|
function isSep(c) {
|
||||||
return c === '.' || c === '_';
|
return c === '.' || c === '_';
|
||||||
}
|
}
|
||||||
|
@ -23,14 +25,14 @@ function matchCaseSensitive(declName, lowerDeclName, pat) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function loadDecls(searchableDataCnt) {
|
export function loadDecls(searchableDataCnt) {
|
||||||
return searchableDataCnt.map(({name, description}) => [name, name.toLowerCase(), description.toLowerCase()])
|
return searchableDataCnt.map(({name, description, link}) => [name, name.toLowerCase(), description.toLowerCase(), link]);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getMatches(decls, pat, maxResults = 30) {
|
export function getMatches(decls, pat, maxResults = 30) {
|
||||||
const lowerPats = pat.toLowerCase().split(/\s/g);
|
const lowerPats = pat.toLowerCase().split(/\s/g);
|
||||||
const patNoSpaces = pat.replace(/\s/g, '');
|
const patNoSpaces = pat.replace(/\s/g, '');
|
||||||
const results = [];
|
const results = [];
|
||||||
for (const [decl, lowerDecl, lowerDoc] of decls) {
|
for (const [decl, lowerDecl, lowerDoc, link] of decls) {
|
||||||
let err = matchCaseSensitive(decl, lowerDecl, patNoSpaces);
|
let err = matchCaseSensitive(decl, lowerDecl, patNoSpaces);
|
||||||
|
|
||||||
// match all words as substrings of docstring
|
// match all words as substrings of docstring
|
||||||
|
@ -39,8 +41,27 @@ export function getMatches(decls, pat, maxResults = 30) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (err !== undefined) {
|
if (err !== undefined) {
|
||||||
results.push({decl, err});
|
results.push({decl, err, link});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return results.sort(({err: a}, {err: b}) => a - b).slice(0, maxResults);
|
return results.sort(({err: a}, {err: b}) => a - b).slice(0, maxResults);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const declURL = new URL(`${SITE_ROOT}searchable_data.bmp`, window.location);
|
||||||
|
|
||||||
|
export const getDecls = (() => {
|
||||||
|
let decls;
|
||||||
|
return () => {
|
||||||
|
if (!decls) decls = new Promise((resolve, reject) => {
|
||||||
|
const req = new XMLHttpRequest();
|
||||||
|
req.responseType = 'json';
|
||||||
|
req.addEventListener('load', () => resolve(loadDecls(req.response)));
|
||||||
|
req.addEventListener('error', () => reject());
|
||||||
|
req.open('GET', declURL);
|
||||||
|
req.send();
|
||||||
|
})
|
||||||
|
return decls;
|
||||||
|
}
|
||||||
|
})()
|
||||||
|
|
||||||
|
export const declSearch = async (q) => getMatches(await getDecls(), q);
|
Loading…
Reference in New Issue