Compare commits
5 Commits
b9404c206c
...
5c5f6ab89d
Author | SHA1 | Date | |
---|---|---|---|
5c5f6ab89d
|
|||
ab618e77c1
|
|||
2f4ba8bba2
|
|||
117f1ee6ee
|
|||
a5341e770c
|
1
Makefile
1
Makefile
@@ -6,6 +6,7 @@ install:
|
|||||||
cp styles.css /opt/notes2web
|
cp styles.css /opt/notes2web
|
||||||
cp fuse.js /opt/notes2web
|
cp fuse.js /opt/notes2web
|
||||||
cp search.js /opt/notes2web
|
cp search.js /opt/notes2web
|
||||||
|
cp toc_search.js /opt/notes2web
|
||||||
|
|
||||||
uninstall:
|
uninstall:
|
||||||
rm -rf /usr/local/bin/notes2web.py /opt/notes2web
|
rm -rf /usr/local/bin/notes2web.py /opt/notes2web
|
||||||
|
@@ -116,6 +116,7 @@ def get_args():
|
|||||||
parser.add_argument('-F', '--force', action="store_true", help="Generate new output html even if source file was modified before output html")
|
parser.add_argument('-F', '--force', action="store_true", help="Generate new output html even if source file was modified before output html")
|
||||||
parser.add_argument('--fuse', type=pathlib.Path, default=pathlib.Path('/opt/notes2web/fuse.js'))
|
parser.add_argument('--fuse', type=pathlib.Path, default=pathlib.Path('/opt/notes2web/fuse.js'))
|
||||||
parser.add_argument('--searchjs', type=pathlib.Path, default=pathlib.Path('/opt/notes2web/search.js'))
|
parser.add_argument('--searchjs', type=pathlib.Path, default=pathlib.Path('/opt/notes2web/search.js'))
|
||||||
|
parser.add_argument('--tocsearchjs', type=pathlib.Path, default=pathlib.Path('/opt/notes2web/toc_search.js'))
|
||||||
return parser.parse_args()
|
return parser.parse_args()
|
||||||
|
|
||||||
|
|
||||||
@@ -331,11 +332,11 @@ def main(args):
|
|||||||
|
|
||||||
for entry in indexentries:
|
for entry in indexentries:
|
||||||
html += (
|
html += (
|
||||||
'<div class="article">'
|
'<li class="article">'
|
||||||
f'<a href="{entry["path"]}">'
|
f'<a href="{entry["path"]}">'
|
||||||
f'{entry["title"]}{"/" if entry["isdirectory"] else ""}'
|
f'{entry["title"]}{"/" if entry["isdirectory"] else ""}'
|
||||||
'</a>'
|
'</a>'
|
||||||
'</div>'
|
'</li>'
|
||||||
)
|
)
|
||||||
html += INDEX_TEMPLATE_FOOT
|
html += INDEX_TEMPLATE_FOOT
|
||||||
|
|
||||||
@@ -345,6 +346,7 @@ def main(args):
|
|||||||
shutil.copyfile(args.stylesheet, args.output_dir.joinpath('styles.css'))
|
shutil.copyfile(args.stylesheet, args.output_dir.joinpath('styles.css'))
|
||||||
shutil.copyfile(args.fuse, args.output_dir.joinpath('fuse.js'))
|
shutil.copyfile(args.fuse, args.output_dir.joinpath('fuse.js'))
|
||||||
shutil.copyfile(args.searchjs, args.output_dir.joinpath('search.js'))
|
shutil.copyfile(args.searchjs, args.output_dir.joinpath('search.js'))
|
||||||
|
shutil.copyfile(args.tocsearchjs, args.output_dir.joinpath('toc_search.js'))
|
||||||
with open(args.output_dir.joinpath('index.html'), 'w+') as fp:
|
with open(args.output_dir.joinpath('index.html'), 'w+') as fp:
|
||||||
with open(args.home_index) as fp2:
|
with open(args.home_index) as fp2:
|
||||||
html = re.sub(r'\$title\$', args.output_dir.parts[0], fp2.read())
|
html = re.sub(r'\$title\$', args.output_dir.parts[0], fp2.read())
|
||||||
|
BIN
screenshot.png
BIN
screenshot.png
Binary file not shown.
Before Width: | Height: | Size: 163 KiB After Width: | Height: | Size: 340 KiB |
@@ -7,15 +7,15 @@ const fuse = new Fuse(data, {
|
|||||||
keys: [
|
keys: [
|
||||||
{
|
{
|
||||||
name: HEADERS,
|
name: HEADERS,
|
||||||
weight: 1
|
weight: 2
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: PATH,
|
name: PATH,
|
||||||
weight: 1
|
weight: 0.5
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: TAGS,
|
name: TAGS,
|
||||||
weight: 1
|
weight: 1.5
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: TITLE,
|
name: TITLE,
|
||||||
|
89
styles.css
89
styles.css
@@ -1,5 +1,15 @@
|
|||||||
@import url("https://alv.cx/styles.css");
|
@import url("https://alv.cx/styles.css");
|
||||||
|
|
||||||
|
html {
|
||||||
|
scroll-behavior: smooth;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
max-width: none;
|
||||||
|
margin: none;
|
||||||
|
padding: none;
|
||||||
|
}
|
||||||
|
|
||||||
.article {
|
.article {
|
||||||
margin: 1em;
|
margin: 1em;
|
||||||
}
|
}
|
||||||
@@ -15,7 +25,13 @@
|
|||||||
display: flex
|
display: flex
|
||||||
}
|
}
|
||||||
|
|
||||||
#search { flex-grow: 9 }
|
#search { flex-grow: 9; }
|
||||||
|
|
||||||
|
#sidebar #search {
|
||||||
|
flex-grow: 0;
|
||||||
|
padding: 1em;
|
||||||
|
margin: 0 1em 1em 1em;
|
||||||
|
}
|
||||||
|
|
||||||
#results {
|
#results {
|
||||||
overflow-x: scroll;
|
overflow-x: scroll;
|
||||||
@@ -33,9 +49,78 @@
|
|||||||
background-color: #86c1b9;
|
background-color: #86c1b9;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#sidebar > #header { padding-bottom: 1em; color: #656565;}
|
||||||
|
|
||||||
#header > * {
|
#header > * {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#contentWrapper {
|
||||||
|
display: flex
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#sidebar {
|
||||||
|
position: sticky;
|
||||||
|
top: 10vh;
|
||||||
|
height: 80vh;
|
||||||
|
max-width: 30em;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
min-width: 20em;
|
||||||
|
padding-right: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#toc {
|
||||||
|
overflow-y: scroll;
|
||||||
|
overflow-x: visible;
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
li {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#content {
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 1em;
|
||||||
|
max-width: 60em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#commitlog, #license { padding: 0; }
|
||||||
|
|
||||||
|
#sidebar,
|
||||||
|
#toc li > a {
|
||||||
|
color: #656565;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul#articlelist li a { color: #454545 }
|
||||||
|
|
||||||
|
#toc li, ul#articlelist { list-style: none; }
|
||||||
|
#toc ul, ul#articlelist { margin-left: 0.75em ; padding-left: 0.75em; }
|
||||||
|
#toc ul, ul#articlelist { border-left: 1px solid #b3b3b3;}
|
||||||
|
#toc > ul { padding; none; padding: 0; margin: 0; border: none;max-width: 100%;}
|
||||||
|
|
||||||
|
#toc li > a,
|
||||||
|
ul#articlelist li a {
|
||||||
|
text-decoration: none;
|
||||||
|
display: inline-block;
|
||||||
|
width: 100%;
|
||||||
|
transition: 0.5s;
|
||||||
|
padding: 0.5em;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
#toc li > a:hover,
|
||||||
|
ul#articlelist li a:hover {
|
||||||
|
background: #d9d9d9;
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 60em) {
|
||||||
|
/* CSS that should be displayed if width is equal to or less than 60em goes here */
|
||||||
|
#contentWrapper { flex-direction: column }
|
||||||
|
#sidebar { position: static; width: 100%; max-width: none; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -9,40 +9,45 @@
|
|||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div id="header">
|
<div id="contentWrapper">
|
||||||
<p class="smallText"> tags: [
|
<div id="sidebar">
|
||||||
$for(tags)$
|
<div id="header">
|
||||||
<a href="/.tags/$tags$.html">$tags$</a>$sep$,
|
<p class="smallText"> tags: [
|
||||||
$endfor$
|
$for(tags)$
|
||||||
]</p>
|
<a href="/.tags/$tags$.html">$tags$</a>$sep$,
|
||||||
<p class="smallText">
|
$endfor$
|
||||||
written by $for(author)$$author$$sep$, $endfor$
|
]</p>
|
||||||
</p>
|
<p class="smallText">
|
||||||
<p class="smallText">
|
written by $for(author)$$author$$sep$, $endfor$
|
||||||
syntax highlighting based on <a href="https://pygments.org/">Pygments'</a> default
|
</p>
|
||||||
colors
|
<p class="smallText">
|
||||||
</p>
|
syntax highlighting based on <a href="https://pygments.org/">Pygments'</a> default
|
||||||
<p class="smallText">
|
colors
|
||||||
page generated by <a href="https://git.alv.cx/alvierahman90/notes2web">notes2web</a>
|
</p>
|
||||||
</p>
|
<p class="smallText">
|
||||||
<details id="commitLog">
|
page generated by <a href="https://git.alv.cx/alvierahman90/notes2web">notes2web</a>
|
||||||
<summary class="smallText">
|
</p>
|
||||||
Commit log (file history)
|
</div>
|
||||||
</summary>
|
<h3>Table of Contents</h3>
|
||||||
$filehistory$
|
<input id="search" placeholder="Search table of contents" />
|
||||||
</details>
|
<div id="toc">$toc$</div>
|
||||||
<details>
|
</div>
|
||||||
<summary class="smallText">
|
<div id="content">
|
||||||
License
|
<details id="commitLog">
|
||||||
</summary>
|
<summary class="smallText">
|
||||||
<pre>$licenseFull$</pre>
|
Commit log (file history)
|
||||||
</details>
|
</summary>
|
||||||
<details>
|
$filehistory$
|
||||||
<summary class="smallText"> Table of Contents </summary>
|
</details>
|
||||||
<div>$toc$</div>
|
<details id="license">
|
||||||
</details>
|
<summary class="smallText">
|
||||||
</div>
|
License
|
||||||
<div id="content">
|
</summary>
|
||||||
$body$
|
<pre>$licenseFull$</pre>
|
||||||
|
</details>
|
||||||
|
$body$
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<script src="/fuse.js"> </script>
|
||||||
|
<script src="/toc_search.js"> </script>
|
||||||
</body>
|
</body>
|
||||||
|
@@ -6,6 +6,7 @@
|
|||||||
<title>$title$</title>
|
<title>$title$</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
<div id="content">
|
||||||
<h1>$h1title$</h1>
|
<h1>$h1title$</h1>
|
||||||
<p>
|
<p>
|
||||||
These are my personal notes. Correctness is not guaranteed.
|
These are my personal notes. Correctness is not guaranteed.
|
||||||
@@ -21,7 +22,7 @@ Browse <a href="/notes">here</a> or by tag <a href="/.tags">here</a>.
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p class="smallText"> page generated by <a href="https://github.com/alvierahman90/notes2web">notes2web</a></p>
|
<p class="smallText"> page generated by <a href="https://github.com/alvierahman90/notes2web">notes2web</a></p>
|
||||||
|
</div>
|
||||||
<script src="/fuse.js"> </script>
|
<script src="/fuse.js"> </script>
|
||||||
<script> const data = $data$ </script>
|
<script> const data = $data$ </script>
|
||||||
<script src="/search.js"> </script>
|
<script src="/search.js"> </script>
|
||||||
|
@@ -7,7 +7,8 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h1>$h1title$</h1>
|
<h1>$h1title$</h1>
|
||||||
|
<div id="content">
|
||||||
$body$
|
$body$
|
||||||
|
<p style="font-size: 0.7em;"> page generated by <a href="https://github.com/alvierahman90/notes2web">notes2web</a></p>
|
||||||
<p style="font-size: 0.7em;"> page generated by <a href="https://github.com/alvierahman90/notes2web">notes2web</a></p>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
@@ -1,2 +1,4 @@
|
|||||||
|
</ul>
|
||||||
<p style="font-size: 0.7em;"> page generated by <a href="https://github.com/alvierahman90/notes2web">notes2web</a></p>
|
<p style="font-size: 0.7em;"> page generated by <a href="https://github.com/alvierahman90/notes2web">notes2web</a></p>
|
||||||
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
@@ -7,6 +7,8 @@
|
|||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
<div id="content">
|
||||||
<h1>$title$</h1>
|
<h1>$title$</h1>
|
||||||
$extra_content$
|
$extra_content$
|
||||||
<div class="article"><a href="..">../</a></div>
|
<ul id="articlelist">
|
||||||
|
<li class="article"><a href="..">../</a></li>
|
||||||
|
@@ -1,2 +1,3 @@
|
|||||||
</pre>
|
</pre>
|
||||||
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
@@ -7,6 +7,7 @@
|
|||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
<div id="content">
|
||||||
<div id="header">
|
<div id="header">
|
||||||
<p class="smallText">
|
<p class="smallText">
|
||||||
page generated by <a href="https://git.alv.cx/alvierahman90/notes2web">notes2web</a>
|
page generated by <a href="https://git.alv.cx/alvierahman90/notes2web">notes2web</a>
|
||||||
|
94
toc_search.js
Normal file
94
toc_search.js
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
var raw_html_tree = document.getElementById('toc').firstChild.cloneNode(true);
|
||||||
|
|
||||||
|
function createSearchable(el) {
|
||||||
|
var par = el.parentElement;
|
||||||
|
var obj = el.cloneNode(true);
|
||||||
|
|
||||||
|
while(par != raw_html_tree) {
|
||||||
|
var clone_parent = par.cloneNode(true);
|
||||||
|
|
||||||
|
while (clone_parent.firstChild != clone_parent.lastChild) {
|
||||||
|
clone_parent.removeChild(clone_parent.lastChild);
|
||||||
|
}
|
||||||
|
console.log("obj.innerHTML: " + obj.innerHTML);
|
||||||
|
console.log("clone_parent.firstChild.innerHTML: " + clone_parent.firstChild.innerHTML);
|
||||||
|
if (obj.innerHTML != clone_parent.firstChild.innerHTML)
|
||||||
|
clone_parent.appendChild(obj);
|
||||||
|
|
||||||
|
obj = clone_parent;
|
||||||
|
par = par.parentElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
searchable: el.innerHTML,
|
||||||
|
obj: obj
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
var searchables = [];
|
||||||
|
Array(...raw_html_tree.getElementsByTagName('a'))
|
||||||
|
.forEach(el => searchables.push(createSearchable(el)));
|
||||||
|
|
||||||
|
var fuse = new Fuse(searchables, { keys: [ 'searchable' ], includeMatches: true});
|
||||||
|
var searchBar = document.getElementById('search');
|
||||||
|
var resultsDiv = document.getElementById('toc');
|
||||||
|
|
||||||
|
function updateResults() {
|
||||||
|
var ul = document.createElement('ul');
|
||||||
|
resultsDiv.innerHTML = '';
|
||||||
|
if (searchBar.value == '') {
|
||||||
|
resultsDiv.appendChild(raw_html_tree);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var results = fuse.search(searchBar.value);
|
||||||
|
|
||||||
|
|
||||||
|
results.forEach(r => {
|
||||||
|
console.log(r)
|
||||||
|
var content = r.item.obj
|
||||||
|
var last_a = Array.from(r.item.obj.getElementsByTagName('a')).pop()
|
||||||
|
|
||||||
|
r.matches.reverse().every(match => {
|
||||||
|
var display_match = match.value;
|
||||||
|
if (match.indices.length >= 1) {
|
||||||
|
match.indices.sort((a, b) => (b[1]-b[0])-(a[1]-a[0]));
|
||||||
|
const indexPair = match.indices[0];
|
||||||
|
const matching_slice = match.value.slice(indexPair[0], indexPair[1]+1);
|
||||||
|
last_a.innerHTML = match.value.replace(
|
||||||
|
matching_slice,
|
||||||
|
'<span class="matchHighlight">' + matching_slice + '</span>'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
})
|
||||||
|
|
||||||
|
ul.appendChild(content);
|
||||||
|
ul.appendChild(document.createElement('br'));
|
||||||
|
})
|
||||||
|
resultsDiv.appendChild(ul);
|
||||||
|
}
|
||||||
|
|
||||||
|
searchBar.addEventListener('keyup', e => {
|
||||||
|
// if user pressed enter
|
||||||
|
if (e.keyCode === 13) {
|
||||||
|
if (e.shiftKey) {
|
||||||
|
window.open(results[0].item.path, '_blank');
|
||||||
|
} else {
|
||||||
|
window.location.href = results[0].item.path;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
updateResults();
|
||||||
|
})
|
||||||
|
|
||||||
|
searchBar.addEventListener('change', updateResults);
|
||||||
|
|
||||||
|
const searchParams = new URL(window.location.href).searchParams;
|
||||||
|
searchBar.value = searchParams.get('q');
|
||||||
|
updateResults();
|
||||||
|
|
||||||
|
if (searchParams.has('lucky')) {
|
||||||
|
window.location.href = results[0].item.path;
|
||||||
|
}
|
Reference in New Issue
Block a user