Initiate repository from existing material
|
@ -0,0 +1,23 @@
|
|||
*~
|
||||
*.swp
|
||||
|
||||
deprec
|
||||
export
|
||||
|
||||
venv_*
|
||||
|
||||
todo.org
|
||||
src/ltximg
|
||||
|
||||
*.pdf
|
||||
*.aux
|
||||
*.bbl
|
||||
*.blg
|
||||
*.idx
|
||||
*.log
|
||||
*.out
|
||||
*.toc
|
||||
|
||||
src/index.html
|
||||
src/index.pdf
|
||||
src/index.tex
|
|
@ -0,0 +1,5 @@
|
|||
|
||||
* 2023
|
||||
** 06
|
||||
*** 05 Initiated repository
|
||||
Set up the repo starting from existing material.
|
|
@ -0,0 +1,296 @@
|
|||
|
||||
/* body { */
|
||||
/* margin: 1rem; */
|
||||
/* padding: 1rem; */
|
||||
/* } */
|
||||
|
||||
html {
|
||||
padding: 4rem;
|
||||
}
|
||||
body{
|
||||
margin: 1rem auto;
|
||||
max-width: 60rem;
|
||||
line-height: 1.4;
|
||||
font-size: 1.1rem;
|
||||
color: #222;
|
||||
padding: 0 1rem;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.title {
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
/* Table of contents */
|
||||
nav#collapsed-table-of-contents {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
nav#collapsed-table-of-contents details {
|
||||
background-color: #e8e8e8;
|
||||
border: none;
|
||||
margin: 0.5rem;
|
||||
}
|
||||
nav#collapsed-table-of-contents details summary {
|
||||
padding: 0.5rem;
|
||||
}
|
||||
nav#collapsed-table-of-contents > details > summary { /* bigger padding for main toc */
|
||||
padding: 1rem;
|
||||
}
|
||||
nav#collapsed-table-of-contents details ul {
|
||||
list-style: none;
|
||||
margin: 0.5rem;
|
||||
padding: 0;
|
||||
}
|
||||
nav#collapsed-table-of-contents details > ul > li {
|
||||
margin: 0.5rem;
|
||||
}
|
||||
nav#collapsed-table-of-contents details > ul > li > a {
|
||||
margin: 0.5rem 1rem;
|
||||
}
|
||||
nav#collapsed-table-of-contents details > ul > li.toc-open {
|
||||
background-color: #c0e8d0;
|
||||
}
|
||||
nav#collapsed-table-of-contents details > ul > li.toc-currentpage {
|
||||
background-color: #a0e0b0;
|
||||
}
|
||||
nav#collapsed-table-of-contents details[open] {
|
||||
border: 1px solid gray;
|
||||
}
|
||||
nav#collapsed-table-of-contents details[open] > summary {
|
||||
background-color: #d0d0d0;
|
||||
}
|
||||
nav#collapsed-table-of-contents details > summary:hover {
|
||||
background-color: #d8d8d8;
|
||||
}
|
||||
nav#collapsed-table-of-contents details > summary.toc-open {
|
||||
background-color: #d0e8d0;
|
||||
}
|
||||
nav#collapsed-table-of-contents details > summary.toc-currentpage {
|
||||
background-color: #a0e0b0;
|
||||
}
|
||||
|
||||
div#text-table-of-contents ul {
|
||||
margin: 0;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
|
||||
/* DEPREC Navbar */
|
||||
div.navbar {
|
||||
list-style: none;
|
||||
}
|
||||
div.navbar li {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
|
||||
/* Breadcrumbs */
|
||||
ul.breadcrumbs {
|
||||
font-size: 70%;
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
}
|
||||
ul.breadcrumbs > li {
|
||||
display: inline;
|
||||
margin-right: 0.3rem;
|
||||
}
|
||||
ul.breadcrumbs > li+li:before {
|
||||
content: "/\00a0";
|
||||
}
|
||||
|
||||
ul.navigation-links {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
}
|
||||
ul.navigation-links > li {
|
||||
font-size: 70%;
|
||||
display: inline-block;
|
||||
margin-right: 1rem;
|
||||
}
|
||||
ul.navigation-links > li {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
table th, table td {
|
||||
padding: 0.5rem;
|
||||
}
|
||||
|
||||
/* HTML5-specific tags */
|
||||
|
||||
aside {
|
||||
width: 40%;
|
||||
padding-left: .5rem;
|
||||
margin-left: .5rem;
|
||||
float: right;
|
||||
box-shadow: inset 5px 0 5px -5px #29627e;
|
||||
font-style: italic;
|
||||
color: #29627e;
|
||||
}
|
||||
|
||||
aside > p {
|
||||
margin: .5rem;
|
||||
}
|
||||
|
||||
details {
|
||||
border: 1px solid gray;
|
||||
margin: 1rem;
|
||||
padding: 0rem;
|
||||
clear: both;
|
||||
}
|
||||
summary {
|
||||
padding: 1rem;
|
||||
}
|
||||
details[open] > p, ul {
|
||||
margin-left: 1rem;
|
||||
margin-right: 1rem;
|
||||
margin: 1rem;
|
||||
}
|
||||
|
||||
|
||||
/* Preformatted code blocks */
|
||||
pre {
|
||||
border-radius: .3rem;
|
||||
background-color: #f2efe4;
|
||||
padding: .5rem;
|
||||
}
|
||||
|
||||
|
||||
/* rank-based container classes */
|
||||
.rant {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
|
||||
/* Environment-specific styles */
|
||||
|
||||
.prereq {
|
||||
background-color: rgba(191, 0, 0, 0.2);
|
||||
}
|
||||
.objectives {
|
||||
background-color: rgba(191, 191, 255, 0.6);
|
||||
}
|
||||
.core {
|
||||
background-color: rgba(191, 255, 191, 0.4);
|
||||
}
|
||||
.derivation {
|
||||
background-color: rgba(191, 255, 191, 0.2);
|
||||
}
|
||||
.example {
|
||||
background-color: rgba(255, 255, 191, 0.6);
|
||||
}
|
||||
.info {
|
||||
background-color: rgba(159, 255, 255, 0.4);
|
||||
}
|
||||
.context {
|
||||
background-color: rgba(191, 223, 255, 0.6);
|
||||
}
|
||||
|
||||
/* when details are open, darken summary */
|
||||
details[open].prereq > summary {
|
||||
background-color: rgba(191, 0, 0, 0.1);
|
||||
}
|
||||
details[open].objectives > summary {
|
||||
background-color: rgba(191, 191, 255, 0.6);
|
||||
}
|
||||
details[open].core > summary {
|
||||
background-color: rgba(191, 255, 191, 0.4);
|
||||
}
|
||||
details[open].derivation > summary {
|
||||
background-color: rgba(191, 255, 191, 0.2);
|
||||
}
|
||||
details[open].example > summary {
|
||||
background-color: rgba(255, 255, 191, 0.6);
|
||||
}
|
||||
details[open].info > summary {
|
||||
background-color: rgba(159, 255, 255, 0.4);
|
||||
}
|
||||
details[open].context > summary {
|
||||
background-color: rgba(191, 223, 255, 0.6);
|
||||
}
|
||||
|
||||
|
||||
/* Permalinks to sections */
|
||||
a.headline-permalink, span.headline-id {
|
||||
float: right;
|
||||
margin-right: 1rem;
|
||||
font-size: 70%;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/* when contextual colors are used for a div */
|
||||
div.prereq, div.objectives, div.core, div.derivation, div.example, div.info, div.context {
|
||||
margin: 1rem;
|
||||
padding: 1rem;
|
||||
padding-bottom: 1.5rem; /* to fit the alteqlabels inside colored box */
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
/* Giving equation nrs from other sources: use aside element */
|
||||
/* aside.alteqlabels { */
|
||||
/* box-shadow: none; /\* remove standard aside property *\/ */
|
||||
/* color: gray; */
|
||||
/* font-size: 50%; */
|
||||
/* width: 10%; */
|
||||
/* } */
|
||||
/* aside.alteqlabels > ul { */
|
||||
/* list-style: none; */
|
||||
/* } */
|
||||
|
||||
ul.altsecnrs {
|
||||
color: gray;
|
||||
font-size: 60%;
|
||||
float: right;
|
||||
/* clear: both; */
|
||||
list-style: none;
|
||||
margin-top: -1rem;
|
||||
padding-top: 0;
|
||||
}
|
||||
ul.altsecnrs > li {
|
||||
display: inline-block;
|
||||
}
|
||||
ul.altsecnrs > li:not(:first-child)::before {
|
||||
content: '/';
|
||||
margin-right: 0.2rem;
|
||||
}
|
||||
|
||||
div.eqlabel {
|
||||
float: right;
|
||||
clear: both;
|
||||
position: relative;
|
||||
z-index: 10;
|
||||
}
|
||||
div.eqlabel p {
|
||||
margin: 0;
|
||||
margin-left: 1rem;
|
||||
}
|
||||
|
||||
div.alteqlabels {
|
||||
color: gray;
|
||||
font-size: 60%;
|
||||
float: right;
|
||||
clear: both;
|
||||
}
|
||||
div.alteqlabels > ul {
|
||||
list-style: none;
|
||||
margin-left: 1rem;
|
||||
padding: 0;
|
||||
}
|
||||
/* div.alteqlabels p { */
|
||||
/* float: right; */
|
||||
/* clear: both; */
|
||||
/* } */
|
||||
|
||||
|
||||
/* Equations */
|
||||
/* .eq-permalink { */
|
||||
/* float: right; */
|
||||
/* } */
|
||||
|
||||
|
||||
div.license {
|
||||
font-size: 60%;
|
||||
}
|
||||
|
||||
.figs2 img {
|
||||
width: 100%;
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
* The Bethe Ansatz
|
||||
|
||||
Source files for the [[https://integrability.org][integrability.org]] presenting a collection of online resources on the Bethe Ansatz and related concepts used in the study of integrable models of quantum mechanics.
|
|
@ -0,0 +1,112 @@
|
|||
#! /usr/bin/env python
|
||||
|
||||
import os
|
||||
from lxml.html import parse, etree, tostring
|
||||
|
||||
link_svg = """<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-link" viewBox="0 0 16 16">
|
||||
<path d="M6.354 5.5H4a3 3 0 0 0 0 6h3a3 3 0 0 0 2.83-4H9c-.086 0-.17.01-.25.031A2 2 0 0 1 7 10.5H4a2 2 0 1 1 0-4h1.535c.218-.376.495-.714.82-1z"/>
|
||||
<path d="M9 5.5a3 3 0 0 0-2.83 4h1.098A2 2 0 0 1 9 6.5h3a2 2 0 1 1 0 4h-1.535a4.02 4.02 0 0 1-.82 1H12a3 3 0 1 0 0-6H9z"/>
|
||||
</svg>"""
|
||||
|
||||
|
||||
os.chdir('export/html')
|
||||
filenames = [f.rpartition('.html')[0] for f in os.listdir() if f.endswith('html')]
|
||||
|
||||
# Build dictionary of which dedicated links and headline links (by filename)
|
||||
dl = {}
|
||||
hl = {}
|
||||
cl = {}
|
||||
for filename in filenames:
|
||||
dl[filename] = []
|
||||
hl[filename] = []
|
||||
tree = parse(f'{filename}.html')
|
||||
for el in tree.iter():
|
||||
# find all dedicated links, which are of form 'a id="..."'
|
||||
# (they are the only links with and id)
|
||||
if (el.tag == 'a' and 'id' in el.attrib):
|
||||
# #and el.attrib['id'].partition(':')[0] in filenames):
|
||||
#and el.attrib['id'].partition(':')[0] == 'eq'):
|
||||
# raise flag if id coincides with a filename:
|
||||
if el.attrib['id'] in filenames:
|
||||
print("** Error: dedicated link name clashes with "
|
||||
f"headline CUSTOM_ID {el.attrib['id']} **")
|
||||
# raise flag if this key already exists:
|
||||
if el.attrib['id'] in dl[filename]:
|
||||
print(f"** Error: multiply-defined label {el.attrib['id']} **")
|
||||
else: # add this dedicated link to our dictionary
|
||||
dl[filename].append(el.attrib['id'])
|
||||
# find the headline links, which are of form '<h[2-6] id="...">'
|
||||
if (el.tag in ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'] and 'id' in el.attrib):
|
||||
if el.attrib['id'] in hl[filename]:
|
||||
print("** Error: multiply-defined headline {el.attrib['id']} **")
|
||||
else:
|
||||
hl[filename].append({
|
||||
'tag': el.tag,
|
||||
'id': el.attrib['id'],
|
||||
'text': el[0].text # el[0] is the a tag (only child)
|
||||
})
|
||||
# find all the child section links inside `<ul class="child-link-list">`
|
||||
# and are of the form `<li><a href="....html">`
|
||||
# if (el.tag == 'ul' and 'class' in el.attrib and
|
||||
# el.attrib['class'] == 'child-link-list'):
|
||||
# for c in el:
|
||||
# cl[c[0].attrib['href'].partition('.')[0] ] =
|
||||
|
||||
|
||||
# Perform all substitutions
|
||||
for filename in filenames:
|
||||
with open(f'{filename}.html', 'r') as file:
|
||||
content = file.read()
|
||||
# cleanup any stray type in script tags coming from old-fashioned org export
|
||||
content = content.replace('style type="text/css"', 'style ')
|
||||
content = content.replace('script type="text/javascript"', 'script ')
|
||||
# remove validation link if present
|
||||
content = content.replace('<a href="https://validator.w3.org/check?uri=referer">Validate</a>', '')
|
||||
# section link substitutions
|
||||
for val in filenames:
|
||||
content = content.replace(
|
||||
# link directly to the headline at `#{val}` even if it's top-level
|
||||
# f'a href="#{val}"', f'a href="./{val}.html#{val}"')
|
||||
f'href="#{val}"', f'href="./{val}.html#{val}"')
|
||||
# equation link substitutions
|
||||
for key, vals in dl.items():
|
||||
for val in vals:
|
||||
#print('Replacing ', f'href="#{val}"', ' by ', f'href="./{key}.html#{val}')
|
||||
content = content.replace(f'href="#{val}"', f'href="./{key}.html#{val}"')
|
||||
# add permalinks
|
||||
content = content.replace(
|
||||
f'<a id="{val}"></a>',
|
||||
f'<a id="{val}"></a><a href="./{key}.html#{val}">{link_svg}</a>'
|
||||
)
|
||||
# add permalinks to headlines
|
||||
for key, vals in hl.items():
|
||||
for val in vals:
|
||||
el_tag = val['tag']
|
||||
el_id = val['id']
|
||||
el_text = val['text']
|
||||
content = content.replace(
|
||||
(f'<{el_tag} id="{el_id}">'
|
||||
f'<a href="./{key}.html#{el_id}">{el_text}</a></{el_tag}>'),
|
||||
(f'<{el_tag} id="{el_id}">{el_text}'
|
||||
f'<a class="headline-permalink" href="./{key}.html#{el_id}">'
|
||||
f'{link_svg}</a>'
|
||||
f'<span class="headline-id">{el_id.replace("_",".")}</span>'
|
||||
f'</{el_tag}>')
|
||||
)
|
||||
# add section ids to all `child-link-list`s
|
||||
content = content.replace(
|
||||
f'<li><a href="{el_id}.html">{el_text}</a></li>',
|
||||
(f'<li><a href="{el_id}.html">{el_text}</a>'
|
||||
f'<span class="headline-id">'
|
||||
f'{el_id.replace("_",".")}</span></li>')
|
||||
)
|
||||
# add section ids to items in the toc
|
||||
content = content.replace(
|
||||
f'<a class="toc-a" href="./{key}.html#{el_id}">{el_text}</a>',
|
||||
(f'<a class="toc-a" href="./{key}.html#{el_id}">{el_text}</a>'
|
||||
f'<span class="headline-id">'
|
||||
f'{el_id.replace("_",".")}</span>')
|
||||
)
|
||||
# rewrite file
|
||||
with open(f'{filename}.html', 'w') as outfile:
|
||||
outfile.write(content)
|
|
@ -0,0 +1,23 @@
|
|||
#! /bin/sh
|
||||
|
||||
BASEDIR="."
|
||||
|
||||
mkdir -p $BASEDIR/export/html
|
||||
rm -rf $BASEDIR/export/html/*
|
||||
|
||||
# Single-page version
|
||||
echo 'Creating single-page version...'
|
||||
mkdir -p $BASEDIR/export/html/singlepage
|
||||
cp $BASEDIR/src/org/index.html $BASEDIR/export/html/singlepage/index.html
|
||||
cp $BASEDIR/css/style.css $BASEDIR/export/html/singlepage/style.css
|
||||
cp -r $BASEDIR/src/fig $BASEDIR/export/html/singlepage/
|
||||
|
||||
# Split version
|
||||
echo 'Creating split pages...'
|
||||
cp $BASEDIR/css/style.css $BASEDIR/export/html/style.css
|
||||
cp -r $BASEDIR/src/fig $BASEDIR/export/html/
|
||||
echo 'Exporting split html...'
|
||||
$BASEDIR/scripts/export_split.py
|
||||
echo 'Repairing links...'
|
||||
$BASEDIR/scripts/cleanup_links.py
|
||||
echo 'All done.'
|
|
@ -0,0 +1,319 @@
|
|||
#! /usr/bin/env python
|
||||
|
||||
import os
|
||||
from lxml.html import parse, etree, tostring
|
||||
|
||||
copyright_string = """
|
||||
<div class="license">
|
||||
<a rel="license noopener" href="https://creativecommons.org/licenses/by/4.0/"
|
||||
target="_blank" class="m-2">
|
||||
<img alt="Creative Commons License" style="border-width:0"
|
||||
src="https://licensebuttons.net/l/by/4.0/80x15.png"/>
|
||||
</a>
|
||||
Except where otherwise noted, all content is licensed under a
|
||||
<a rel="license noopener" href="https://creativecommons.org/licenses/by/4.0/"
|
||||
target="_blank">Creative Commons Attribution 4.0 International License</a>.
|
||||
</div>
|
||||
"""
|
||||
|
||||
BASEDIR = "./"
|
||||
SRCDIR = f"{BASEDIR}src/org/"
|
||||
|
||||
tree = parse(f"{SRCDIR}index.html")
|
||||
|
||||
el_head = None
|
||||
el_header = None
|
||||
el_title = None
|
||||
el_nav = None
|
||||
el_ttoc = None
|
||||
el_content = None
|
||||
el_postamble = None
|
||||
|
||||
sections_2 = []
|
||||
|
||||
for el in tree.iter():
|
||||
if el.tag == 'head':
|
||||
el_head = el
|
||||
if el.tag == 'header':
|
||||
el_header = el
|
||||
if 'class' in el.attrib and el.attrib['class'] == 'title':
|
||||
el_title = el
|
||||
if el.tag == 'nav':
|
||||
el_nav = el
|
||||
if 'id' in el.attrib and el.attrib['id'] == 'text-table-of-contents':
|
||||
el_ttoc = el
|
||||
if 'id' in el.attrib and el.attrib['id'] == 'content':
|
||||
el_content = el
|
||||
if 'id' in el.attrib and el.attrib['id'] == 'postamble':
|
||||
el_postamble = el
|
||||
if 'class' in el.attrib and el.attrib['class'].startswith('outline-2'):
|
||||
sections_2.append(el)
|
||||
|
||||
export_dir = f"{BASEDIR}export/html"
|
||||
if not os.path.isdir(export_dir):
|
||||
os.makedirs(export_dir)
|
||||
|
||||
|
||||
def ordered_pages(el):
|
||||
"""
|
||||
Creates a list of all pages, able to return previous, next and up links.
|
||||
|
||||
`el` should be the text-table-of-contents element.
|
||||
"""
|
||||
page_ids = []
|
||||
page_texts = []
|
||||
for child in el.iter():
|
||||
if child.tag == 'a':
|
||||
page_ids.append(child.attrib['href'].lstrip('#'))
|
||||
page_texts.append(child.text)
|
||||
return page_ids, page_texts
|
||||
|
||||
page_ids, page_texts = ordered_pages(el_ttoc)
|
||||
|
||||
def head_at_location(el_head, page_id):
|
||||
output = tostring(el_head, pretty_print=True, encoding='unicode')
|
||||
try:
|
||||
index = page_ids.index(page_id)
|
||||
except ValueError:
|
||||
return output
|
||||
if index == 0:
|
||||
return output
|
||||
return output.replace(
|
||||
'</title>',
|
||||
f': {page_texts[index]}</title>'
|
||||
)
|
||||
|
||||
def breadcrumbs(page_id):
|
||||
try:
|
||||
index = page_ids.index(page_id)
|
||||
except ValueError:
|
||||
return ''
|
||||
if index == 0: # mains page, no need for breadcrumbs
|
||||
return ''
|
||||
breadcrumb_lis = f'<li>{page_texts[index]}</li>'
|
||||
# If book or article, take shortcut
|
||||
if page_id.startswith("b-"): # this is a book
|
||||
page_id_stripped = "l_b"
|
||||
elif page_id[:4].isdigit(): # this is an article
|
||||
page_id_stripped = f"l_a_{page_id[:4]}"
|
||||
else:
|
||||
page_id_stripped = page_ids[index].rpartition('_')[0]
|
||||
while page_id_stripped:
|
||||
index_stripped = page_ids.index(page_id_stripped)
|
||||
breadcrumb_lis = (
|
||||
# give class to link to prevent auto addition of ids from cleanup_links script
|
||||
'<li><a class="breadcrumb-link"' +
|
||||
f'href="{page_ids[index_stripped]}.html">' +
|
||||
f'{page_texts[index_stripped]}</a></li>'
|
||||
+ breadcrumb_lis)
|
||||
page_id_stripped = page_id_stripped.rpartition('_')[0]
|
||||
return f'<ul class="breadcrumbs">{breadcrumb_lis}</ul>'
|
||||
|
||||
def link_previous(page_id):
|
||||
try:
|
||||
index = page_ids.index(page_id)
|
||||
except ValueError:
|
||||
return None
|
||||
if index == 0: # first, no previous
|
||||
return None
|
||||
# If depth is 1, there is no previous
|
||||
if page_id.count('_') == 0:
|
||||
return None
|
||||
else:
|
||||
return f'<a href="{page_ids[index-1]}.html">{page_texts[index-1]} <small>[{page_ids[index-1].replace("_",".")}]</small></a>'
|
||||
|
||||
def link_next(page_id):
|
||||
try:
|
||||
index = page_ids.index(page_id)
|
||||
except ValueError:
|
||||
return None
|
||||
if index == len(page_ids) - 1: # last, no next
|
||||
return None
|
||||
return f'<a href="{page_ids[index+1]}.html">{page_texts[index+1]} <small>[{page_ids[index+1].replace("_",".")}]</small></a>'
|
||||
|
||||
def link_up(page_id):
|
||||
try:
|
||||
index = page_ids.index(page_id)
|
||||
except ValueError:
|
||||
return None
|
||||
# Strip one '_' from id and point there
|
||||
if page_id.count('_') > 0:
|
||||
index_up = page_ids.index(page_id.rpartition('_')[0])
|
||||
return f'<a href="{page_ids[index_up]}.html">{page_texts[index_up]} <small>[{page_ids[index_up].replace("_",".")}]</small></a>'
|
||||
return None
|
||||
|
||||
def navigation_links(location):
|
||||
links = '<ul class="navigation-links">'
|
||||
previous = link_previous(location)
|
||||
if previous:
|
||||
links += f'<li>Prev: {previous}</li>'
|
||||
nxt = link_next(location)
|
||||
if nxt:
|
||||
links += f'<li>Next: {nxt}</li>'
|
||||
up = link_up(location)
|
||||
if up:
|
||||
links += f'<li>Up: {up}</li>'
|
||||
links += '</ul>'
|
||||
if previous or nxt or up:
|
||||
return links
|
||||
return ''
|
||||
|
||||
def search_box():
|
||||
return """
|
||||
<form style="float: right; padding-right: 0;" method="get" id="search" action="https://duckduckgo.com/" target="_blank">
|
||||
<input type="hidden" name="sites" value="integrability.org"/>
|
||||
<input class="search" type="text" name="q" maxlength="300" placeholder="Search"/>
|
||||
<input type="submit" value="Search" style="visibility: hidden; width: 0;" /></form>
|
||||
"""
|
||||
|
||||
def list_to_details_recursive(el):
|
||||
"""
|
||||
`el` contains either a single `a` child, or an `a` followed by `ul`.
|
||||
In the first case, output as is.
|
||||
In the second case, replace by details/summary.
|
||||
"""
|
||||
# checks
|
||||
if not (len(el) == 1 or len(el) == 2):
|
||||
raise ValueError(f'el must have either 1 or 2 children, found {len(el)}')
|
||||
if not el[0].tag in ['a', 'ul']:
|
||||
raise ValueError(f'el[0] must be an a or ul tag, but found a {el[0].tag}')
|
||||
if len(el) == 2 and not (el[0].tag == 'a' and el[1].tag == 'ul'):
|
||||
raise ValueError(f'for len(el) == 2, el[1] must be ul, but found {el[1].tag}')
|
||||
# single child, output as is
|
||||
if len(el) == 1 and el[0].tag == 'a':
|
||||
output = tostring(el[0], pretty_print=True, encoding='unicode')
|
||||
else: # build a details/summary
|
||||
summary_text = (
|
||||
'Table of contents' + search_box() if len(el) == 1 else
|
||||
tostring(el[0], pretty_print=True, encoding='unicode')
|
||||
)
|
||||
ul = el[0] if len(el) == 1 else el[1]
|
||||
# print(f'summary_text: {summary_text}')
|
||||
# print(f'len(ul): {len(ul)}')
|
||||
# print([li.tag for li in ul])
|
||||
# print([tostring(li, pretty_print=True, encoding='unicode') for li in ul])
|
||||
output = ('\n<details>'
|
||||
f'\n<summary>\n{summary_text}'
|
||||
'\n</summary>\n<ul>\n')
|
||||
for li in ul:
|
||||
if not li.tag == 'li':
|
||||
raise ValueError('child of ul should be li')
|
||||
output += '<li>\n'
|
||||
output += list_to_details_recursive(li)
|
||||
output += '\n</li>\n'
|
||||
output += '\n</ul>\n</details>'
|
||||
return output
|
||||
|
||||
|
||||
|
||||
collapsed_toc = '\n<nav id="collapsed-table-of-contents">'
|
||||
collapsed_toc += list_to_details_recursive(el_ttoc)
|
||||
collapsed_toc += '\n</nav>\n'
|
||||
|
||||
|
||||
def toc_at_location(collapsed_toc, location):
|
||||
"""
|
||||
Given a collapsed toc and location (filename),
|
||||
mark the details hierarchy as open.
|
||||
"""
|
||||
output = collapsed_toc
|
||||
if location != 'index':
|
||||
# open all ancestors
|
||||
prefix = location.rpartition('_')[0]
|
||||
while prefix:
|
||||
output = output.replace(
|
||||
f'<details>\n<summary>\n<a href="#{prefix}"',
|
||||
f'<details open="">\n<summary class="toc-open">\n<a href="#{prefix}"')
|
||||
prefix = prefix.rpartition('_')[0]
|
||||
# highlight the current location, whether it's a summary or a
|
||||
output = output.replace(
|
||||
f'<details>\n<summary>\n<a href="#{location}"',
|
||||
f'<details open="">\n<summary class="toc-currentpage">\n<a href="#{location}"'
|
||||
)
|
||||
output = output.replace(
|
||||
f'<li>\n<a href="#{location}"',
|
||||
f'<li class="toc-currentpage">\n<a href="#{location}"'
|
||||
)
|
||||
# but close all details which contain deeper levels than location
|
||||
output = output.replace(
|
||||
f'<details open="">\n<summary>\n<a href="#{location}_',
|
||||
f'<details>\n<summary>\n<a href="#{location}_')
|
||||
return output.replace('<a href', '<a class="toc-a" href')
|
||||
|
||||
def write_file_start(_file, location):
|
||||
_file.write('<!DOCTYPE html>\n<html lang="en">\n')
|
||||
_file.write(head_at_location(el_head, location))
|
||||
_file.write('<div id="content">\n')
|
||||
#_file.write(tostring(el_header, pretty_print=True, encoding='unicode'))
|
||||
_file.write('<header>\n<h1 class="title">\n'
|
||||
'<a href="./index.html" class="homepage-link">')
|
||||
_file.write(f'{el_title.text}</a>\n</h1>\n</header>')
|
||||
_file.write(toc_at_location(collapsed_toc, location))
|
||||
_file.write(breadcrumbs(location))
|
||||
_file.write(navigation_links(location))
|
||||
|
||||
def write_file_end(_file, location):
|
||||
_file.write('\n<br>')
|
||||
_file.write(navigation_links(location)) # repeat, for convenience
|
||||
_file.write('\n<br>')
|
||||
_file.write('\n<hr>')
|
||||
_file.write(copyright_string)
|
||||
_file.write(tostring(el_postamble, pretty_print=True, encoding='unicode'))
|
||||
_file.write('\n</div>\n</html>')
|
||||
|
||||
|
||||
def write_files_recursive(name, el, levelmax=5):
|
||||
"""
|
||||
Recursively extract outlines.
|
||||
"""
|
||||
if 'id' in el.attrib and el.attrib['id'] == 'content':
|
||||
level = 1
|
||||
elif not (el is not None and
|
||||
'class' in el.attrib and
|
||||
el.attrib['class'].startswith('outline-')):
|
||||
print(f'Element name {name} has no outline class, no files written.')
|
||||
return
|
||||
else:
|
||||
level = int(el.attrib['class'].partition('outline-')[2][0])
|
||||
|
||||
_file = open(f'{BASEDIR}export/html/{name}.html', 'w')
|
||||
write_file_start(_file, name)
|
||||
|
||||
# Count outline children for establishing output format
|
||||
children = []
|
||||
for child in el.iter():
|
||||
if ('class' in child.attrib and
|
||||
child.attrib['class'].startswith('outline-%s' % str(level + 1))):
|
||||
children.append(child)
|
||||
|
||||
# if no children or if we're on levelmax, write everything
|
||||
if (len(children) == 0 or level == levelmax):
|
||||
_file.write(tostring(el, pretty_print=True, encoding='unicode'))
|
||||
# otherwise write anything above first next-level headling,
|
||||
# and then replace the next-level headlines by links to their files
|
||||
else:
|
||||
if (el.text):
|
||||
_file.write(el.text)
|
||||
for child in el:
|
||||
if ('class' in child.attrib and
|
||||
child.attrib['class'].startswith('outline-%s' % str(level + 1))):
|
||||
break # break out once we hit the first next-level headline
|
||||
if child.tag != "nav": # don't write the table-of-contents
|
||||
_file.write(tostring(child, pretty_print=True, encoding='unicode'))
|
||||
# now print the list of children
|
||||
_file.write(f'<h{level+1}>In this section:</h{level+1}>')
|
||||
_file.write('\n<ul class="child-links-list">')
|
||||
for child in children:
|
||||
child_h = next(child.iter('h%s' % int(level + 1)))
|
||||
child_label = child_h.attrib['id']
|
||||
child_text = next(child_h.iter('a')).text
|
||||
_file.write(f'\n<li><a href="{child_label}.html">{child_text}</a></li>')
|
||||
write_files_recursive(name=child_label, el=child)
|
||||
_file.write('\n</ul>\n')
|
||||
|
||||
write_file_end(_file, name)
|
||||
_file.close()
|
||||
|
||||
|
||||
# Rewrite the index.html file:
|
||||
write_files_recursive('index', el_content) # the only call needed
|
|
@ -0,0 +1,90 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
entries = {}
|
||||
|
||||
outfile = open("../lit/papers.org", "w")
|
||||
|
||||
|
||||
def org_entry(bibtex_entry_text, bibtex_entry_dict):
|
||||
if {
|
||||
"key", "author", "title", "journal", "volume", "pages", "year", "doi",
|
||||
} <= bibtex_entry_dict.keys():
|
||||
b = {}
|
||||
b["key"] = bibtex_entry_dict["key"].replace("_", ".")
|
||||
b["author"] = bibtex_entry_dict["author"]
|
||||
b["title"] = bibtex_entry_dict["title"]
|
||||
b["journal"] = bibtex_entry_dict["journal"]
|
||||
b["volume"] = bibtex_entry_dict["volume"]
|
||||
b["pages"] = bibtex_entry_dict["pages"]
|
||||
b["year"] = bibtex_entry_dict["year"]
|
||||
b["doi"] = bibtex_entry_dict["doi"]
|
||||
b_text = bibtex_entry_text.replace(bibtex_entry_dict["key"], b["key"])
|
||||
return (
|
||||
f"""
|
||||
|
||||
**** {b["key"]}
|
||||
:PROPERTIES:
|
||||
:CUSTOM_ID: {b["key"]}
|
||||
:END:
|
||||
|
||||
{b["author"]},
|
||||
/{b["title"]}/,
|
||||
{b["journal"]} **{b["volume"]}**, {b["pages"]} ({b["year"]}), doi:[[https://doi.org/{b["doi"]}][{b["doi"]}]].
|
||||
|
||||
| <20> | <60> |
|
||||
| Extended data | |
|
||||
|------------------+------|
|
||||
| Author | {b["author"]} |
|
||||
| Title | {b["title"]} |
|
||||
| Journal | {b["journal"]} |
|
||||
| Volume | {b["volume"]} |
|
||||
| Pages | {b["pages"]} |
|
||||
| Year | {b["year"]} |
|
||||
| doi | [[https://doi.org/{b["doi"]}][{b["doi"]}]] |
|
||||
| Publication date | |
|
||||
|------------------+------|
|
||||
| Submission date | |
|
||||
""" + """
|
||||
#+begin_details
|
||||
#+begin_summary
|
||||
#+html: BibTeX
|
||||
#+end_summary
|
||||
#+begin_src bibtex
|
||||
""" + f"{b_text}" + """
|
||||
#+end_src
|
||||
#+end_details
|
||||
|
||||
#+attr_html: :open true
|
||||
#+begin_details
|
||||
#+begin_summary
|
||||
#+html: Annotations
|
||||
#+end_summary
|
||||
#+end_details
|
||||
|
||||
|
||||
"""
|
||||
)
|
||||
else:
|
||||
return ""
|
||||
|
||||
|
||||
with open("../lit/papers.bib", errors="ignore") as infile:
|
||||
while line := infile.readline():
|
||||
if "@article" in line.lower():
|
||||
bibtex_entry = line
|
||||
key = line.partition("{")[2].rstrip(",\n")
|
||||
entries[key] = {}
|
||||
entries[key]["key"] = key
|
||||
while line := infile.readline():
|
||||
bibtex_entry += line
|
||||
if line.startswith("}"):
|
||||
break
|
||||
field, _, value = line.partition("=")
|
||||
field = field.strip()
|
||||
value = value.strip().removesuffix(",")
|
||||
if value.startswith("{{") and value.endswith("}}"):
|
||||
value = value.removeprefix("{{").removesuffix("}}")
|
||||
value = value.removeprefix("{").removesuffix("}")
|
||||
value = value.removeprefix('"').removesuffix('"')
|
||||
entries[key][field] = value
|
||||
outfile.write(org_entry(bibtex_entry, entries[key]))
|
|
@ -0,0 +1,21 @@
|
|||
#!/bin/sh
|
||||
|
||||
ba_export_html_dir='/home/jscaux/work/writing/lecture_notes/Bethe_Ansatz/export/html/'
|
||||
ba_html_build_dir='/home/jscaux/work/writing/lecture_notes/Bethe_Ansatz_html/build/'
|
||||
|
||||
cd $ba_html_build_dir
|
||||
|
||||
cp -r $ba_export_html_dir* $ba_html_build_dir
|
||||
|
||||
# remove files which don't exist anymore
|
||||
for file in $(ls -R)
|
||||
do
|
||||
if ! [ -f $BA_export_html_dir$file ]
|
||||
then
|
||||
rm $file
|
||||
fi
|
||||
done
|
||||
|
||||
echo 'Committing'
|
||||
msg='Update '$(date +"%F %R")
|
||||
git commit -a -m "$msg"
|
|
@ -0,0 +1,3 @@
|
|||
#! /bin/bash
|
||||
|
||||
rsync -avhPz --delete export/html/ jscaux@opal6.opalstack.com:apps/integrability
|
After Width: | Height: | Size: 53 KiB |
After Width: | Height: | Size: 68 KiB |
After Width: | Height: | Size: 70 KiB |
After Width: | Height: | Size: 54 KiB |
After Width: | Height: | Size: 59 KiB |
After Width: | Height: | Size: 67 KiB |
After Width: | Height: | Size: 42 KiB |
After Width: | Height: | Size: 42 KiB |
After Width: | Height: | Size: 51 KiB |
After Width: | Height: | Size: 70 KiB |
After Width: | Height: | Size: 66 KiB |
|
@ -0,0 +1,4 @@
|
|||
# #+OPTIONS: num:nil // uncomment to remove section numbering
|
||||
#+OPTIONS: toc:4
|
||||
|
||||
#+AUTHOR: Jean-Sébastien Caux
|