Compare commits

...

14 Commits

7 changed files with 67 additions and 44 deletions

1
.gitignore vendored
View File

@ -2,3 +2,4 @@
env env
n n
web web
__pycache__

View File

@ -1,5 +1,6 @@
install: install:
cp notes2web.py n2w_add_uuid.py /usr/local/bin cp n2w_add_uuid.py /usr/local/bin
sed "s/N2W_COMMIT = \"\"/N2W_COMMIT = \"$$(git rev-parse --short HEAD)\"/" notes2web.py > /usr/local/bin/notes2web.py
pip3 install -r requirements.txt pip3 install -r requirements.txt
mkdir -p /opt/notes2web mkdir -p /opt/notes2web
cp -r templates /opt/notes2web cp -r templates /opt/notes2web

View File

@ -21,6 +21,8 @@ INDEX_TEMPLATE_FOOT = None
INDEX_TEMPLATE_HEAD = None INDEX_TEMPLATE_HEAD = None
EXTRA_INDEX_CONTENT = None EXTRA_INDEX_CONTENT = None
N2W_COMMIT = ""
def is_plaintext(filename): def is_plaintext(filename):
return re.match(r'^text/', magic.from_file(str(filename), mime=True)) is not None return re.match(r'^text/', magic.from_file(str(filename), mime=True)) is not None
@ -62,7 +64,16 @@ def get_inherited_tags(file, base_folder):
tags += folder_properties.get('itags') tags += folder_properties.get('itags')
print(f"get_inherited_tags {tags=}") print(f"get_inherited_tags {tags=}")
return tags return list(set(tags))
def git_head_sha1(working_dir):
git_response = subprocess.run(
[ 'git', f"--git-dir={working_dir.joinpath('.git')}", 'rev-parse', '--short', 'HEAD' ],
stdout=subprocess.PIPE
).stdout.decode('utf-8')
return git_response.strip()
def git_filehistory(working_dir, filename): def git_filehistory(working_dir, filename):
@ -201,7 +212,7 @@ def main(args):
# extract tags from frontmatter, save to tag_dict # extract tags from frontmatter, save to tag_dict
fm = frontmatter.load(filename) fm = frontmatter.load(filename)
if isinstance(fm.get('tags'), list): if isinstance(fm.get('tags'), list):
for tag in fm.get('tags') + get_inherited_tags(filename, args.notes): for tag in list(set(fm.get('tags') + get_inherited_tags(filename, args.notes))):
t = { t = {
'path': str(pathlib.Path(output_filename).relative_to(args.output_dir)), 'path': str(pathlib.Path(output_filename).relative_to(args.output_dir)),
'title': fm.get('title') or pathlib.Path(filename).name 'title': fm.get('title') or pathlib.Path(filename).name
@ -222,7 +233,7 @@ def main(args):
all_entries.append({ all_entries.append({
'path': '/' + str(pathlib.Path(*pathlib.Path(output_filename).parts[1:])), 'path': '/' + str(pathlib.Path(*pathlib.Path(output_filename).parts[1:])),
'title': fm.get('title') or pathlib.Path(filename).name, 'title': fm.get('title') or pathlib.Path(filename).name,
'tags': fm.get('tags'), 'tags': list(set(fm.get('tags'))),
'headers': header_lines, 'headers': header_lines,
'uuid': fm.get('uuid') 'uuid': fm.get('uuid')
}) })
@ -237,6 +248,7 @@ def main(args):
article = frontmatter.load(fp) article = frontmatter.load(fp)
article['tags'] += get_inherited_tags(filename, args.notes) article['tags'] += get_inherited_tags(filename, args.notes)
article['tags'] = sorted(list(set(article['tags'])))
article['filehistory'] = filehistory article['filehistory'] = filehistory
article['licenseFull'] = notes_license article['licenseFull'] = notes_license
html = pypandoc.convert_text(frontmatter.dumps(article), 'html', format='md', extra_args=[ html = pypandoc.convert_text(frontmatter.dumps(article), 'html', format='md', extra_args=[
@ -391,6 +403,8 @@ def main(args):
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())
html = re.sub(r'\$h1title\$', args.output_dir.parts[0], html) html = re.sub(r'\$h1title\$', args.output_dir.parts[0], html)
html = re.sub(r'\$n2w_commit\$', N2W_COMMIT, html)
html = re.sub(r'\$notes_git_head_sha1\$', git_head_sha1(args.notes), html)
html = re.sub(r'\$data\$', json.dumps(all_entries), html) html = re.sub(r'\$data\$', json.dumps(all_entries), html)

View File

@ -3,37 +3,51 @@ const PATH = "path"
const TAGS = "tags" const TAGS = "tags"
const TITLE = "title" const TITLE = "title"
const SEARCH_TIMEOUT_MS = 100
var SEARCH_TIMEOUT_ID = -1
const fuse = new Fuse(data, { const fuse = new Fuse(data, {
keys: [ keys: [
{ {
name: HEADERS, name: HEADERS,
weight: 1.5 weight: 0.2
}, },
{ {
name: PATH, name: PATH,
weight: 0.5 weight: 0.1
}, },
{ {
name: TAGS, name: TAGS,
weight: 1.5 weight: 0.1
}, },
{ {
name: TITLE, name: TITLE,
weight: 4 weight: 4
} }
], ],
includeMatches: true includeMatches: true,
useExtendedSearch: true,
ignoreLocation: true,
threshhold: 0.4,
}) })
const RESULTS_MAX = 5
const searchBar = document.getElementById('search') const searchBar = document.getElementById('search')
const resultsMax = document.getElementById('resultsMax')
const resultsDiv = document.getElementById('results') const resultsDiv = document.getElementById('results')
var results = [] var results = []
function updateResultsWithTimeout() {
console.log("clearing timeout")
if (SEARCH_TIMEOUT_ID) SEARCH_TIMEOUT_ID = clearTimeout(SEARCH_TIMEOUT_ID)
SEARCH_TIMEOUT_ID = setTimeout(updateResults, SEARCH_TIMEOUT_MS)
}
function updateResults() { function updateResults() {
console.log("updating results")
resultsDiv.innerHTML = '' resultsDiv.innerHTML = ''
results = fuse.search(searchBar.value).slice(0, parseInt(resultsMax.value)) results = fuse.search(searchBar.value, { limit: RESULTS_MAX })
results.forEach(r => { results.forEach(r => {
wrapper = document.createElement('div') wrapper = document.createElement('div')
wrapper.className = "article" wrapper.className = "article"
@ -95,12 +109,10 @@ searchBar.addEventListener('keyup', e => {
} }
return return
} }
updateResults() updateResultsWithTimeout()
}) })
searchBar.addEventListener('change', updateResults) searchBar.addEventListener('change', updateResultsWithTimeout)
resultsMax.addEventListener('keyup', updateResults)
resultsMax.addEventListener('change', updateResults)
const searchParams = new URL(window.location.href).searchParams; const searchParams = new URL(window.location.href).searchParams;
searchBar.value = searchParams.get('q'); searchBar.value = searchParams.get('q');

View File

@ -101,6 +101,8 @@ mjx-container {
overflow-x: auto; overflow-x: auto;
} }
p.metadata { margin: 0 }
@media (max-width: 80em) { @media (max-width: 80em) {
/* CSS that should be displayed if width is equal to or less than 60em goes here */ /* CSS that should be displayed if width is equal to or less than 60em goes here */
#contentWrapper { flex-direction: column } #contentWrapper { flex-direction: column }

View File

@ -17,34 +17,28 @@
<body> <body>
<div id="contentWrapper"> <div id="contentWrapper">
<div id="sidebar"> <div id="content">
<div id="header"> <p class="smallText metadata">
<p class="smallText"> title: $title$
<a href="/permalink?uuid=$uuid$">permalink</a>
</p> </p>
<p class="smallText"> tags: [ <p class="smallText metadata">
uuid: $uuid$ (<a href="/permalink?uuid=$uuid$">permalink</a>)
</p>
<p class="smallText metadata"> tags: [
$for(tags)$ $for(tags)$
<a href="/.tags/$tags$.html">$tags$</a>$sep$, <a href="/.tags/$tags$.html">$tags$</a>$sep$,
$endfor$ $endfor$
]</p> ]</p>
<p class="smallText"> <p class="smallText metadata">
written by $for(author)$$author$$sep$, $endfor$ written by $for(author)$$author$$sep$, $endfor$
</p> </p>
<p class="smallText"> <p class="smallText metadata">
syntax highlighting based on <a href="https://pygments.org/">Pygments'</a> default syntax highlighting based on <a href="https://pygments.org/">Pygments'</a> default
colors colors
</p> </p>
<p class="smallText"> <p class="smallText metadata">
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>
</p> </p>
</div>
<div id="tocWrapper" style="width: 100%" >
<h3>Table of Contents</h3>
<input id="search" width="100%" placeholder="Search table of contents" />
<div id="toc">$toc$</div>
</div>
</div>
<div id="content">
<details id="commitLog"> <details id="commitLog">
<summary class="smallText"> <summary class="smallText">
Commit log (file history) Commit log (file history)

View File

@ -14,14 +14,13 @@ Browse <a href="/notes">here</a> or by tag <a href="/.tags">here</a>.
</p> </p>
<div id="searchWrapper"> <div id="searchWrapper">
<input placeholder="Search" id="search" autofocus> <input autocomplete="off" placeholder="search" id="search" autofocus>
<input type="number" id="resultsMax" min="0" value="5">
</div> </div>
<p class="smallText" style="margin-top: 0; text-align: center;"> Press <kbd>Enter</kbd> to open first result or <kbd>Shift</kbd>+<kbd>Enter</kbd> to open in new tab</p> <p class="smallText" style="margin-top: 0; text-align: center;"> Press <kbd>Enter</kbd> to open first result or <kbd>Shift</kbd>+<kbd>Enter</kbd> to open in new tab</p>
<div id="results"> <div id="results">
</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> (commit $n2w_commit$) notes commit $notes_git_head_sha1$</p>
</div> </div>
<script src="/fuse.js"> </script> <script src="/fuse.js"> </script>
<script> const data = $data$ </script> <script> const data = $data$ </script>